Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@
## 1.0.0b2 (Unreleased)

### Features Added

* Added missing methods for Mapping API
* Made load method properties unordered.

### Breaking Changes
* Removed custom Key Vault Error
* Removed unneeded __repr__ and copy methods.

### Bugs Fixed

### Other Changes

* Updated method docs
* Fixed load doc that used `selector` instead of `selects`.
* Fixed CLI link in Readme.

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@


class AzureAppConfigurationKeyVaultOptions:

"""
Options for connecting to Key Vault.

Expand All @@ -16,11 +17,10 @@ class AzureAppConfigurationKeyVaultOptions:
provided.
:type secret_clients: list[~azure.keyvault.secrets.SecretClient]
:param secret_resolver: A function that takes a URI and returns a value.
:type secret_resolver: callable
:type secret_resolver: Callable[[str], str]
"""

def __init__(self, credential=None, secret_clients=None, secret_resolver=None):
# type: (TokenCredential, List[SecretClient], Callable) -> None
def __init__(self, *, credential=None, secret_clients=None, secret_resolver=None):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to use something like:

Suggested change
def __init__(self, *, credential=None, secret_clients=None, secret_resolver=None):
def __init__(self, *, credential: Optional[TokenCredential]=None, secret_clients: Optional[List[SecretClient]]=None, secret_resolver: Optional[Callable[[str], str]]=None):

?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is updated in the other PR as it changes to multiple @overloads

# type: (TokenCredential, List[SecretClient], Callable[[str], str]) -> None
self.credential = credential
self.secret_clients = secret_clients
self.secret_resolver = secret_resolver
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,18 @@
import json
from azure.appconfiguration import AzureAppConfigurationClient
from azure.keyvault.secrets import SecretClient, KeyVaultSecretIdentifier
from azure.core.exceptions import ResourceNotFoundError
from ._settingselector import SettingSelector
from ._azure_appconfiguration_provider_error import KeyVaultReferenceError
from ._constants import KEY_VAULT_REFERENCE_CONTENT_TYPE

from ._user_agent import USER_AGENT


class AzureAppConfigurationProvider:

"""
Provides a dictionary-like interface to Azure App Configuration settings. Enables loading of sets of configuration
settings from Azure App Configuration into a Python application. Enables trimming of prefixes from configuration
keys. Enables resolution of Key Vault references in configuration settings.
"""

def __init__(self):
# type: () -> None
self._dict = {}
Expand Down Expand Up @@ -130,19 +127,12 @@ def __resolve_keyvault_reference(config, key_vault_options, secret_clients):
secret_clients[key_vault_identifier.vault_url] = referenced_client

if referenced_client:
try:
return referenced_client.get_secret(
key_vault_identifier.name, version=key_vault_identifier.version
).value
except ResourceNotFoundError:
raise KeyVaultReferenceError(
"Key Vault %s does not contain secret %s"
% (key_vault_identifier.vault_url, key_vault_identifier.name)
)
return referenced_client.get_secret(key_vault_identifier.name, version=key_vault_identifier.version).value
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean we want to raise ResourceNotFoundError rather than wrapping it into KeyVaultReferenceError?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of the comments brought up in the review board meeting was that we shouldn't use the customer errors unless we really need one for something. So, yes in this case raise whatever error the SDK throws.


if key_vault_options.secret_resolver is not None:
return key_vault_options.secret_resolver(config.secret_id)
raise KeyVaultReferenceError(

raise AttributeError(
"No Secret Client found for Key Vault reference %s" % (key_vault_identifier.vault_url)
)

Expand All @@ -169,22 +159,18 @@ def __is_json_content_type(content_type):
return False

def __getitem__(self, key):
"""
Returns the value of the specified key.
type: (str) -> object
"""
return self._dict[key]

def __repr__(self):
return repr(self._dict)
def __iter__(self):
return self._dict.__iter__()

def __len__(self):
return len(self._dict)

def copy(self):
"""
Returns a copy of the configuration settings

type: () -> dict
"""
return self._dict.copy()

def __contains__(self, __x: object):
"""
Returns True if the configuration settings contains the specified key
Expand All @@ -201,6 +187,15 @@ def keys(self):
"""
return self._dict.keys()

def items(self):
"""
Returns a list of key-value pairs loaded from Azure App Configuration. Any values that are Key Vault references
will be resolved.

type: () -> list
"""
return self._dict.items()

def values(self):
"""
Returns a list of values loaded from Azure App Configuration. Any values that are Key Vault references will be
Expand All @@ -209,3 +204,25 @@ def values(self):
type: () -> list
"""
return self._dict.values()

def get(self, key, default=None):
"""
Returns the value of the specified key. If the key does not exist, returns the default value.

type: (str, object) -> object
"""
return self._dict.get(key, default)

def __eq__(self, other):
if not isinstance(other, AzureAppConfigurationProvider):
return False
if self._dict != other._dict:
return False
if self._trim_prefixes != other._trim_prefixes:
return False
if self._client != other._client:
return False
return True

def __ne__(self, other):
return not self == other