From a34e4ccdd521f111474694f9eb1fdc6d17cf1f0d Mon Sep 17 00:00:00 2001 From: Steven Dong Date: Thu, 2 Feb 2023 13:55:36 -0500 Subject: [PATCH 1/2] fix pylint for container.py --- src/confcom/azext_confcom/container.py | 459 +++++++++++++------------ 1 file changed, 248 insertions(+), 211 deletions(-) diff --git a/src/confcom/azext_confcom/container.py b/src/confcom/azext_confcom/container.py index 944488f13b8..f98511fd8f4 100644 --- a/src/confcom/azext_confcom/container.py +++ b/src/confcom/azext_confcom/container.py @@ -22,268 +22,305 @@ ) -class ContainerImage: - @classmethod - def from_json( - cls, container_json: Any, debug_mode: bool = False - ) -> "ContainerImage": - containerImage = case_insensitive_dict_get( - container_json, config.ACI_FIELD_CONTAINERS_CONTAINERIMAGE +def extract_container_image(container_json: Any) -> str: + containerImage = case_insensitive_dict_get( + container_json, config.ACI_FIELD_CONTAINERS_CONTAINERIMAGE + ) + if not containerImage: + eprint( + f'Field ["{config.ACI_FIELD_CONTAINERS}"]' + + f'["{config.ACI_FIELD_CONTAINERS_CONTAINERIMAGE}"] is empty or can not be found.' + ) + return containerImage + + +def extract_env_rules(container_json: Any): + environmentRules = [] + env_rules = case_insensitive_dict_get( + container_json, config.ACI_FIELD_CONTAINERS_ENVS + ) + if env_rules is None: # empty(no envs) is acceptable + eprint( + f'Field ["{config.ACI_FIELD_CONTAINERS}"]' + + f'["{config.ACI_FIELD_CONTAINERS_ENVS}"] is null or can not be found.' ) - if not containerImage: + + # parse each environment variable pair and add it to list + for rule in env_rules: + name, value, strategy, required = ( + case_insensitive_dict_get(rule, config.ACI_FIELD_CONTAINERS_ENVS_NAME), + case_insensitive_dict_get(rule, config.ACI_FIELD_CONTAINERS_ENVS_VALUE), + case_insensitive_dict_get(rule, config.ACI_FIELD_CONTAINERS_ENVS_STRATEGY), + case_insensitive_dict_get(rule, config.ACI_FIELD_CONTAINERS_ENVS_REQUIRED), + ) + if name is None or value is None or strategy is None: eprint( - f'Field ["{config.ACI_FIELD_CONTAINERS}"]' - + f'["{config.ACI_FIELD_CONTAINERS_CONTAINERIMAGE}"] is empty or can not be found.' + f'Field ["{config.ACI_FIELD_CONTAINERS}"]["{config.ACI_FIELD_CONTAINERS_ENVS}"] is incorrect.' ) - id_val = case_insensitive_dict_get(container_json, config.ACI_FIELD_CONTAINERS_ID) - - environmentRules = [] - env_rules = case_insensitive_dict_get( - container_json, config.ACI_FIELD_CONTAINERS_ENVS + environmentRules.append( + { + config.POLICY_FIELD_CONTAINERS_ELEMENTS_ENVS_RULE: f"{name}={value}", + config.POLICY_FIELD_CONTAINERS_ELEMENTS_ENVS_STRATEGY: strategy, + # default value for "required" is False + config.POLICY_FIELD_CONTAINERS_ELEMENTS_REQUIRED: required + if required is not None + else False, + } ) - if env_rules is None: # empty(no envs) is acceptable + return environmentRules + + +def extract_id(container_json: Any) -> str: + return case_insensitive_dict_get(container_json, config.ACI_FIELD_CONTAINERS_ID) + + +def extract_working_dir(container_json: Any): + # parse working directory + workingDir = case_insensitive_dict_get( + container_json, config.ACI_FIELD_CONTAINERS_WORKINGDIR + ) + # check workingDir is an absolute path if user specified + if workingDir: + if not isinstance(workingDir, str): eprint( f'Field ["{config.ACI_FIELD_CONTAINERS}"]' - + f'["{config.ACI_FIELD_CONTAINERS_ENVS}"] is null or can not be found.' + + f'["{config.ACI_FIELD_CONTAINERS_WORKINGDIR}"] must be a String.' ) - - # parse each environment variable pair and add it to list - for rule in env_rules: - name, value, strategy, required = ( - case_insensitive_dict_get(rule, config.ACI_FIELD_CONTAINERS_ENVS_NAME), - case_insensitive_dict_get(rule, config.ACI_FIELD_CONTAINERS_ENVS_VALUE), - case_insensitive_dict_get( - rule, config.ACI_FIELD_CONTAINERS_ENVS_STRATEGY - ), - case_insensitive_dict_get( - rule, config.ACI_FIELD_CONTAINERS_ENVS_REQUIRED - ), + if not os.path.isabs(workingDir): + eprint( + f'Field ["{config.ACI_FIELD_CONTAINERS}"]' + + f'["{config.ACI_FIELD_CONTAINERS_WORKINGDIR}"] with value: {workingDir} is not absolute path.' ) - if name is None or value is None or strategy is None: - eprint( - f'Field ["{config.ACI_FIELD_CONTAINERS}"]["{config.ACI_FIELD_CONTAINERS_ENVS}"] is incorrect.' - ) + return workingDir + + +def extract_command(container_json: Any): + # parse command + command = case_insensitive_dict_get( + container_json, config.ACI_FIELD_CONTAINERS_COMMAND + ) + if not isinstance(command, list): + eprint( + f'Field ["{config.ACI_FIELD_CONTAINERS}"]' + + f'["{config.ACI_FIELD_CONTAINERS_COMMAND}"] must be list of Strings.' + ) + return command - environmentRules.append( - { - config.POLICY_FIELD_CONTAINERS_ELEMENTS_ENVS_RULE: f"{name}={value}", - config.POLICY_FIELD_CONTAINERS_ELEMENTS_ENVS_STRATEGY: strategy, - # default value for "required" is False - config.POLICY_FIELD_CONTAINERS_ELEMENTS_REQUIRED: required - if required is not None - else False, - } - ) - # parse command - command = case_insensitive_dict_get( - container_json, config.ACI_FIELD_CONTAINERS_COMMAND - ) - if not isinstance(command, list): +def extract_mounts(container_json: Any): + # parse mounts + mounts = case_insensitive_dict_get( + container_json, config.ACI_FIELD_CONTAINERS_MOUNTS + ) + _mounts = [] + if mounts: + if not isinstance(mounts, list): eprint( f'Field ["{config.ACI_FIELD_CONTAINERS}"]' - + f'["{config.ACI_FIELD_CONTAINERS_COMMAND}"] must be list of Strings.' + + f'["{config.ACI_FIELD_CONTAINERS_MOUNTS}"] must be list of Mount configuration.' ) - # parse working directory - workingDir = case_insensitive_dict_get( - container_json, config.ACI_FIELD_CONTAINERS_WORKINGDIR - ) - # check workingDir is an absolute path if user specified - if workingDir: - if not isinstance(workingDir, str): + for m in mounts: + mount_type = case_insensitive_dict_get( + m, config.ACI_FIELD_CONTAINERS_MOUNTS_TYPE + ) + if mount_type not in config.MOUNT_SOURCE_TABLE: eprint( f'Field ["{config.ACI_FIELD_CONTAINERS}"]' - + f'["{config.ACI_FIELD_CONTAINERS_WORKINGDIR}"] must be a String.' + + f'["{config.ACI_FIELD_CONTAINERS_MOUNTS}"]' + + f'["{config.ACI_FIELD_CONTAINERS_MOUNTS_TYPE}"]' + + "can only be following values:" + + f'{",".join(list(config.MOUNT_SOURCE_TABLE.keys()))} .' ) - if not os.path.isabs(workingDir): + + mount_path = case_insensitive_dict_get( + m, config.ACI_FIELD_CONTAINERS_MOUNTS_PATH + ) + if not mount_path: eprint( f'Field ["{config.ACI_FIELD_CONTAINERS}"]' - + f'["{config.ACI_FIELD_CONTAINERS_WORKINGDIR}"] with value: {workingDir} is not absolute path.' + + f'["{config.ACI_FIELD_CONTAINERS_MOUNTS}"]' + + f'["{config.ACI_FIELD_CONTAINERS_MOUNTS_PATH}"] is empty or can not be found.' ) - # parse mounts - mounts = case_insensitive_dict_get( - container_json, config.ACI_FIELD_CONTAINERS_MOUNTS - ) - _mounts = [] - if mounts: - if not isinstance(mounts, list): + mount_readonly = case_insensitive_dict_get( + m, config.ACI_FIELD_CONTAINERS_MOUNTS_READONLY + ) + if mount_readonly is not None and not isinstance(mount_readonly, bool): eprint( f'Field ["{config.ACI_FIELD_CONTAINERS}"]' - + f'["{config.ACI_FIELD_CONTAINERS_MOUNTS}"] must be list of Mount configuration.' + + f'["{config.ACI_FIELD_CONTAINERS_MOUNTS}"]' + + f'["{config.ACI_FIELD_CONTAINERS_MOUNTS_READONLY}"] can only be boolean value.' ) - for m in mounts: - mount_type = case_insensitive_dict_get( - m, config.ACI_FIELD_CONTAINERS_MOUNTS_TYPE - ) - if mount_type not in config.MOUNT_SOURCE_TABLE: - eprint( - f'Field ["{config.ACI_FIELD_CONTAINERS}"]' - + f'["{config.ACI_FIELD_CONTAINERS_MOUNTS}"]' - + f'["{config.ACI_FIELD_CONTAINERS_MOUNTS_TYPE}"]' - + "can only be following values:" - + f'{",".join(list(config.MOUNT_SOURCE_TABLE.keys()))} .' - ) - - mount_path = case_insensitive_dict_get( - m, config.ACI_FIELD_CONTAINERS_MOUNTS_PATH - ) - if not mount_path: - eprint( - f'Field ["{config.ACI_FIELD_CONTAINERS}"]' - + f'["{config.ACI_FIELD_CONTAINERS_MOUNTS}"]' - + f'["{config.ACI_FIELD_CONTAINERS_MOUNTS_PATH}"] is empty or can not be found.' - ) - - mount_readonly = case_insensitive_dict_get( - m, config.ACI_FIELD_CONTAINERS_MOUNTS_READONLY - ) - if mount_readonly is not None and not isinstance(mount_readonly, bool): - eprint( - f'Field ["{config.ACI_FIELD_CONTAINERS}"]' - + f'["{config.ACI_FIELD_CONTAINERS_MOUNTS}"]' - + f'["{config.ACI_FIELD_CONTAINERS_MOUNTS_READONLY}"] can only be boolean value.' - ) - - # readonly default to False if not specified - if mount_readonly is None: - mount_readonly = False + # readonly default to False if not specified + if mount_readonly is None: + mount_readonly = False + + _mounts.append(m) + return _mounts + + +def extract_excess_process(container_json: Any, container_image: str, debug_mode: bool): + if ":" in container_image: + base = container_image.split(":")[0] + else: + base = container_image + # convert to shorthand: base = containerImage.split(":")[0] if ":" in containerImage else containerImage + # get the exec_processes info used as a liveness probe + exec_processes = case_insensitive_dict_get( + container_json, config.ACI_FIELD_CONTAINERS_EXEC_PROCESSES + ) + exec_processes_output = [] + if exec_processes: + if not isinstance(exec_processes, list): + eprint( + f'Field ["{config.ACI_FIELD_CONTAINERS}"]' + + f'["{config.ACI_FIELD_CONTAINERS_EXEC_PROCESSES}"] can only be a list.' + ) - _mounts.append(m) + for exec_processes_item in exec_processes: - _allow_elevated = case_insensitive_dict_get( - container_json, config.ACI_FIELD_CONTAINERS_ALLOW_ELEVATED - ) - if _allow_elevated: - if not isinstance(_allow_elevated, bool): + exec_command = case_insensitive_dict_get( + exec_processes_item, config.ACI_FIELD_CONTAINERS_COMMAND + ) + if not isinstance(exec_command, list) and all( + map(lambda x: isinstance(x, str), exec_command) + ): eprint( f'Field ["{config.ACI_FIELD_CONTAINERS}"]' - + f'["{config.ACI_FIELD_CONTAINERS_ALLOW_ELEVATED}"] can only be boolean value.' + + f'["{config.ACI_FIELD_CONTAINERS_EXEC_PROCESSES}"]' + + f'["{config.ACI_FIELD_CONTAINERS_COMMAND}"]' + + "can only be a list of strings." ) - else: - # default is allow_elevated should be true - _allow_elevated = True - if ":" in containerImage: - base = containerImage.split(":")[0] - else: - base = containerImage - - # get the exec_processes info used as a liveness probe - exec_processes = case_insensitive_dict_get( - container_json, config.ACI_FIELD_CONTAINERS_EXEC_PROCESSES - ) - exec_processes_output = [] - if exec_processes: - if not isinstance(exec_processes, list): + exec_signals = case_insensitive_dict_get( + exec_processes_item, + config.ACI_FIELD_CONTAINERS_SIGNAL_CONTAINER_PROCESSES, + ) + if not isinstance(exec_signals, list) and all( + map(lambda x: isinstance(x, int), exec_signals) + ): eprint( f'Field ["{config.ACI_FIELD_CONTAINERS}"]' - + f'["{config.ACI_FIELD_CONTAINERS_EXEC_PROCESSES}"] can only be a list.' + + f'["{config.ACI_FIELD_CONTAINERS_EXEC_PROCESSES}"]' + + f'["{config.ACI_FIELD_CONTAINERS_COMMAND}"]' + + "can only be a list of integers." ) - for exec_processes_item in exec_processes: + # can either be bool or undefined so give it a default value of False if not a sidecar + default_exec_stdio = ( + True if base in config.BASELINE_SIDECAR_CONTAINERS else debug_mode + ) + exec_stdio_value = case_insensitive_dict_get( + exec_processes_item, config.ACI_FIELD_CONTAINERS_ALLOW_STDIO_ACCESS + ) + exec_stdio_access = ( + exec_stdio_value if exec_stdio_value is not None else default_exec_stdio + ) - exec_command = case_insensitive_dict_get( - exec_processes_item, config.ACI_FIELD_CONTAINERS_COMMAND - ) - if not isinstance(exec_command, list) and all( - map(lambda x: isinstance(x, str), exec_command) - ): - eprint( - f'Field ["{config.ACI_FIELD_CONTAINERS}"]' - + f'["{config.ACI_FIELD_CONTAINERS_EXEC_PROCESSES}"]' - + f'["{config.ACI_FIELD_CONTAINERS_COMMAND}"]' - + "can only be a list of strings." - ) - - exec_signals = case_insensitive_dict_get( - exec_processes_item, - config.ACI_FIELD_CONTAINERS_SIGNAL_CONTAINER_PROCESSES, - ) - if not isinstance(exec_signals, list) and all( - map(lambda x: isinstance(x, int), exec_signals) - ): - eprint( - f'Field ["{config.ACI_FIELD_CONTAINERS}"]' - + f'["{config.ACI_FIELD_CONTAINERS_EXEC_PROCESSES}"]' - + f'["{config.ACI_FIELD_CONTAINERS_COMMAND}"]' - + "can only be a list of integers." - ) - - # can either be bool or undefined so give it a default value of False if not a sidecar - default_exec_stdio = ( - True if base in config.BASELINE_SIDECAR_CONTAINERS else debug_mode - ) - exec_stdio_value = case_insensitive_dict_get( - exec_processes_item, config.ACI_FIELD_CONTAINERS_ALLOW_STDIO_ACCESS - ) - exec_stdio_access = ( - exec_stdio_value - if exec_stdio_value is not None - else default_exec_stdio + if not isinstance(exec_stdio_access, bool): + eprint( + f'Field ["{config.ACI_FIELD_CONTAINERS}"]' + + f'["{config.ACI_FIELD_CONTAINERS_EXEC_PROCESSES}"]' + + f'["{config.ACI_FIELD_CONTAINERS_ALLOW_STDIO_ACCESS}"]' + + "can only be a boolean." ) - if not isinstance(exec_stdio_access, bool): - eprint( - f'Field ["{config.ACI_FIELD_CONTAINERS}"]' - + f'["{config.ACI_FIELD_CONTAINERS_EXEC_PROCESSES}"]' - + f'["{config.ACI_FIELD_CONTAINERS_ALLOW_STDIO_ACCESS}"]' - + "can only be a boolean." - ) + exec_processes_output.append( + { + config.POLICY_FIELD_CONTAINERS_ELEMENTS_COMMANDS: exec_command, + config.POLICY_FIELD_CONTAINER_SIGNAL_CONTAINER_PROCESSES: exec_signals, + config.POLICY_FIELD_CONTAINERS_ALLOW_STDIO_ACCESS: exec_stdio_access, + } + ) + return exec_processes_output - exec_processes_output.append( - { - config.POLICY_FIELD_CONTAINERS_ELEMENTS_COMMANDS: exec_command, - config.POLICY_FIELD_CONTAINER_SIGNAL_CONTAINER_PROCESSES: exec_signals, - config.POLICY_FIELD_CONTAINERS_ALLOW_STDIO_ACCESS: exec_stdio_access, - } - ) - # get the signals info used as a liveness probe - signals = ( - case_insensitive_dict_get( - container_json, config.ACI_FIELD_CONTAINERS_SIGNAL_CONTAINER_PROCESSES +# change +def extract_allow_elevated(container_json: Any): + _allow_elevated = case_insensitive_dict_get( + container_json, config.ACI_FIELD_CONTAINERS_ALLOW_ELEVATED + ) + if _allow_elevated: + if not isinstance(_allow_elevated, bool): + eprint( + f'Field ["{config.ACI_FIELD_CONTAINERS}"]' + + f'["{config.ACI_FIELD_CONTAINERS_ALLOW_ELEVATED}"] can only be boolean value.' ) - or [] + else: + # default is allow_elevated should be true + _allow_elevated = True + return _allow_elevated + + +def extract_allow_studio_access(container_json: Any): + # get the field for Standard IO access, default to true + allow_stdio_value = case_insensitive_dict_get( + container_json, config.ACI_FIELD_CONTAINERS_ALLOW_STDIO_ACCESS + ) + allow_stdio_access = allow_stdio_value if allow_stdio_value is not None else True + return allow_stdio_access + + +def extract_get_signals(container_json: Any): + # get the signals info used as a liveness probe + signals = ( + case_insensitive_dict_get( + container_json, config.ACI_FIELD_CONTAINERS_SIGNAL_CONTAINER_PROCESSES ) - if signals: - if not isinstance(signals, list): + or [] + ) + if signals: + if not isinstance(signals, list): + eprint( + f'Field ["{config.ACI_FIELD_CONTAINERS}"]' + + '["{config.ACI_FIELD_CONTAINERS_SIGNAL_CONTAINER_PROCESSES}"]' + + "can only be a list." + ) + + for signals_item in signals: + if not isinstance(signals_item, int): eprint( f'Field ["{config.ACI_FIELD_CONTAINERS}"]' + '["{config.ACI_FIELD_CONTAINERS_SIGNAL_CONTAINER_PROCESSES}"]' - + "can only be a list." + + "can only be an integer." ) + return signals - for signals_item in signals: - if not isinstance(signals_item, int): - eprint( - f'Field ["{config.ACI_FIELD_CONTAINERS}"]' - + '["{config.ACI_FIELD_CONTAINERS_SIGNAL_CONTAINER_PROCESSES}"]' - + "can only be an integer." - ) - - # get the field for Standard IO access, default to true - allow_stdio_value = case_insensitive_dict_get( - container_json, config.ACI_FIELD_CONTAINERS_ALLOW_STDIO_ACCESS - ) - allow_stdio_access = ( - allow_stdio_value if allow_stdio_value is not None else True - ) +class ContainerImage: + # pylint: disable=too-many-instance-attributes + + @classmethod + def from_json( + cls, container_json: Any, debug_mode: bool = False + ) -> "ContainerImage": + + container_image = extract_container_image(container_json) + id_val = extract_id(container_json) + environment_rules = extract_env_rules(container_json=container_json) + command = extract_command(container_json) + working_dir = extract_working_dir(container_json) + mounts = extract_mounts(container_json) + allow_elevated = extract_allow_elevated(container_json) + exec_processes = extract_excess_process( + container_json, container_image, debug_mode + ) + signals = extract_get_signals(container_json) + allow_studio_access = extract_allow_studio_access(container_json) return ContainerImage( - containerImage=containerImage, - environmentRules=environmentRules, + containerImage=container_image, + environmentRules=environment_rules, command=command, - workingDir=workingDir, - mounts=_mounts, - allow_elevated=_allow_elevated, + workingDir=working_dir, + mounts=mounts, + allow_elevated=allow_elevated, extraEnvironmentRules=[], - execProcesses=exec_processes_output, + execProcesses=exec_processes, signals=signals, - allowStdioAccess=allow_stdio_access, + allowStdioAccess=allow_studio_access, id_val=id_val, ) @@ -367,8 +404,8 @@ def _get_environment_rules(self) -> List[Dict[str, Any]]: if rule[config.ACI_FIELD_CONTAINERS_ENVS_NAME] not in env_var_names: out_rules.append( { - config.POLICY_FIELD_CONTAINERS_ELEMENTS_ENVS_RULE: - f"{rule[config.ACI_FIELD_CONTAINERS_ENVS_NAME]}=" + # pylint: disable=line-too-long + config.POLICY_FIELD_CONTAINERS_ELEMENTS_ENVS_RULE: f"{rule[config.ACI_FIELD_CONTAINERS_ENVS_NAME]}=" + f"{rule[config.ACI_FIELD_CONTAINERS_ENVS_VALUE]}", config.POLICY_FIELD_CONTAINERS_ELEMENTS_ENVS_STRATEGY: rule[ config.ACI_FIELD_CONTAINERS_ENVS_STRATEGY From 38bd22aa09dc7a2ecfa2ec205f2b6434d39c8dc0 Mon Sep 17 00:00:00 2001 From: Steven Dong Date: Thu, 2 Feb 2023 15:38:28 -0500 Subject: [PATCH 2/2] remove pylint and fix a few small issues --- src/confcom/azext_confcom/container.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/confcom/azext_confcom/container.py b/src/confcom/azext_confcom/container.py index f98511fd8f4..1e903abfb8f 100644 --- a/src/confcom/azext_confcom/container.py +++ b/src/confcom/azext_confcom/container.py @@ -162,12 +162,9 @@ def extract_mounts(container_json: Any): return _mounts -def extract_excess_process(container_json: Any, container_image: str, debug_mode: bool): - if ":" in container_image: - base = container_image.split(":")[0] - else: - base = container_image - # convert to shorthand: base = containerImage.split(":")[0] if ":" in containerImage else containerImage +def extract_exec_process(container_json: Any, container_image: str, debug_mode: bool): + base = container_image.split(":")[0] if ":" in container_image else container_image + # get the exec_processes info used as a liveness probe exec_processes = case_insensitive_dict_get( container_json, config.ACI_FIELD_CONTAINERS_EXEC_PROCESSES @@ -276,7 +273,7 @@ def extract_get_signals(container_json: Any): if not isinstance(signals, list): eprint( f'Field ["{config.ACI_FIELD_CONTAINERS}"]' - + '["{config.ACI_FIELD_CONTAINERS_SIGNAL_CONTAINER_PROCESSES}"]' + + f'["{config.ACI_FIELD_CONTAINERS_SIGNAL_CONTAINER_PROCESSES}"]' + "can only be a list." ) @@ -284,7 +281,7 @@ def extract_get_signals(container_json: Any): if not isinstance(signals_item, int): eprint( f'Field ["{config.ACI_FIELD_CONTAINERS}"]' - + '["{config.ACI_FIELD_CONTAINERS_SIGNAL_CONTAINER_PROCESSES}"]' + + f'["{config.ACI_FIELD_CONTAINERS_SIGNAL_CONTAINER_PROCESSES}"]' + "can only be an integer." ) return signals @@ -305,7 +302,7 @@ def from_json( working_dir = extract_working_dir(container_json) mounts = extract_mounts(container_json) allow_elevated = extract_allow_elevated(container_json) - exec_processes = extract_excess_process( + exec_processes = extract_exec_process( container_json, container_image, debug_mode ) signals = extract_get_signals(container_json) @@ -404,8 +401,8 @@ def _get_environment_rules(self) -> List[Dict[str, Any]]: if rule[config.ACI_FIELD_CONTAINERS_ENVS_NAME] not in env_var_names: out_rules.append( { - # pylint: disable=line-too-long - config.POLICY_FIELD_CONTAINERS_ELEMENTS_ENVS_RULE: f"{rule[config.ACI_FIELD_CONTAINERS_ENVS_NAME]}=" + config.POLICY_FIELD_CONTAINERS_ELEMENTS_ENVS_RULE: + f"{rule[config.ACI_FIELD_CONTAINERS_ENVS_NAME]}=" + f"{rule[config.ACI_FIELD_CONTAINERS_ENVS_VALUE]}", config.POLICY_FIELD_CONTAINERS_ELEMENTS_ENVS_STRATEGY: rule[ config.ACI_FIELD_CONTAINERS_ENVS_STRATEGY