-
Notifications
You must be signed in to change notification settings - Fork 3.4k
[AppConfig] Adding new command 'set-keyvault' to kv subgroup #11571
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0d1c101
5249754
052d283
0a35643
969eec1
1bd55e5
216a321
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -147,3 +147,15 @@ def validate_filter_parameter(string): | |
| else: | ||
| logger.warning("Ignoring filter parameter '%s' because parameter name is empty.", string) | ||
| return result | ||
|
|
||
|
|
||
| def validate_secret_identifier(namespace): | ||
| """ Validate the format of keyvault reference secret identifier """ | ||
| from azure.keyvault.key_vault_id import KeyVaultIdentifier | ||
|
|
||
| identifier = getattr(namespace, 'secret_identifier', None) | ||
| try: | ||
| # this throws an exception for invalid format of secret identifier | ||
| KeyVaultIdentifier(uri=identifier) | ||
| except Exception as e: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Any specific type of exception this can throw? Since our error message is very specific to secret identifier value. #Resolved
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Going through the keyvault SDK, it looks like they only throw ValueError and TypeError at this time. But I didn't find any official documentation which says they can't throw anything else in future. I could change our error message to clarify that the exception was thrown by keyvault. In reply to: 358527193 [](ancestors = 358527193) |
||
| raise CLIError("Received an exception while validating the format of secret identifier.\n{0}".format(str(e))) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,6 +30,7 @@ | |
| logger = get_logger(__name__) | ||
| FEATURE_FLAG_PREFIX = ".appconfig.featureflag/" | ||
| FEATURE_FLAG_CONTENT_TYPE = "application/vnd.microsoft.appconfig.ff+json;charset=utf-8" | ||
| KEYVAULT_CONTENT_TYPE = "application/vnd.microsoft.appconfig.keyvaultref+json;charset=utf-8" | ||
|
|
||
|
|
||
| def import_config(cmd, | ||
|
|
@@ -273,6 +274,65 @@ def set_key(cmd, | |
| "Fail to set the key '{}' due to a conflicting operation.".format(key)) | ||
|
|
||
|
|
||
| def set_keyvault(cmd, | ||
| key, | ||
| secret_identifier, | ||
| name=None, | ||
| label=None, | ||
| tags=None, | ||
| yes=False, | ||
| connection_string=None): | ||
| connection_string = resolve_connection_string(cmd, name, connection_string) | ||
| azconfig_client = AzconfigClient(connection_string) | ||
|
|
||
| keyvault_ref_value = json.dumps({"uri": secret_identifier}, ensure_ascii=False) | ||
| retry_times = 3 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why we need json dumps here to create a dictionary? #Resolved
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 'value' attribute of KeyValue object is supposed to be a string. In order to preserve double quotes while converting this dict to str, we use json dumps. In reply to: 358477565 [](ancestors = 358477565)
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, so the key value will look like In reply to: 358518179 [](ancestors = 358518179,358477565)
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, only the double quotes around uri and identifier will be escaped. In reply to: 358528290 [](ancestors = 358528290,358518179,358477565) |
||
| retry_interval = 1 | ||
|
|
||
| label = label if label and label != ModifyKeyValueOptions.empty_label else None | ||
| for i in range(0, retry_times): | ||
| try: | ||
| retrieved_kv = azconfig_client.get_keyvalue(key, QueryKeyValueOptions(label)) | ||
| except HTTPException as exception: | ||
| raise CLIError(str(exception)) | ||
|
|
||
| if retrieved_kv is None: | ||
| set_kv = KeyValue(key, keyvault_ref_value, label, tags, KEYVAULT_CONTENT_TYPE) | ||
| else: | ||
| logger.warning("This operation will result in overwriting existing key whose value is: %s", retrieved_kv.value) | ||
| set_kv = KeyValue(key=key, | ||
| label=label, | ||
| value=keyvault_ref_value, | ||
| content_type=KEYVAULT_CONTENT_TYPE, | ||
| tags=retrieved_kv.tags if tags is None else tags) | ||
| set_kv.etag = retrieved_kv.etag | ||
|
|
||
| verification_kv = { | ||
| "key": set_kv.key, | ||
| "label": set_kv.label, | ||
| "content_type": set_kv.content_type, | ||
| "value": set_kv.value, | ||
| "tags": set_kv.tags | ||
| } | ||
| entry = json.dumps(verification_kv, indent=2, sort_keys=True, ensure_ascii=False) | ||
| confirmation_message = "Are you sure you want to set the keyvault reference: \n" + entry + "\n" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add ensure_ascii=False in json.dumps #Resolved
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| user_confirmation(confirmation_message, yes) | ||
|
|
||
| try: | ||
| return azconfig_client.add_keyvalue(set_kv, ModifyKeyValueOptions()) if set_kv.etag is None else azconfig_client.update_keyvalue(set_kv, ModifyKeyValueOptions()) | ||
| except HTTPException as exception: | ||
| if exception.status == StatusCodes.PRECONDITION_FAILED: | ||
| logger.debug( | ||
| 'Retrying setting %s times with exception: concurrent setting operations', i + 1) | ||
| time.sleep(retry_interval) | ||
| else: | ||
| raise CLIError(str(exception)) | ||
| except Exception as exception: | ||
| raise CLIError(str(exception)) | ||
| raise CLIError( | ||
| "Failed to set the keyvault reference '{}' due to a conflicting operation.".format(key)) | ||
|
|
||
|
|
||
| def delete_key(cmd, | ||
| key, | ||
| name=None, | ||
|
|
||
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Uh oh!
There was an error while loading. Please reload this page.