diff --git a/ansible/library/kolla_toolbox.py b/ansible/library/kolla_toolbox.py index acfc8a15ae..b3bc82dc42 100644 --- a/ansible/library/kolla_toolbox.py +++ b/ansible/library/kolla_toolbox.py @@ -12,11 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -from distutils.version import StrictVersion import json import re -from ansible.module_utils.ansible_release import __version__ as ansible_version from ansible.module_utils.basic import AnsibleModule from ast import literal_eval @@ -117,17 +115,14 @@ def gen_commandline(params): if params.get('module_name'): command.extend(['-m', params.get('module_name')]) if params.get('module_args'): - if StrictVersion(ansible_version) < StrictVersion('2.11.0'): - module_args = params.get('module_args') - else: - try: - module_args = literal_eval(params.get('module_args')) - except SyntaxError: - if not isinstance(params.get('module_args'), str): - raise + try: + module_args = literal_eval(params.get('module_args')) + except SyntaxError: + if not isinstance(params.get('module_args'), str): + raise - # account for string arguments - module_args = split(params.get('module_args')) + # account for string arguments + module_args = split(params.get('module_args')) if isinstance(module_args, dict): module_args = ' '.join("{}='{}'".format(key, value) for key, value in module_args.items()) @@ -147,11 +142,6 @@ def get_docker_client(): return docker.APIClient -def docker_supports_environment_in_exec(client): - docker_version = StrictVersion(client.api_version) - return docker_version >= StrictVersion('1.25') - - def use_docker(module): client = get_docker_client()( version=module.params.get('api_version'), @@ -167,79 +157,43 @@ def use_docker(module): if 'user' in module.params: kwargs['user'] = module.params['user'] - # NOTE(mgoddard): Docker 1.12 has API version 1.24, and was installed by - # kolla-ansible bootstrap-servers on Rocky and earlier releases. This API - # version does not have support for specifying environment variables for - # exec jobs, which is necessary to use the Ansible JSON output formatter. - # While we continue to support this version of Docker, fall back to the old - # regex-based method for API version 1.24 and earlier. - # TODO(mgoddard): Remove this conditional (keep the if) when we require - # Docker API version 1.25+. - if docker_supports_environment_in_exec(client): - # Use the JSON output formatter, so that we can parse it. - environment = {"ANSIBLE_STDOUT_CALLBACK": "json", - "ANSIBLE_LOAD_CALLBACK_PLUGINS": "True"} - job = client.exec_create(kolla_toolbox, command_line, - environment=environment, **kwargs) - json_output = client.exec_start(job) + # Use the JSON output formatter, so that we can parse it. + environment = {"ANSIBLE_STDOUT_CALLBACK": "json", + "ANSIBLE_LOAD_CALLBACK_PLUGINS": "True"} + job = client.exec_create(kolla_toolbox, command_line, + environment=environment, **kwargs) + json_output = client.exec_start(job) - try: - output = json.loads(json_output) - except Exception: - module.fail_json( - msg='Can not parse the inner module output: %s' % json_output) + try: + output = json.loads(json_output) + except Exception: + module.fail_json( + msg='Can not parse the inner module output: %s' % json_output) - # Expected format is the following: - # { - # "plays": [ - # { - # "tasks": [ - # { - # "hosts": { - # "localhost": { - # - # } - # } - # } - # ] - # { - # ] - # } - try: - ret = output['plays'][0]['tasks'][0]['hosts']['localhost'] - except (KeyError, IndexError): - module.fail_json( - msg='Ansible JSON output has unexpected format: %s' % output) - - # Remove Ansible's internal variables from returned fields. - ret.pop('_ansible_no_log', None) - else: - job = client.exec_create(kolla_toolbox, command_line, **kwargs) - output = client.exec_start(job) - - for exp in [JSON_REG, NON_JSON_REG]: - m = exp.match(output) - if m: - inner_output = m.groupdict().get('stdout') - status = m.groupdict().get('status') - break - else: - module.fail_json( - msg='Can not parse the inner module output: %s' % output) - - ret = dict() - try: - ret = json.loads(inner_output) - except ValueError: - # Some modules (e.g. command) do not produce a JSON output. - # Instead, check the status, and assume changed on success. - ret['stdout'] = inner_output - if status != "SUCCESS": - ret['failed'] = True - else: - # No way to know whether changed - assume yes. - ret['changed'] = True + # Expected format is the following: + # { + # "plays": [ + # { + # "tasks": [ + # { + # "hosts": { + # "localhost": { + # + # } + # } + # } + # ] + # { + # ] + # } + try: + ret = output['plays'][0]['tasks'][0]['hosts']['localhost'] + except (KeyError, IndexError): + module.fail_json( + msg='Ansible JSON output has unexpected format: %s' % output) + # Remove Ansible's internal variables from returned fields. + ret.pop('_ansible_no_log', None) return ret diff --git a/ansible/module_utils/kolla_container_worker.py b/ansible/module_utils/kolla_container_worker.py index 4895820c6e..7fdf541758 100644 --- a/ansible/module_utils/kolla_container_worker.py +++ b/ansible/module_utils/kolla_container_worker.py @@ -28,7 +28,6 @@ class ContainerWorker(ABC): self.changed = False # Use this to store arguments to pass to exit_json(). self.result = {} - self._cgroupns_mode_supported = True self.systemd = SystemdWorker(self.params) @@ -141,8 +140,6 @@ class ContainerWorker(ABC): pass def compare_cgroupns_mode(self, container_info): - if not self._cgroupns_mode_supported: - return False new_cgroupns_mode = self.params.get('cgroupns_mode') if new_cgroupns_mode is None: # means we don't care what it is diff --git a/ansible/module_utils/kolla_docker_worker.py b/ansible/module_utils/kolla_docker_worker.py index 87beccb72a..2daf13eab9 100644 --- a/ansible/module_utils/kolla_docker_worker.py +++ b/ansible/module_utils/kolla_docker_worker.py @@ -19,8 +19,6 @@ import os from ansible.module_utils.kolla_container_worker import COMPARE_CONFIG_CMD from ansible.module_utils.kolla_container_worker import ContainerWorker -from distutils.version import StrictVersion - def get_docker_client(): return docker.APIClient @@ -38,13 +36,8 @@ class DockerWorker(ContainerWorker): self.dc = get_docker_client()(**options) - self._cgroupns_mode_supported = ( - StrictVersion(self.dc._version) >= StrictVersion('1.41')) - self._dimensions_kernel_memory_removed = ( - StrictVersion(self.dc._version) >= StrictVersion('1.42')) - - if self._dimensions_kernel_memory_removed: - self.dimension_map.pop('kernel_memory', None) + self._dimensions_kernel_memory_removed = True + self.dimension_map.pop('kernel_memory', None) def generate_tls(self): tls = {'verify': self.params.get('tls_verify')} @@ -304,12 +297,11 @@ class DockerWorker(ContainerWorker): host_config = self.dc.create_host_config(**options) - if self._cgroupns_mode_supported: - # NOTE(yoctozepto): python-docker does not support CgroupnsMode - # natively so we stuff it in manually. - cgroupns_mode = self.params.get('cgroupns_mode') - if cgroupns_mode is not None: - host_config['CgroupnsMode'] = cgroupns_mode + # NOTE(yoctozepto): python-docker does not support CgroupnsMode + # natively so we stuff it in manually. + cgroupns_mode = self.params.get('cgroupns_mode') + if cgroupns_mode is not None: + host_config['CgroupnsMode'] = cgroupns_mode # detached containers should only log to journald if self.params.get('detach'): diff --git a/tests/kolla_container_tests/test_docker_worker.py b/tests/kolla_container_tests/test_docker_worker.py index e6e6f0de21..564f93a666 100644 --- a/tests/kolla_container_tests/test_docker_worker.py +++ b/tests/kolla_container_tests/test_docker_worker.py @@ -244,22 +244,8 @@ class TestMainModule(base.BaseTestCase): result=False, some_key="some_value") - def test_sets_cgroupns_mode_supported_false(self): - self.dw = get_DockerWorker(self.fake_data['params']) - self.assertFalse(self.dw._cgroupns_mode_supported) - - def test_sets_cgroupns_mode_supported_true(self): - self.dw = get_DockerWorker(self.fake_data['params'], - docker_api_version='1.41') - self.assertTrue(self.dw._cgroupns_mode_supported) - - def test_sets_dimensions_kernelmemory_supported_true(self): - self.dw = get_DockerWorker(self.fake_data['params']) - self.assertFalse(self.dw._dimensions_kernel_memory_removed) - def test_sets_dimensions_kernelmemory_supported_false(self): - self.dw = get_DockerWorker(self.fake_data['params'], - docker_api_version='1.42') + self.dw = get_DockerWorker(self.fake_data['params']) self.assertTrue(self.dw._dimensions_kernel_memory_removed) def test_common_options_defaults(self): @@ -1416,10 +1402,10 @@ class TestAttrComp(base.BaseTestCase): self.dw.module.fail_json.assert_not_called() self.assertFalse(resp) - def test_compare_dimensions_key_no_more_supported(self): + def test_compare_dimensions_invalid_unit(self): self.fake_data['params']['dimensions'] = { 'mem_limit': '1024', 'mem_reservation': '3M', - 'memswap_limit': '2g', 'kernel_memory': '4M'} + 'memswap_limit': '2E'} container_info = dict() container_info['HostConfig'] = { 'CpuPeriod': 0, 'Memory': 1024, 'CpuQuota': 0, @@ -1428,26 +1414,8 @@ class TestAttrComp(base.BaseTestCase): 'MemoryReservation': 3 * 1024 * 1024, 'Ulimits': []} self.dw = get_DockerWorker(self.fake_data['params']) self.dw.compare_dimensions(container_info) - expected_msg = ("The dimension [kernel_memory] is no more " - "supported by Docker, please remove it from " - "yours configs or change to the new one.") - self.dw.module.fail_json.assert_called_once_with( - failed=True, msg=expected_msg) - - def test_compare_dimensions_invalid_unit(self): - self.fake_data['params']['dimensions'] = { - 'mem_limit': '1024', 'mem_reservation': '3M', - 'memswap_limit': '2g', 'kernel_memory': '4E'} - container_info = dict() - container_info['HostConfig'] = { - 'CpuPeriod': 0, 'KernelMemory': 0, 'Memory': 1024, 'CpuQuota': 0, - 'CpusetCpus': '', 'CpuShares': 0, 'BlkioWeight': 0, - 'CpusetMems': '', 'MemorySwap': 2 * 1024 * 1024 * 1024, - 'MemoryReservation': 3 * 1024 * 1024, 'Ulimits': []} - self.dw = get_DockerWorker(self.fake_data['params']) - self.dw.compare_dimensions(container_info) expected_msg = ("The docker dimension unit [e] is " - "not supported for the dimension [4E]." + "not supported for the dimension [2E]." " The currently supported units are " "['b', 'k', 'm', 'g'].") self.dw.module.fail_json.assert_called_once_with( @@ -1538,7 +1506,7 @@ class TestAttrComp(base.BaseTestCase): self.dw = get_DockerWorker(self.fake_data['params']) self.assertFalse(self.dw.compare_dimensions(container_info)) - def test_compare_dimensions_kernel_memory_1_42(self): + def test_compare_dimensions_kernel_memory_unsupported(self): self.fake_data['params']['dimensions'] = { 'kernel_memory': '1024'} container_info = dict() @@ -1547,8 +1515,7 @@ class TestAttrComp(base.BaseTestCase): 'CpusetCpus': '', 'CpuShares': 0, 'BlkioWeight': 0, 'CpusetMems': '', 'MemorySwap': 0, 'MemoryReservation': 0, 'Ulimits': []} - self.dw = get_DockerWorker(self.fake_data['params'], - docker_api_version='1.42') + self.dw = get_DockerWorker(self.fake_data['params']) self.dw.compare_dimensions(container_info) self.dw.module.exit_json.assert_called_once_with( failed=True, msg=repr("Unsupported dimensions"),