Skip to content
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

[AppConfig] Support import/export of all labels between 2 config stores #11756

Merged
merged 10 commits into from
Jan 21, 2020
1 change: 1 addition & 0 deletions CredScanSuppressions.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
},
{
"file": [
"src\\azure-cli\\azure\\cli\\command_modules\\appconfig\\tests\\latest\\recordings\\test_appconfig_to_appconfig_import_export.yaml",
"src\\azure-cli\\azure\\cli\\command_modules\\appconfig\\tests\\latest\\recordings\\test_azconfig_credential.yaml",
"src\\azure-cli\\azure\\cli\\command_modules\\appconfig\\tests\\latest\\recordings\\test_azconfig_feature.yaml",
"src\\azure-cli\\azure\\cli\\command_modules\\appconfig\\tests\\latest\\recordings\\test_azconfig_feature_filter.yaml",
Expand Down
4 changes: 4 additions & 0 deletions src/azure-cli/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
Release History
===============

**AppConfig**

* Support import/export of all labels from appconfig to appconfig

2.0.79
++++++

Expand Down
12 changes: 8 additions & 4 deletions src/azure-cli/azure/cli/command_modules/appconfig/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,14 @@
examples:
- name: Export all keys and feature flags with label test to a json file.
text: az appconfig kv export -n MyAppConfiguration --label test -d file --path D:/abc.json --format json
- name: Export all keys and feature flags with null label to another App Configuration.
text: az appconfig kv export -n MyAppConfiguration -d appconfig --dest-name AnotherAppConfiguration
- name: Export all keys with null label to an App Service application.
text: az appconfig kv export -n MyAppConfiguration -d appservice --appservice-account MyAppService
- name: Export all keys with label test excluding feature flags to a json file.
text: az appconfig kv export -n MyAppConfiguration --label test -d file --path D:/abc.json --format json --skip-features
- name: Export all keys and feature flags with all labels to another App Configuration.
text: az appconfig kv export -n MyAppConfiguration -d appconfig --dest-name AnotherAppConfiguration --key * --label * --preserve-labels
- name: Export all keys and feature flags with all labels to another App Configuration and overwrite destination labels.
text: az appconfig kv export -n MyAppConfiguration -d appconfig --dest-name AnotherAppConfiguration --key * --label * --dest-label ExportedKeys
"""

helps['appconfig kv import'] = """
Expand All @@ -84,12 +86,14 @@
examples:
- name: Import all keys and feature flags from a file and apply test label.
text: az appconfig kv import -n MyAppConfiguration --label test -s file --path D:/abc.json --format json
- name: Import all keys and feature flags and apply null label from an App Configuration.
text: az appconfig kv import -n MyAppConfiguration -s appconfig --src-name AnotherAppConfiguration
- name: Import all keys and feature flags with null label and apply new label from an App Configuration.
text: az appconfig kv import -n MyAppConfiguration -s appconfig --src-name AnotherAppConfiguration --label ImportedKeys
- name: Import all keys and apply null label from an App Service appliaction.
text: az appconfig kv import -n MyAppConfiguration -s appservice --appservice-account MyAppService
- name: Import all keys with label test and apply test2 label excluding feature flags from an App Configuration.
text: az appconfig kv import -n MyAppConfiguration -s appconfig --src-label test --label test2 --src-name AnotherAppConfiguration --skip-features
- name: Import all keys and feature flags with all labels to another App Configuration.
text: az appconfig kv import -n MyAppConfiguration -s appconfig --src-name AnotherAppConfiguration --src-key * --src-label * --preserve-labels
"""

helps['appconfig kv list'] = """
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ def __read_kv_from_config_store(cmd, name=None, connection_string=None, key=None
return key_values


def __write_kv_and_features_to_config_store(cmd, key_values, features=None, name=None, connection_string=None, label=None):
def __write_kv_and_features_to_config_store(cmd, key_values, features=None, name=None, connection_string=None, label=None, preserve_labels=False):
if not key_values and not features:
return
try:
Expand All @@ -239,9 +239,14 @@ def __write_kv_and_features_to_config_store(cmd, key_values, features=None, name
if features:
key_values.extend(__convert_featureflag_list_to_keyvalue_list(features))

for kv in key_values:
kv.label = label
azconfig_client.set_keyvalue(kv, ModifyKeyValueOptions())
if not preserve_labels:
for kv in key_values:
kv.label = label
azconfig_client.set_keyvalue(kv, ModifyKeyValueOptions())
else:
for kv in key_values:
azconfig_client.set_keyvalue(kv, ModifyKeyValueOptions())

except Exception as exception:
raise CLIError(str(exception))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,14 @@ def load_arguments(self, _):
c.argument('src_name', help='The name of the source App Configuration.')
c.argument('src_connection_string', validator=validate_connection_string, help="Combination of access key and endpoint of the source store.")
c.argument('src_key', help='If no key specified, import all keys by default. Support star sign as filters, for instance abc* means keys with abc as prefix. Similarly, *abc and *abc* are also supported. Key filtering not applicable for feature flags. By default, all feature flags with specified label will be imported.')
c.argument('src_label', help="Only keys with this label in source AppConfig will be imported. If no label specified, import keys with null label by default.")
c.argument('src_label', help="Only keys with this label in source AppConfig will be imported. If no value specified, import keys with null label by default. Support star sign as filters, for instance * means all labels, abc* means labels with abc as prefix. Similarly, *abc and *abc* are also supported.")
c.argument('preserve_labels', arg_type=get_three_state_flag(), help="Flag to preserve labels from source AppConfig. This argument should NOT be specified along with --label.")

with self.argument_context('appconfig kv import', arg_group='AppService') as c:
c.argument('appservice_account', validator=validate_appservice_name_or_id, help='ARM ID for AppService OR the name of the AppService, assuming it is in the same subscription and resource group as the App Configuration. Required for AppService arguments')

with self.argument_context('appconfig kv export') as c:
c.argument('label', help="Only keys and feature flags with this label will be exported. If no label specified, export keys and feature flags with null label by default.")
c.argument('label', help="Only keys and feature flags with this label will be exported. If no label specified, export keys and feature flags with null label by default. Only when export destination is appconfig, we support star sign as filters, for instance * means all labels and abc* means labels with abc as prefix. Similarly, *abc and *abc* are also supported. Label filters are not supported when exporting to file or appservice.")
c.argument('prefix', help="Prefix to be trimmed from keys. Prefix will be ignored for feature flags.")
c.argument('key', help='If no key specified, return all keys by default. Support star sign as filters, for instance abc* means keys with abc as prefix. Similarly, *abc and *abc* are also supported. Key filtering not applicable for feature flags. By default, all feature flags with specified label will be exported.')
c.argument('destination', options_list=['--destination', '-d'], arg_type=get_enum_type(['file', 'appconfig', 'appservice']), validator=validate_export, help="The destination of exporting. Note that exporting feature flags to appservice is not supported.")
Expand All @@ -116,7 +117,8 @@ def load_arguments(self, _):
with self.argument_context('appconfig kv export', arg_group='AppConfig') as c:
c.argument('dest_name', help='The name of the destination App Configuration.')
c.argument('dest_connection_string', validator=validate_connection_string, help="Combination of access key and endpoint of the destination store.")
c.argument('dest_label', help="Exported KVs will be labeled with this destination label.")
c.argument('dest_label', help="Exported KVs will be labeled with this destination label. If neither --dest-label nor --preserve-labels is specified, will assign null label.")
c.argument('preserve_labels', arg_type=get_three_state_flag(), help="Flag to preserve labels from source AppConfig. This argument should NOT be specified along with --dest-label.")

with self.argument_context('appconfig kv export', arg_group='AppService') as c:
c.argument('appservice_account', validator=validate_appservice_name_or_id, help='ARM ID for AppService OR the name of the AppService, assuming it is in the same subscription and resource group as the App Configuration. Required for AppService arguments')
Expand Down
36 changes: 27 additions & 9 deletions src/azure-cli/azure/cli/command_modules/appconfig/keyvalue.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

# pylint: disable=line-too-long
# pylint: disable=line-too-long, too-many-locals

import json
import time
Expand Down Expand Up @@ -40,6 +40,7 @@ def import_config(cmd,
label=None,
prefix="", # prefix to add
yes=False,
skip_features=False,
# from-file parameters
path=None,
format_=None,
Expand All @@ -50,10 +51,9 @@ def import_config(cmd,
src_connection_string=None,
src_key=None,
src_label=None,
preserve_labels=False,
# from-appservice parameters
appservice_account=None,
skip_features=False):
# pylint: disable=too-many-locals
appservice_account=None):
src_features = []
dest_features = []
dest_kvs = []
Expand All @@ -70,6 +70,14 @@ def import_config(cmd,
src_features = __read_features_from_file(file_path=path, format_=format_)

elif source == 'appconfig':
if label is not None and preserve_labels:
raise CLIError("Import failed! Please provide only one of these arguments: 'label' or 'preserve-labels'. See 'az appconfig kv import -h' for examples.")
if preserve_labels:
# We need label to be the same as src_label for preview later.
# This will have no effect on label while writing to config store
# as we check preserve_labels again before labelling KVs.
label = src_label

src_kvs = __read_kv_from_config_store(cmd, name=src_name, connection_string=src_connection_string,
key=src_key, label=src_label, prefix_to_add=prefix)
# We need to separate KV from feature flags
Expand Down Expand Up @@ -122,7 +130,7 @@ def import_config(cmd,

# import into configstore
__write_kv_and_features_to_config_store(
cmd, key_values=src_kvs, name=name, connection_string=connection_string, label=label)
cmd, key_values=src_kvs, name=name, connection_string=connection_string, label=label, preserve_labels=preserve_labels)


def export_config(cmd,
Expand All @@ -133,25 +141,35 @@ def export_config(cmd,
key=None,
prefix="", # prefix to remove
yes=False,
skip_features=False,
# to-file parameters
path=None,
format_=None,
separator=None,
naming_convention='pascal',
# to-config-store parameters
dest_name=None,
dest_connection_string=None,
dest_label=None,
preserve_labels=False,
# to-app-service parameters
appservice_account=None,
skip_features=False,
naming_convention='pascal'):
appservice_account=None):
src_features = []
dest_features = []
dest_kvs = []
destination = destination.lower()
format_ = format_.lower() if format_ else None
naming_convention = naming_convention.lower()

if destination == 'appconfig':
if dest_label is not None and preserve_labels:
raise CLIError("Export failed! Please provide only one of these arguments: 'dest-label' or 'preserve-labels'. See 'az appconfig kv export -h' for examples.")
if preserve_labels:
# We need dest_label to be the same as label for preview later.
# This will have no effect on label while writing to config store
# as we check preserve_labels again before labelling KVs.
dest_label = label

# fetch key values from user's configstore
src_kvs = __read_kv_from_config_store(
cmd, name=name, connection_string=connection_string, key=key, label=label, prefix_to_remove=prefix)
Expand Down Expand Up @@ -224,7 +242,7 @@ def export_config(cmd,
naming_convention=naming_convention)
elif destination == 'appconfig':
__write_kv_and_features_to_config_store(cmd, key_values=src_kvs, features=src_features, name=dest_name,
connection_string=dest_connection_string, label=dest_label)
connection_string=dest_connection_string, label=dest_label, preserve_labels=preserve_labels)
elif destination == 'appservice':
__write_kv_to_app_service(cmd, key_values=src_kvs, appservice_account=appservice_account)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#Mon Dec 30 11:27:28 Pacific Standard Time 2019
#Tue Jan 07 13:12:22 Pacific Standard Time 2020
Color=Red
Region=West US
feature-management.FalseFeature=false
Expand Down

Large diffs are not rendered by default.

Loading