Skip to content

Commit 2037678

Browse files
authored
App Config Provider - Provider Refactor (#43196)
* Code Cleanup * Move validation to shared file * Updating Header Check * Update test_azureappconfigurationproviderbase.py * moved async tests to aio folder * post merge updates
1 parent 9a00094 commit 2037678

17 files changed

+317
-434
lines changed

sdk/appconfiguration/azure-appconfiguration-provider/assets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"AssetsRepo": "Azure/azure-sdk-assets",
33
"AssetsRepoPrefixPath": "python",
44
"TagPrefix": "python/appconfiguration/azure-appconfiguration-provider",
5-
"Tag": "python/appconfiguration/azure-appconfiguration-provider_b13d43b82a"
5+
"Tag": "python/appconfiguration/azure-appconfiguration-provider_ccc89e9eaa"
66
}

sdk/appconfiguration/azure-appconfiguration-provider/azure/appconfiguration/provider/_azureappconfigurationprovider.py

Lines changed: 19 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@
1414
overload,
1515
List,
1616
Tuple,
17-
TYPE_CHECKING,
1817
)
1918
from azure.appconfiguration import ( # type:ignore # pylint:disable=no-name-in-module
2019
ConfigurationSetting,
2120
FeatureFlagConfigurationSetting,
2221
SecretReferenceConfigurationSetting,
2322
)
23+
from azure.core.credentials import TokenCredential
2424
from azure.core.exceptions import AzureError, HttpResponseError
2525
from ._models import AzureAppConfigurationKeyVaultOptions, SettingSelector
2626
from ._key_vault._secret_provider import SecretProvider
@@ -30,16 +30,13 @@
3030
)
3131
from ._azureappconfigurationproviderbase import (
3232
AzureAppConfigurationProviderBase,
33-
update_correlation_context_header,
3433
delay_failure,
34+
process_load_parameters,
3535
sdk_allowed_kwargs,
3636
)
3737
from ._client_manager import ConfigurationClientManager, _ConfigurationClientWrapper as ConfigurationClient
3838
from ._user_agent import USER_AGENT
3939

40-
if TYPE_CHECKING:
41-
from azure.core.credentials import TokenCredential
42-
4340
JSON = Mapping[str, Any]
4441
logger = logging.getLogger(__name__)
4542

