Skip to content

Commit e1f5641

Browse files
ChristineWanjauChristine WANJAU
andauthored
[App Config] az appconfig kv import/export/restore: Add dry-run feature (#30842)
Co-authored-by: Christine WANJAU <cwanjau@microsoft.com>
1 parent fd4a6cd commit e1f5641

18 files changed

+25190
-78401
lines changed

src/azure-cli/azure/cli/command_modules/appconfig/_help.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,8 @@
177177
text: az appconfig kv export -n MyAppConfiguration -d appconfig --tags tag1=value1 tag2=value2 --dest-name AnotherAppConfiguration
178178
- name: Export all keys and feature flags to another App Configuration store and apply new tags.
179179
text: az appconfig kv export -n MyAppConfiguration -d appconfig --dest-name AnotherAppConfiguration --dest-tags newtag1=newvalue1
180+
- name: Preview the export result without making any changes to the App Configuration store.
181+
text: az appconfig kv export -n MyAppConfiguration --label test -d file --path D:/abc.json --format json --dry-run
180182
"""
181183

182184
helps['appconfig kv import'] = """
@@ -203,8 +205,10 @@
203205
text: az appconfig kv import -n MyAppConfiguration -s file --path D:/abc.json --format json --profile appconfig/kvset
204206
- name: Import all keys and feature flags with specific tags from an App Configuration store and apply new tags.
205207
text: az appconfig kv import -n MyAppConfiguration -s appconfig --src-name AnotherAppConfiguration --src-tags tag1=value1 tag2=value2 --tags newtag1=newvalue1
206-
- name: Import allkeys and feature flags from a file and apply new tags.
208+
- name: Import all keys and feature flags from a file and apply new tags.
207209
text: az appconfig kv import -n MyAppConfiguration -s file --path D:/abc.json --format json --tags tag1=value1
210+
- name: Preview the import result without making any changes to the App Configuration store.
211+
text: az appconfig kv import -n MyAppConfiguration -s file --path D:/abc.json --format json --dry-run
208212
209213
"""
210214

@@ -254,6 +258,8 @@
254258
text: az appconfig kv restore --key color --connection-string Endpoint=https://contoso.azconfig.io;Id=xxx;Secret=xxx --label v1.* --datetime "2019-05-01T11:24:12Z"
255259
- name: Restore all key-values with specific tags to a specific point in time.
256260
text: az appconfig kv restore -n MyAppConfiguration --tags tag1=value1 tag2=value2 --datetime "2019-05-01T11:24:12Z"
261+
- name: Preview the restore result without making any changes to the App Configuration store.
262+
text: az appconfig kv restore -n MyAppConfiguration --datetime "2019-05-01T11:24:12Z" --dry-run
257263
"""
258264

259265
helps['appconfig kv set'] = """

src/azure-cli/azure/cli/command_modules/appconfig/_kv_export_helpers.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ def __export_keyvalue(key_segments, value, constructed_data):
373373

374374

375375
# Helper functions
376-
def __export_kvset_to_file(file_path, keyvalues, yes):
376+
def __export_kvset_to_file(file_path, keyvalues, yes, dry_run=False):
377377
if len(keyvalues) == 0:
378378
logger.warning("\nSource configuration is empty. Nothing to export.")
379379
return
@@ -387,6 +387,9 @@ def __export_kvset_to_file(file_path, keyvalues, yes):
387387
updates, level="kvset", yes=yes, title="KVSet", indent=2, show_update_diff=False
388388
)
389389

390+
if dry_run:
391+
return
392+
390393
if not yes:
391394
user_confirmation("Do you want to continue? \n")
392395
try:

src/azure-cli/azure/cli/command_modules/appconfig/_kv_import_helpers.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,7 @@ def __import_kvset_from_file(
457457
path,
458458
strict,
459459
yes,
460+
dry_run=False,
460461
import_mode=ImportMode.IGNORE_MATCH,
461462
correlation_request_id=None,
462463
):
@@ -498,7 +499,7 @@ def __import_kvset_from_file(
498499
show_update_diff=False,
499500
)
500501

501-
if not changes_detected:
502+
if not changes_detected or dry_run:
502503
return
503504

504505
if not yes:

src/azure-cli/azure/cli/command_modules/appconfig/_params.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
validate_resolve_keyvault, validate_export_profile, validate_import_profile,
2828
validate_strict_import, validate_export_as_reference, validate_snapshot_filters,
2929
validate_snapshot_export, validate_snapshot_import, validate_tag_filters,
30-
validate_import_tag_filters)
30+
validate_import_tag_filters, validate_dry_run)
3131

3232

3333
def load_arguments(self, _):
@@ -228,6 +228,7 @@ def load_arguments(self, _):
228228
c.argument('skip_features', help="Import only key values and exclude all feature flags. By default, all feature flags will be imported from file or appconfig. Not applicable for appservice.", arg_type=get_three_state_flag())
229229
c.argument('content_type', help='Content type of all imported items.')
230230
c.argument('import_mode', arg_type=get_enum_type([ImportMode.ALL, ImportMode.IGNORE_MATCH]), help='If import mode is "ignore-match", only source key-values that do not already exist or whose value, content-type or tags are different from that of an existing key-value with the same key and label, will be written. Import mode "all" writes all key-values to the destination regardless of whether they exist or not.')
231+
c.argument('dry_run', validator=validate_dry_run, help="Preview the result of import operation without making any changes to the App Configuration store.")
231232

232233
with self.argument_context('appconfig kv import', arg_group='File') as c:
233234
c.argument('path', help='Local configuration file path. Required for file arguments.')
@@ -265,6 +266,7 @@ def load_arguments(self, _):
265266
c.argument('snapshot', validator=validate_snapshot_export,
266267
help="Export all keys in a given snapshot of the App Configuration store. If no snapshot is specified, the keys currently in the store are exported based on the specified key and label filters.")
267268
c.argument('tags', arg_type=tags_arg_type, help="Key-values which contain the specified tags in source AppConfig will be exported. If no tags are specified, all key-values with any tags can be exported. Support space-separated tag filters: key[=value] [key[=value] ...].")
269+
c.argument('dry_run', validator=validate_dry_run, help="Preview the result of export operation without making any changes to the App Configuration store.")
268270

269271
with self.argument_context('appconfig kv export', arg_group='File') as c:
270272
c.argument('path', help='Local configuration file path. Required for file arguments.')
@@ -324,6 +326,7 @@ def load_arguments(self, _):
324326
c.argument('key', help='If no key specified, restore all keys by default. Support star sign as filters, for instance abc* means keys with abc as prefix.')
325327
c.argument('label', help="If no label specified, restore all key-value pairs with all labels. Support star sign as filters, for instance abc* means labels with abc as prefix. Use '\\0' for null label.")
326328
c.argument('tags', arg_type=tags_arg_type, help="If no tags are specified, restore all key-values with any tags. Support space-separated tags: key[=value] [key[=value] ...].")
329+
c.argument('dry_run', validator=validate_dry_run, help="Preview the result of restore operation without making any changes to the App Configuration store.")
327330

328331
with self.argument_context('appconfig kv lock') as c:
329332
c.argument('key', help='Key to be locked.')

src/azure-cli/azure/cli/command_modules/appconfig/_validators.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,3 +453,8 @@ def validate_tag_filters(namespace):
453453
def validate_import_tag_filters(namespace):
454454
"""Validates tag filters in the 'src_tags' attribute."""
455455
_validate_tag_filter_list(getattr(namespace, 'src_tags', None))
456+
457+
458+
def validate_dry_run(namespace):
459+
if namespace.dry_run and namespace.yes:
460+
raise MutuallyExclusiveArgumentError("The '--dry-run' and '--yes' options cannot be specified together.")

src/azure-cli/azure/cli/command_modules/appconfig/keyvalue.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ def import_config(cmd,
7373
auth_mode="key",
7474
endpoint=None,
7575
import_mode=ImportMode.IGNORE_MATCH,
76+
dry_run=False,
7677
# from-file parameters
7778
path=None,
7879
format_=None,
@@ -108,7 +109,7 @@ def import_config(cmd,
108109
# fetch key values from source
109110
if source == 'file':
110111
if profile == ImportExportProfiles.KVSET:
111-
__import_kvset_from_file(client=azconfig_client, path=path, strict=strict, yes=yes, import_mode=import_mode, correlation_request_id=correlation_request_id)
112+
__import_kvset_from_file(client=azconfig_client, path=path, strict=strict, yes=yes, dry_run=dry_run, import_mode=import_mode, correlation_request_id=correlation_request_id)
112113
return
113114
if format_ and content_type:
114115
# JSON content type is only supported with JSON format.
@@ -219,7 +220,7 @@ def import_config(cmd,
219220
ff_diff = ff_comparer.compare(dest_kvs=dest_features, strict=strict, ignore_matching_kvs=import_mode == ImportMode.IGNORE_MATCH)
220221
need_feature_change = print_preview(ff_diff, source, yes=yes, strict=strict, title="Feature Flags")
221222

222-
if not need_kv_change and not need_feature_change:
223+
if (not need_kv_change and not need_feature_change) or dry_run:
223224
return
224225

225226
if not yes:
@@ -273,6 +274,7 @@ def export_config(cmd,
273274
auth_mode="key",
274275
endpoint=None,
275276
snapshot=None,
277+
dry_run=False,
276278
# to-file parameters
277279
path=None,
278280
format_=None,
@@ -360,7 +362,7 @@ def export_config(cmd,
360362
__discard_features_from_retrieved_kv(src_kvs)
361363

362364
if profile == ImportExportProfiles.KVSET:
363-
__export_kvset_to_file(file_path=path, keyvalues=src_kvs, yes=yes)
365+
__export_kvset_to_file(file_path=path, keyvalues=src_kvs, yes=yes, dry_run=dry_run)
364366
return
365367

366368
if destination == 'appservice' and export_as_reference:
@@ -419,8 +421,9 @@ def export_config(cmd,
419421
ff_diff = ff_comparer.compare(dest_kvs=__convert_featureflag_list_to_keyvalue_list(dest_features))
420422
need_feature_change = print_preview(ff_diff, destination, yes=yes, title="Feature Flags")
421423

422-
if not need_feature_change and not need_kv_change:
424+
if (not need_feature_change and not need_kv_change) or dry_run:
423425
return
426+
424427
# if customer needs preview & confirmation
425428
if not yes:
426429
user_confirmation("Do you want to continue? \n")
@@ -824,6 +827,7 @@ def restore_key(cmd,
824827
connection_string=None,
825828
yes=False,
826829
auth_mode="key",
830+
dry_run=False,
827831
endpoint=None):
828832
azconfig_client = get_appconfig_data_client(cmd, name, connection_string, auth_mode, endpoint)
829833

@@ -849,11 +853,10 @@ def restore_key(cmd,
849853

850854
need_change = __print_restore_preview(restore_diff, yes=yes)
851855

852-
if not yes:
853-
if need_change is False:
854-
logger.debug('Canceling the restore operation based on user selection.')
855-
return
856+
if dry_run or not need_change:
857+
return
856858

859+
if not yes:
857860
user_confirmation("Do you want to continue? \n")
858861

859862
kvs_to_restore = restore_diff.get(JsonDiff.ADD, [])

0 commit comments

Comments
 (0)