1# --------------------------------------------------------------------------------------------
2# Copyright (c) Microsoft Corporation. All rights reserved.
3# Licensed under the MIT License. See License.txt in the project root for license information.
4# --------------------------------------------------------------------------------------------
5
6# pylint: disable=line-too-long
7# pylint: disable=too-many-statements
8
9from knack.arguments import CLIArgumentType
10from azure.cli.core.commands.parameters import (get_enum_type,
11                                                get_location_type,
12                                                get_three_state_flag,
13                                                tags_type,
14                                                resource_group_name_type)
15from azure.cli.core.commands.validators import \
16    get_default_location_from_resource_group
17
18from ._validators import (validate_appservice_name_or_id,
19                          validate_connection_string, validate_datetime,
20                          validate_export, validate_import,
21                          validate_import_depth, validate_query_fields,
22                          validate_feature_query_fields, validate_filter_parameters,
23                          validate_separator, validate_secret_identifier,
24                          validate_key, validate_feature, validate_feature_key,
25                          validate_identity, validate_auth_mode,
26                          validate_resolve_keyvault)
27
28
29def load_arguments(self, _):
30
31    # PARAMETER REGISTRATION
32    fields_arg_type = CLIArgumentType(
33        nargs='+',
34        help='Space-separated customized output fields.',
35        validator=validate_query_fields,
36        arg_type=get_enum_type(['key', 'value', 'label', 'content_type', 'etag', 'tags', 'locked', 'last_modified'])
37    )
38    feature_fields_arg_type = CLIArgumentType(
39        nargs='+',
40        help='Customize output fields for Feature Flags.',
41        validator=validate_feature_query_fields,
42        arg_type=get_enum_type(['name', 'key', 'label', 'locked', 'last_modified', 'state', 'description', 'conditions'])
43    )
44    filter_parameters_arg_type = CLIArgumentType(
45        validator=validate_filter_parameters,
46        help="Space-separated filter parameters in 'name[=value]' format. The value must be an escaped JSON string.",
47        nargs='*'
48    )
49    datatime_filter_arg_type = CLIArgumentType(
50        validator=validate_datetime,
51        help='Format: "YYYY-MM-DDThh:mm:ssZ". If no time zone specified, use UTC by default.'
52    )
53    top_arg_type = CLIArgumentType(
54        options_list=['--top', '-t'],
55        type=int,
56        help='Maximum number of items to return. Must be a positive integer. Default to 100.'
57    )
58    identities_arg_type = CLIArgumentType(
59        nargs='*',
60        validator=validate_identity
61    )
62
63    with self.argument_context('appconfig') as c:
64        c.argument('resource_group_name', arg_type=resource_group_name_type)
65        c.argument('name', options_list=['--name', '-n'], id_part='None', help='Name of the App Configuration. You can configure the default name using `az configure --defaults app_configuration_store=<name>`', configured_default='app_configuration_store')
66        c.argument('connection_string', validator=validate_connection_string, configured_default='appconfig_connection_string',
67                   help="Combination of access key and endpoint of App Configuration. Can be found using 'az appconfig credential list'. Users can preset it using `az configure --defaults appconfig_connection_string=<connection_string>` or environment variable with the name AZURE_APPCONFIG_CONNECTION_STRING.")
68        c.argument('yes', options_list=['--yes', '-y'], help='Do not prompt for confirmation.')
69        c.argument('datetime', arg_type=datatime_filter_arg_type)
70        c.argument('top', arg_type=top_arg_type)
71        c.argument('all_', options_list=['--all'], action='store_true', help="List all items.")
72        c.argument('fields', arg_type=fields_arg_type)
73        c.argument('sku', help='The sku of App Configuration', arg_type=get_enum_type(['Free', 'Standard']))
74        c.argument('endpoint', help='If auth mode is "login", provide endpoint URL of the App Configuration. The endpoint can be retrieved using "az appconfig show" command. You can configure the default endpoint using `az configure --defaults appconfig_endpoint=<endpoint>`', configured_default='appconfig_endpoint')
75        c.argument('auth_mode', arg_type=get_enum_type(['login', 'key']), configured_default='appconfig_auth_mode', validator=validate_auth_mode,
76                   help='This parameter can be used for indicating how a data operation is to be authorized. ' +
77                   'If the auth mode is "key", provide connection string or store name and your account access keys will be retrieved for authorization. ' +
78                   'If the auth mode is "login", provide the store endpoint or store name and your "az login" credentials will be used for authorization. ' +
79                   'You can configure the default auth mode using `az configure --defaults appconfig_auth_mode=<auth_mode>`. ' +
80                   'For more information, see https://docs.microsoft.com/azure/azure-app-configuration/concept-enable-rbac')
81
82    with self.argument_context('appconfig create') as c:
83        c.argument('location', options_list=['--location', '-l'], arg_type=get_location_type(self.cli_ctx), validator=get_default_location_from_resource_group)
84        c.argument('tags', arg_type=tags_type, help="Space-separated tags: key[=value] [key[=value] ...].")
85        c.argument('assign_identity', arg_type=identities_arg_type,
86                   help='Space-separated list of managed identities to be assigned. Use "[system]" to refer to system-assigned managed identity or a resource ID to refer to user-assigned managed identity. If this argument is provided without any value, system-assigned managed identity will be assigned by default. If this argument is not provided, no managed identities will be assigned to this App Configuration store.')
87        c.argument('enable_public_network', options_list=['--enable-public-network', '-e'], arg_type=get_three_state_flag(), is_preview=True,
88                   help='When true, requests coming from public networks have permission to access this store while private endpoint is enabled. When false, only requests made through Private Links can reach this store.')
89        c.argument('disable_local_auth', arg_type=get_three_state_flag(), is_preview=True, help='Disable all authentication methods other than AAD authentication.')
90
91    with self.argument_context('appconfig update') as c:
92        c.argument('tags', arg_type=tags_type)
93        c.argument('enable_public_network', options_list=['--enable-public-network', '-e'], arg_type=get_three_state_flag(), is_preview=True,
94                   help='When true, requests coming from public networks have permission to access this store while private endpoint is enabled. When false, only requests made through Private Links can reach this store.')
95        c.argument('disable_local_auth', arg_type=get_three_state_flag(), is_preview=True, help='Disable all authentication methods other than AAD authentication.')
96
97    with self.argument_context('appconfig update', arg_group='Customer Managed Key') as c:
98        c.argument('encryption_key_name', help='The name of the KeyVault key.')
99        c.argument('encryption_key_vault', help='The URI of the KeyVault.')
100        c.argument('encryption_key_version', help='The version of the KeyVault key. Use the latest version by default.')
101        c.argument('identity_client_id', help='Client ID of the managed identity with wrap and unwrap access to encryption key. Use system-assigned managed identity by default.')
102
103    with self.argument_context('appconfig identity assign') as c:
104        c.argument('identities', arg_type=identities_arg_type, help="Accept system-assigned or user-assigned managed identities separated by spaces. Use '[system]' to refer to system-assigned managed identity or a resource ID to refer to user-assigned managed identity. If this argument is not provided or this argument is provided without any value, system-assigned managed identity will be used by default.")
105
106    with self.argument_context('appconfig identity remove') as c:
107        c.argument('identities', arg_type=identities_arg_type, help="Accept system-assigned or user-assigned managed identities separated by spaces. Use '[system]' to refer to system-assigned managed identity, '[all]' for all managed identities or a resource ID to refer user-assigned managed identity. If this argument is not provided or this argument is provided without any value, system-assigned managed identity will be removed by default.")
108
109    with self.argument_context('appconfig credential regenerate') as c:
110        c.argument('id_', options_list=['--id'], help='Id of the key to be regenerated. Can be found using az appconfig credential list command.')
111
112    with self.argument_context('appconfig kv import') as c:
113        c.argument('label', help="Imported KVs and feature flags will be assigned with this label. If no label specified, will assign null label.")
114        c.argument('prefix', help="This prefix will be appended to the front of imported keys. Prefix will be ignored for feature flags.")
115        c.argument('source', options_list=['--source', '-s'], arg_type=get_enum_type(['file', 'appconfig', 'appservice']), validator=validate_import, help="The source of importing. Note that importing feature flags from appservice is not supported.")
116        c.argument('yes', help="Do not prompt for preview.")
117        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())
118        c.argument('content_type', help='Content type of all imported items.')
119
120    with self.argument_context('appconfig kv import', arg_group='File') as c:
121        c.argument('path', help='Local configuration file path. Required for file arguments.')
122        c.argument('format_', options_list=['--format'], arg_type=get_enum_type(['json', 'yaml', 'properties']), help='Imported file format. Required for file arguments. Currently, feature flags are not supported in properties format.')
123        c.argument('depth', validator=validate_import_depth, help="Depth for flattening the json or yaml file to key-value pairs. Flatten to the deepest level by default if --separator is provided. Not applicable for property files or feature flags.")
124        # bypass cli allowed values limition
125        c.argument('separator', validator=validate_separator, help="Delimiter for flattening the json or yaml file to key-value pairs. Separator will be ignored for property files and feature flags. Supported values: '.', ',', ';', '-', '_', '__', '/', ':' ")
126
127    with self.argument_context('appconfig kv import', arg_group='AppConfig') as c:
128        c.argument('src_name', help='The name of the source App Configuration.')
129        c.argument('src_connection_string', validator=validate_connection_string, help="Combination of access key and endpoint of the source store.")
130        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. Key filtering not applicable for feature flags. By default, all feature flags with specified label will be imported.')
131        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.")
132        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.")
133        c.argument('src_endpoint', help='If --src-auth-mode is "login", provide endpoint URL of the source App Configuration.')
134        c.argument('src_auth_mode', arg_type=get_enum_type(['login', 'key']),
135                   help='Auth mode for connecting to source App Configuration. For details, refer to "--auth-mode" argument.')
136
137    with self.argument_context('appconfig kv import', arg_group='AppService') as c:
138        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')
139
140    with self.argument_context('appconfig kv export') as c:
141        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. Label filters are not supported when exporting to file or appservice.")
142        c.argument('prefix', help="Prefix to be trimmed from keys. Prefix will be ignored for feature flags.")
143        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. Key filtering not applicable for feature flags. By default, all feature flags with specified label will be exported.')
144        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.")
145        c.argument('yes', help="Do not prompt for preview.")
146        c.argument('skip_features', help="Export items excluding all feature flags. By default, all features with the specified label will be exported to file or appconfig. Not applicable for appservice.", arg_type=get_three_state_flag())
147        c.argument('skip_keyvault', help="Export items excluding all key vault references. By default, all key vault references with the specified label will be exported.", arg_type=get_three_state_flag())
148
149    with self.argument_context('appconfig kv export', arg_group='File') as c:
150        c.argument('path', help='Local configuration file path. Required for file arguments.')
151        c.argument('format_', options_list=['--format'], arg_type=get_enum_type(['json', 'yaml', 'properties']), help='File format exporting to. Required for file arguments. Currently, feature flags are not supported in properties format.')
152        c.argument('depth', validator=validate_import_depth, help="Depth for flattening the key-value pairs to json or yaml file. Flatten to the deepest level by default. Not applicable for property files or feature flags.")
153        # bypass cli allowed values limition
154        c.argument('separator', validator=validate_separator, help="Delimiter for flattening the key-value pairs to json or yaml file. Required for exporting hierarchical structure. Separator will be ignored for property files and feature flags. Supported values: '.', ',', ';', '-', '_', '__', '/', ':' ")
155        c.argument('naming_convention', arg_type=get_enum_type(['pascal', 'camel', 'underscore', 'hyphen']), help='Naming convention to be used for "Feature Management" section of file. Example: pascal = FeatureManagement, camel = featureManagement, underscore = feature_management, hyphen = feature-management.')
156        c.argument('resolve_keyvault', arg_type=get_three_state_flag(), validator=validate_resolve_keyvault, help="Resolve the content of key vault reference.")
157
158    with self.argument_context('appconfig kv export', arg_group='AppConfig') as c:
159        c.argument('dest_name', help='The name of the destination App Configuration.')
160        c.argument('dest_connection_string', validator=validate_connection_string, help="Combination of access key and endpoint of the destination store.")
161        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.")
162        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.")
163        c.argument('dest_endpoint', help='If --dest-auth-mode is "login", provide endpoint URL of the destination App Configuration.')
164        c.argument('dest_auth_mode', arg_type=get_enum_type(['login', 'key']),
165                   help='Auth mode for connecting to destination App Configuration. For details, refer to "--auth-mode" argument.')
166
167    with self.argument_context('appconfig kv export', arg_group='AppService') as c:
168        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')
169
170    with self.argument_context('appconfig kv set') as c:
171        c.argument('key', validator=validate_key, help="Key to be set. Key cannot be a '.' or '..', or contain the '%' character.")
172        c.argument('label', help="If no label specified, set the key with null label by default")
173        c.argument('tags', arg_type=tags_type)
174        c.argument('content_type', help='Content type of the keyvalue to be set.')
175        c.argument('value', help='Value of the keyvalue to be set.')
176
177    with self.argument_context('appconfig kv set-keyvault') as c:
178        c.argument('key', validator=validate_key, help="Key to be set. Key cannot be a '.' or '..', or contain the '%' character.")
179        c.argument('label', help="If no label specified, set the key with null label by default")
180        c.argument('tags', arg_type=tags_type)
181        c.argument('secret_identifier', validator=validate_secret_identifier, help="ID of the Key Vault object. Can be found using 'az keyvault {collection} show' command, where collection is key, secret or certificate. To set reference to the latest version of your secret, remove version information from secret identifier.")
182
183    with self.argument_context('appconfig kv delete') as c:
184        c.argument('key', help='Support star sign as filters, for instance * means all key and abc* means keys with abc as prefix.')
185        c.argument('label', help="If no label specified, delete entry with null label. Support star sign as filters, for instance * means all label and abc* means labels with abc as prefix.")
186
187    with self.argument_context('appconfig kv show') as c:
188        c.argument('key', help='Key to be showed.')
189        c.argument('label', help="If no label specified, show entry with null label. Filtering is not supported.")
190
191    with self.argument_context('appconfig kv list') as c:
192        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.')
193        c.argument('label', help="If no label specified, list all labels. Support star sign as filters, for instance abc* means labels with abc as prefix. Use '\\0' for null label.")
194        c.argument('resolve_keyvault', arg_type=get_three_state_flag(), help="Resolve the content of key vault reference. This argument should NOT be specified along with --fields. Instead use --query for customized query.")
195
196    with self.argument_context('appconfig kv restore') as c:
197        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.')
198        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.")
199
200    with self.argument_context('appconfig kv lock') as c:
201        c.argument('key', help='Key to be locked.')
202        c.argument('label', help="If no label specified, lock entry with null label. Filtering is not supported.")
203
204    with self.argument_context('appconfig kv unlock') as c:
205        c.argument('key', help='Key to be unlocked.')
206        c.argument('label', help="If no label specified, unlock entry with null label. Filtering is not supported.")
207
208    with self.argument_context('appconfig revision list') as c:
209        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.')
210        c.argument('label', help="If no label specified, list all labels. Support star sign as filters, for instance abc* means labels with abc as prefix. Use '\\0' for null label.")
211
212    with self.argument_context('appconfig feature') as c:
213        c.argument('key', validator=validate_feature_key, help='Key of the feature flag. Key must start with the ".appconfig.featureflag/" prefix. Key cannot contain the "%" character. If both key and feature arguments are provided, only key will be used. Default key is the reserved prefix ".appconfig.featureflag/" + feature name.')
214
215    with self.argument_context('appconfig feature show') as c:
216        c.argument('feature', help='Name of the feature flag to be retrieved. If the feature flag key is different from the default key, provide the `--key` argument instead.')
217        c.argument('label', help="If no label specified, show entry with null label. Filtering is not supported.")
218        c.argument('fields', arg_type=feature_fields_arg_type)
219
220    with self.argument_context('appconfig feature set') as c:
221        c.argument('feature', validator=validate_feature, help="Name of the feature flag to be set. Feature name cannot contain the '%' character.")
222        c.argument('label', help="If no label specified, set the feature flag with null label by default")
223        c.argument('description', help='Description of the feature flag to be set.')
224        c.argument('key', validator=validate_feature_key, help='Key of the feature flag. Key must start with the ".appconfig.featureflag/" prefix. Key cannot contain the "%" character. Default key is the reserved prefix ".appconfig.featureflag/" + feature name.')
225
226    with self.argument_context('appconfig feature delete') as c:
227        c.argument('feature', help='Name of the feature to be deleted. If the feature flag key is different from the default key, provide the `--key` argument instead. Support star sign as filters, for instance * means all features and abc* means features with abc as prefix. Comma separated features are not supported. Please provide escaped string if your feature name contains comma.')
228        c.argument('label', help="If no label specified, delete the feature flag with null label by default. Support star sign as filters, for instance * means all labels and abc* means labels with abc as prefix.")
229        c.argument('key', validator=validate_feature_key, help='Key of the feature flag. Key must start with the ".appconfig.featureflag/" prefix. Key cannot contain the "%" character. If both key and feature arguments are provided, only key will be used. Support star sign as filters, for instance ".appconfig.featureflag/*" means all features and ".appconfig.featureflag/abc*" means features with abc as prefix. Comma separated features are not supported. Please provide escaped string if your feature name contains comma.')
230
231    with self.argument_context('appconfig feature list') as c:
232        c.argument('feature', help='Name of the feature to be listed. If the feature flag key is different from the default key, provide the `--key` argument instead. Support star sign as filters, for instance * means all features and abc* means features with abc as prefix. Comma separated features are not supported. Please provide escaped string if your feature name contains comma.')
233        c.argument('label', help="If no label specified, list all labels. Support star sign as filters, for instance * means all labels and abc* means labels with abc as prefix. Use '\\0' for null label.")
234        c.argument('fields', arg_type=feature_fields_arg_type)
235        c.argument('all_', help="List all feature flags.")
236        c.argument('key', validator=validate_feature_key, help='Key of the feature flag. Key must start with the ".appconfig.featureflag/" prefix. Key cannot contain the "%" character. If both key and feature arguments are provided, only key will be used. Support star sign as filters, for instance ".appconfig.featureflag/*" means all features and ".appconfig.featureflag/abc*" means features with abc as prefix. Comma separated features are not supported. Please provide escaped string if your feature name contains comma.')
237
238    with self.argument_context('appconfig feature lock') as c:
239        c.argument('feature', help='Name of the feature to be locked. If the feature flag key is different from the default key, provide the `--key` argument instead.')
240        c.argument('label', help="If no label specified, lock the feature flag with null label by default.")
241
242    with self.argument_context('appconfig feature unlock') as c:
243        c.argument('feature', help='Name of the feature to be unlocked. If the feature flag key is different from the default key, provide the `--key` argument instead.')
244        c.argument('label', help="If no label specified, unlock the feature flag with null label by default.")
245
246    with self.argument_context('appconfig feature enable') as c:
247        c.argument('feature', help='Name of the feature to be enabled. If the feature flag key is different from the default key, provide the `--key` argument instead.')
248        c.argument('label', help="If no label specified, enable the feature flag with null label by default.")
249
250    with self.argument_context('appconfig feature disable') as c:
251        c.argument('feature', help='Name of the feature to be disabled. If the feature flag key is different from the default key, provide the `--key` argument instead.')
252        c.argument('label', help="If no label specified, disable the feature flag with null label by default.")
253
254    with self.argument_context('appconfig feature filter add') as c:
255        c.argument('feature', help='Name of the feature to which you want to add the filter. If the feature flag key is different from the default key, provide the `--key` argument instead.')
256        c.argument('label', help="If no label specified, add to the feature flag with null label by default.")
257        c.argument('filter_name', help='Name of the filter to be added.')
258        c.argument('filter_parameters', arg_type=filter_parameters_arg_type)
259        c.argument('index', type=int, help='Zero-based index in the list of filters where you want to insert the new filter. If no index is specified or index is invalid, filter will be added to the end of the list.')
260
261    with self.argument_context('appconfig feature filter delete') as c:
262        c.argument('feature', help='Name of the feature from which you want to delete the filter. If the feature flag key is different from the default key, provide the `--key` argument instead.')
263        c.argument('label', help="If no label specified, delete from the feature flag with null label by default.")
264        c.argument('filter_name', help='Name of the filter to be deleted.')
265        c.argument('index', type=int, help='Zero-based index of the filter to be deleted in case there are multiple instances with same filter name.')
266        c.argument('all_', help="Delete all filters associated with a feature flag.")
267
268    with self.argument_context('appconfig feature filter show') as c:
269        c.argument('feature', help='Name of the feature which contains the filter. If the feature flag key is different from the default key, provide the `--key` argument instead.')
270        c.argument('label', help="If no label specified, show the feature flag with null label by default.")
271        c.argument('filter_name', help='Name of the filter to be displayed.')
272        c.argument('index', type=int, help='Zero-based index of the filter to be displayed in case there are multiple instances with same filter name.')
273
274    with self.argument_context('appconfig feature filter list') as c:
275        c.argument('feature', help='Name of the feature whose filters you want to be displayed. If the feature flag key is different from the default key, provide the `--key` argument instead.')
276        c.argument('label', help="If no label specified, display filters from the feature flag with null label by default.")
277        c.argument('all_', help="List all filters associated with a feature flag.")
278