@@ -176,51 +173,19 @@ def load( # pylint: disable=docstring-keyword-should-match-keyword-only
176173

177174

178175
def load(*args, **kwargs) -> "AzureAppConfigurationProvider":
179-
endpoint: Optional[str] = kwargs.pop("endpoint", None)
180-
credential: Optional["TokenCredential"] = kwargs.pop("credential", None)
181-
connection_string: Optional[str] = kwargs.pop("connection_string", None)
182-
key_vault_options: Optional[AzureAppConfigurationKeyVaultOptions] = kwargs.pop("key_vault_options", None)
183176
start_time = datetime.datetime.now()
184177

185-
# Update endpoint and credential if specified positionally.
186-
if len(args) > 2:
187-
raise TypeError(
188-
"Unexpected positional parameters. Please pass either endpoint and credential, or a connection string."
189-
)
190-
if len(args) == 1:
191-
if endpoint is not None:
192-
raise TypeError("Received multiple values for parameter 'endpoint'.")
193-
endpoint = args[0]
194-
elif len(args) == 2:
195-
if credential is not None:
196-
raise TypeError("Received multiple values for parameter 'credential'.")
197-
endpoint, credential = args
198-
199-
if (endpoint or credential) and connection_string:
200-
raise ValueError("Please pass either endpoint and credential, or a connection string.")
201-
202-
# Removing use of AzureAppConfigurationKeyVaultOptions
203-
if key_vault_options:
204-
if "keyvault_credential" in kwargs or "secret_resolver" in kwargs or "keyvault_client_configs" in kwargs:
205-
raise ValueError(
206-
"Key Vault configurations should only be set by either the key_vault_options or kwargs not both."
207-
)
208-
kwargs["keyvault_credential"] = key_vault_options.credential
209-
kwargs["secret_resolver"] = key_vault_options.secret_resolver
210-
kwargs["keyvault_client_configs"] = key_vault_options.client_configs
211-
212-
if kwargs.get("keyvault_credential") is not None and kwargs.get("secret_resolver") is not None:
213-
raise ValueError("A keyvault credential and secret resolver can't both be configured.")
214-
215-
uses_key_vault = (
216-
"keyvault_credential" in kwargs
217-
or "keyvault_client_configs" in kwargs
218-
or "secret_resolver" in kwargs
219-
or kwargs.get("uses_key_vault", False)
220-
)
178+
# Process common load parameters using shared logic
179+
params = process_load_parameters(*args, **kwargs)
221180

222-
provider = _buildprovider(connection_string, endpoint, credential, uses_key_vault=uses_key_vault, **kwargs)
223-
kwargs = sdk_allowed_kwargs(kwargs)
181+
provider = _buildprovider(
182+
params["connection_string"],
183+
params["endpoint"],
184+
params["credential"],
185+
uses_key_vault=params["uses_key_vault"],
186+
**params["kwargs"],
187+
)
188+
kwargs = sdk_allowed_kwargs(params["kwargs"])
224189

225190
try:
226191
provider._load_all(**kwargs) # pylint:disable=protected-access
@@ -231,7 +196,7 @@ def load(*args, **kwargs) -> "AzureAppConfigurationProvider":
231196

232197

233198
def _buildprovider(
234-
connection_string: Optional[str], endpoint: Optional[str], credential: Optional["TokenCredential"], **kwargs
199+
connection_string: Optional[str], endpoint: Optional[str], credential: Optional[TokenCredential], **kwargs
235200
) -> "AzureAppConfigurationProvider":
236201
# pylint:disable=protected-access
237202
if connection_string:
@@ -254,7 +219,7 @@ class AzureAppConfigurationProvider(AzureAppConfigurationProviderBase): # pylin
254219
"""
255220

256221
def __init__(self, **kwargs: Any) -> None:
257-
super().__init__(**kwargs)
222+
super(AzureAppConfigurationProvider, self).__init__(**kwargs)
258223

259224
if "user_agent" in kwargs:
260225
user_agent = kwargs.pop("user_agent") + " " + USER_AGENT
@@ -288,17 +253,12 @@ def __init__(self, **kwargs: Any) -> None:
288253

289254
def _attempt_refresh(self, client: ConfigurationClient, replica_count: int, is_failover_request: bool, **kwargs):
290255
settings_refreshed = False
291-
headers = update_correlation_context_header(
256+
headers = self._update_correlation_context_header(
292257
kwargs.pop("headers", {}),
293258
"Watch",
294259
replica_count,
295-
self._feature_flag_enabled,
296-
self._feature_filter_usage,
297260
self._secret_provider.uses_key_vault,
298-
self._uses_load_balancing,
299261
is_failover_request,
300-
self._uses_ai_configuration,
301-
self._uses_aicc_configuration,
302262
)
303263
configuration_settings: List[ConfigurationSetting] = []
304264
feature_flags: Optional[List[FeatureFlagConfigurationSetting]] = None
@@ -341,17 +301,7 @@ def _attempt_refresh(self, client: ConfigurationClient, replica_count: int, is_f
341301
# Configuration Settings have been refreshed
342302
processed_settings = self._process_configurations(configuration_settings)
343303

344-
if feature_flags:
345-
# Reset feature flag usage
346-
self._feature_filter_usage = {}
347-
processed_feature_flags = [self._process_feature_flag(ff) for ff in feature_flags]
348-
349-
if self._feature_flag_enabled:
350-
# Create the feature management schema and add feature flags
351-
if feature_flags:
352-
self._watched_feature_flags = self._update_watched_feature_flags(feature_flags)
353-
processed_settings[FEATURE_MANAGEMENT_KEY] = {}
354-
processed_settings[FEATURE_MANAGEMENT_KEY][FEATURE_FLAG_KEY] = processed_feature_flags
304+
processed_settings = self._process_feature_flags(processed_settings, processed_feature_flags, feature_flags)
355305
self._dict = processed_settings
356306
if settings_refreshed:
357307
# Update the watch keys that have changed
@@ -363,7 +313,6 @@ def _attempt_refresh(self, client: ConfigurationClient, replica_count: int, is_f
363313
self._feature_flag_refresh_timer.reset()
364314
if (settings_refreshed or feature_flags) and self._on_refresh_success:
365315
self._on_refresh_success()
366-
return
367316
except AzureError as e:
368317
logger.warning("Failed to refresh configurations from endpoint %s", client.endpoint)
369318
self._replica_client_manager.backoff(client)
@@ -412,7 +361,7 @@ def refresh(self, **kwargs) -> None:
412361
finally:
413362
self._refresh_lock.release()
414363

415-
def _load_all(self, **kwargs):
364+
def _load_all(self, **kwargs: Any) -> None:
416365
self._replica_client_manager.refresh_clients()
417366
self._replica_client_manager.find_active_clients()
418367
is_failover_request = False
@@ -424,21 +373,15 @@ def _load_all(self, **kwargs):
424373
exception: Exception = RuntimeError(error_message)
425374

426375
while client := self._replica_client_manager.get_next_active_client():
427-
headers = update_correlation_context_header(
376+
headers = self._update_correlation_context_header(
428377
kwargs.pop("headers", {}),
429378
"Startup",
430379
replica_count,
431-
self._feature_flag_enabled,
432-
self._feature_filter_usage,
433380
self._secret_provider.uses_key_vault,
434-
self._uses_load_balancing,
435381
is_failover_request,
436-
self._uses_ai_configuration,
437-
self._uses_aicc_configuration,
438382
)
439383
try:
440384
configuration_settings = client.load_configuration_settings(self._selects, headers=headers, **kwargs)
441-
processed_feature_flags = []
442385
watched_settings = self._update_watched_settings(configuration_settings)
443386
processed_settings = self._process_configurations(configuration_settings)
444387

@@ -448,12 +391,7 @@ def _load_all(self, **kwargs):
448391
headers=headers,
449392
**kwargs,
450393
)
451-
processed_feature_flags = (
452-
[self._process_feature_flag(ff) for ff in feature_flags] if feature_flags else []
453-
)
454-
processed_settings[FEATURE_MANAGEMENT_KEY] = {}
455-
processed_settings[FEATURE_MANAGEMENT_KEY][FEATURE_FLAG_KEY] = processed_feature_flags
456-
self._watched_feature_flags = self._update_watched_feature_flags(feature_flags)
394+
processed_settings = self._process_feature_flags(processed_settings, [], feature_flags)
457395
for (key, label), etag in self._watched_settings.items():
458396
if not etag:
459397
try:

0 commit comments

Comments
 (0)