diff --git a/src/azure-cli/azure/cli/command_modules/acs/_validators.py b/src/azure-cli/azure/cli/command_modules/acs/_validators.py index 7c7897b40ee..9e8253dfd83 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/_validators.py +++ b/src/azure-cli/azure/cli/command_modules/acs/_validators.py @@ -416,6 +416,7 @@ def extract_comma_separated_string( allow_empty_value=False, keep_none=False, default_value=None, + allow_appending_values_to_same_key=False, ): """Extract comma-separated string. @@ -425,6 +426,8 @@ def extract_comma_separated_string( Option allow_empty_value is valid since extract_kv is specified. When the number of string segments split by "=" is 1, the first segment is retained as the key and empty string would be set as its corresponding value without raising an exception. + Option allow_appending_values_to_same_key is valid since extract_kv is specified. For the same key, the new value + is appended to the existing value separated by commas. If keep_none is specified, will return None when input is None. Otherwise will return default_value if input is None or empty string. """ @@ -457,6 +460,8 @@ def extract_comma_separated_string( if enable_strip: key = key.strip() value = value.strip() + if allow_appending_values_to_same_key and key in result: + value = "{},{}".format(result[key], value) result[key] = value else: raise InvalidArgumentValueError( diff --git a/src/azure-cli/azure/cli/command_modules/acs/agentpool_decorator.py b/src/azure-cli/azure/cli/command_modules/acs/agentpool_decorator.py index 40145a8c4d1..98732f517d7 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/agentpool_decorator.py +++ b/src/azure-cli/azure/cli/command_modules/acs/agentpool_decorator.py @@ -349,6 +349,7 @@ def get_aks_custom_headers(self) -> Dict[str, str]: enable_strip=True, extract_kv=True, default_value={}, + allow_appending_values_to_same_key=True, ) # this parameter does not need validation diff --git a/src/azure-cli/azure/cli/command_modules/acs/custom.py b/src/azure-cli/azure/cli/command_modules/acs/custom.py index 26a44b8b96e..af0504aae70 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/custom.py +++ b/src/azure-cli/azure/cli/command_modules/acs/custom.py @@ -3203,6 +3203,7 @@ def aks_agentpool_add(cmd, client, resource_group_name, cluster_name, nodepool_n enable_strip=True, extract_kv=True, default_value={}, + allow_appending_values_to_same_key=True, ) return sdk_no_wait( @@ -3300,6 +3301,7 @@ def aks_agentpool_upgrade(cmd, client, resource_group_name, cluster_name, enable_strip=True, extract_kv=True, default_value={}, + allow_appending_values_to_same_key=True, ) return sdk_no_wait( @@ -3413,6 +3415,7 @@ def aks_agentpool_update(cmd, client, resource_group_name, cluster_name, nodepoo enable_strip=True, extract_kv=True, default_value={}, + allow_appending_values_to_same_key=True, ) return sdk_no_wait( @@ -4161,6 +4164,7 @@ def aks_snapshot_create(cmd, # pylint: disable=too-many-locals,too-many-state enable_strip=True, extract_kv=True, default_value={}, + allow_appending_values_to_same_key=True, ) return client.create_or_update(resource_group_name, name, snapshot, headers=aks_custom_headers) diff --git a/src/azure-cli/azure/cli/command_modules/acs/decorator.py b/src/azure-cli/azure/cli/command_modules/acs/decorator.py index 74c061bd650..89362575589 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/decorator.py +++ b/src/azure-cli/azure/cli/command_modules/acs/decorator.py @@ -4617,6 +4617,7 @@ def get_aks_custom_headers(self) -> Dict[str, str]: enable_strip=True, extract_kv=True, default_value={}, + allow_appending_values_to_same_key=True, ) # In create mode, add AAD session key to header. diff --git a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_validators.py b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_validators.py index 097e54f6c60..de26420ae42 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_validators.py +++ b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_validators.py @@ -351,7 +351,7 @@ def test_extract_comma_separated_string(self): validators.extract_comma_separated_string(s12, extract_kv=True) s13 = "WindowsContainerRuntime=containerd,AKSHTTPCustomFeatures=Microsoft.ContainerService/CustomNodeConfigPreview" - t13 = validators.extract_comma_separated_string(s13, enable_strip=True, extract_kv=True, default_value={},) + t13 = validators.extract_comma_separated_string(s13, enable_strip=True, extract_kv=True, default_value={}, allow_appending_values_to_same_key=True) g13 = {"WindowsContainerRuntime": "containerd", "AKSHTTPCustomFeatures": "Microsoft.ContainerService/CustomNodeConfigPreview"} self.assertEqual(t13, g13) @@ -360,6 +360,16 @@ def test_extract_comma_separated_string(self): g14 = {"": ""} self.assertEqual(t14, g14) + s15 = "WindowsContainerRuntime=containerd,AKSHTTPCustomFeatures=Microsoft.ContainerService/AKSTestFeaturePreview,AKSHTTPCustomFeatures=Microsoft.ContainerService/AKSExampleFeaturePreview" + t15 = validators.extract_comma_separated_string(s15, enable_strip=True, extract_kv=True, default_value={},) + g15 = {"WindowsContainerRuntime": "containerd", "AKSHTTPCustomFeatures": "Microsoft.ContainerService/AKSExampleFeaturePreview"} + self.assertEqual(t15, g15) + + s16 = "WindowsContainerRuntime=containerd,AKSHTTPCustomFeatures=Microsoft.ContainerService/AKSTestFeaturePreview,AKSHTTPCustomFeatures=Microsoft.ContainerService/AKSExampleFeaturePreview" + t16 = validators.extract_comma_separated_string(s16, enable_strip=True, extract_kv=True, default_value={}, allow_appending_values_to_same_key=True) + g16 = {"WindowsContainerRuntime": "containerd", "AKSHTTPCustomFeatures": "Microsoft.ContainerService/AKSTestFeaturePreview,Microsoft.ContainerService/AKSExampleFeaturePreview"} + self.assertEqual(t16, g16) + class CredentialFormatNamespace: def __init__(self, credential_format): @@ -381,3 +391,7 @@ def test_valid_format(self): namespace = CredentialFormatNamespace(credential_format) validators.validate_credential_format(namespace) + + +if __name__ == "__main__": + unittest.main()