diff --git a/ansible.changes b/ansible.changes index 5c6e395..ac1136b 100644 --- a/ansible.changes +++ b/ansible.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Mon Jul 13 17:53:58 UTC 2020 - Andrey Karepin + +- added ansible_bugfix_640.diff to fix gh#ansible-collections/community.general#640 + ------------------------------------------------------------------- Mon Jun 22 23:10:23 UTC 2020 - Michael Ströder diff --git a/ansible.spec b/ansible.spec index fffe14c..0104d51 100644 --- a/ansible.spec +++ b/ansible.spec @@ -229,6 +229,8 @@ URL: https://ansible.com/ Source: https://releases.ansible.com/ansible/ansible-%{version}.tar.gz Source1: https://releases.ansible.com/ansible/ansible-%{version}.tar.gz.sha Source99: ansible-rpmlintrc +# PATCH-FEATURE-UPSTREAM ansible_bugfix_640.diff gh#ansible-collections/community.general#640 +Patch: ansible_bugfix_640.diff BuildArch: noarch # extented documentation %if 0%{?with_docs} @@ -288,6 +290,9 @@ automatically. %prep %setup -q -n ansible-%{version} +pushd lib/ansible +%patch -p2 +popd for file in .git_keep .travis.yml ; do find . -name "$file" -delete @@ -298,7 +303,6 @@ find contrib/ -type f -exec chmod 644 {} + find ./ -type f -exec \ sed -i '1s|^#!%{_bindir}/env |#!%{_bindir}/|' {} \; - %build %{python} setup.py build %if 0%{?with_docs} diff --git a/ansible_bugfix_640.diff b/ansible_bugfix_640.diff new file mode 100644 index 0000000..88eea20 --- /dev/null +++ b/ansible_bugfix_640.diff @@ -0,0 +1,278 @@ +--- a/plugins/modules/cloud/docker/docker_container.py ++++ b/plugins/modules/cloud/docker/docker_container.py +@@ -1067,6 +1067,9 @@ from distutils.version import LooseVersi + from time import sleep + + from ansible.module_utils.common.text.formatters import human_to_bytes ++from ansible.module_utils.six import string_types ++from ansible.module_utils._text import to_native, to_text ++ + from ansible.module_utils.docker.common import ( + AnsibleDockerClient, + DifferenceTracker, +@@ -1080,7 +1083,6 @@ from ansible.module_utils.docker.common + DOCKER_COMMON_ARGS, + RequestException, + ) +-from ansible.module_utils.six import string_types + + try: + from docker import utils +@@ -1269,7 +1271,7 @@ class TaskParameters(DockerBaseClass): + if self.groups: + # In case integers are passed as groups, we need to convert them to + # strings as docker internally treats them as strings. +- self.groups = [str(g) for g in self.groups] ++ self.groups = [to_text(g, errors='surrogate_or_strict') for g in self.groups] + + for param_name in REQUIRES_CONVERSION_TO_BYTES: + if client.module.params.get(param_name): +@@ -1301,7 +1303,7 @@ class TaskParameters(DockerBaseClass): + try: + self.healthcheck, self.disable_healthcheck = parse_healthcheck(self.healthcheck) + except ValueError as e: +- self.fail(str(e)) ++ self.fail(to_native(e)) + + self.exp_links = None + self.volume_binds = self._get_volume_binds(self.volumes) +@@ -1328,12 +1330,12 @@ class TaskParameters(DockerBaseClass): + + if self.entrypoint: + # convert from list to str. +- self.entrypoint = ' '.join([str(x) for x in self.entrypoint]) ++ self.entrypoint = ' '.join([to_text(x, errors='surrogate_or_strict') for x in self.entrypoint]) + + if self.command: + # convert from list to str + if isinstance(self.command, list): +- self.command = ' '.join([str(x) for x in self.command]) ++ self.command = ' '.join([to_text(x, errors='surrogate_or_strict') for x in self.command]) + + self.mounts_opt, self.expected_mounts = self._process_mounts() + +@@ -1587,7 +1589,7 @@ class TaskParameters(DockerBaseClass): + + binds = {} + for port in self.published_ports: +- parts = split_colon_ipv6(str(port), self.client) ++ parts = split_colon_ipv6(to_text(port, errors='surrogate_or_strict'), self.client) + container_port = parts[-1] + protocol = '' + if '/' in container_port: +@@ -1657,7 +1659,7 @@ class TaskParameters(DockerBaseClass): + exposed = [] + if self.exposed_ports: + for port in self.exposed_ports: +- port = str(port).strip() ++ port = to_text(port, errors='surrogate_or_strict').strip() + protocol = 'tcp' + match = re.search(r'(/.+$)', port) + if match: +@@ -1751,9 +1753,10 @@ class TaskParameters(DockerBaseClass): + if not isinstance(v, string_types): + self.client.module.warn( + "Non-string value found for log_options option '%s'. The value is automatically converted to '%s'. " +- "If this is not correct, or you want to avoid such warnings, please quote the value." % (k, str(v)) ++ "If this is not correct, or you want to avoid such warnings, please quote the value." % ( ++ k, to_text(v, errors='surrogate_or_strict')) + ) +- v = str(v) ++ v = to_text(v, errors='surrogate_or_strict') + self.log_options[k] = v + options['Config'][k] = v + +@@ -1787,13 +1790,13 @@ class TaskParameters(DockerBaseClass): + if self.env_file: + parsed_env_file = utils.parse_env_file(self.env_file) + for name, value in parsed_env_file.items(): +- final_env[name] = str(value) ++ final_env[name] = to_text(value, errors='surrogate_or_strict') + if self.env: + for name, value in self.env.items(): + if not isinstance(value, string_types): + self.fail("Non-string value found for env option. Ambiguous env options must be " + "wrapped in quotes to avoid them being interpreted. Key: %s" % (name, )) +- final_env[name] = str(value) ++ final_env[name] = to_text(value, errors='surrogate_or_strict') + return final_env + + def _get_network_id(self, network_name): +@@ -1804,7 +1807,7 @@ class TaskParameters(DockerBaseClass): + network_id = network['Id'] + break + except Exception as exc: +- self.fail("Error getting network id for %s - %s" % (network_name, str(exc))) ++ self.fail("Error getting network id for %s - %s" % (network_name, to_native(exc))) + return network_id + + def _process_mounts(self): +@@ -2160,7 +2163,7 @@ class Container(DockerBaseClass): + if not minimal_version.get('supported', True): + continue + compare = self.parameters.client.comparisons[self.parameters_map.get(key, key)] +- self.log('check differences %s %s vs %s (%s)' % (key, getattr(self.parameters, key), str(value), compare)) ++ self.log('check differences %s %s vs %s (%s)' % (key, getattr(self.parameters, key), to_text(value, errors='surrogate_or_strict'), compare)) + if getattr(self.parameters, key, None) is not None: + match = self._compare(getattr(self.parameters, key), value, compare) + +@@ -2183,7 +2186,7 @@ class Container(DockerBaseClass): + else: + # We sort the list of dictionaries by using the sorted items of a dict as its key. + def sort_key_fn(x): +- return sorted((a, str(b)) for a, b in x.items()) ++ return sorted((a, to_text(b, errors='surrogate_or_strict')) for a, b in x.items()) + if p is not None: + p = sorted(p, key=sort_key_fn) + if c is not None: +@@ -2363,9 +2366,9 @@ class Container(DockerBaseClass): + elif isinstance(config[0], tuple): + expected_bound_ports[container_port] = [] + for host_ip, host_port in config: +- expected_bound_ports[container_port].append({'HostIp': host_ip, 'HostPort': str(host_port)}) ++ expected_bound_ports[container_port].append({'HostIp': host_ip, 'HostPort': to_text(host_port, errors='surrogate_or_strict')}) + else: +- expected_bound_ports[container_port] = [{'HostIp': config[0], 'HostPort': str(config[1])}] ++ expected_bound_ports[container_port] = [{'HostIp': config[0], 'HostPort': to_text(config[1], errors='surrogate_or_strict')}] + return expected_bound_ports + + def _get_expected_links(self): +@@ -2482,7 +2485,7 @@ class Container(DockerBaseClass): + image_ports = [self._normalize_port(p) for p in image_exposed_ports.keys()] + param_ports = [] + if self.parameters.ports: +- param_ports = [str(p[0]) + '/' + p[1] for p in self.parameters.ports] ++ param_ports = [to_text(p[0], errors='surrogate_or_strict') + '/' + p[1] for p in self.parameters.ports] + result = list(set(image_ports + param_ports)) + self.log(result, pretty_print=True) + return result +@@ -2506,7 +2509,7 @@ class Container(DockerBaseClass): + return None + result = dict() + for key, value in config_sysctls.items(): +- result[key] = str(value) ++ result[key] = to_text(value, errors='surrogate_or_strict') + return result + + def _get_expected_cmd(self): +@@ -2688,7 +2691,7 @@ class ContainerManager(DockerBaseClass): + self.client.unpause(container=container.Id) + except Exception as exc: + self.fail("Error %s container %s: %s" % ( +- "pausing" if self.parameters.paused else "unpausing", container.Id, str(exc) ++ "pausing" if self.parameters.paused else "unpausing", container.Id, to_native(exc) + )) + container = self._get_container(container.Id) + self.results['changed'] = True +@@ -2810,7 +2813,7 @@ class ContainerManager(DockerBaseClass): + self.client.disconnect_container_from_network(container.Id, diff['parameter']['id']) + except Exception as exc: + self.fail("Error disconnecting container from network %s - %s" % (diff['parameter']['name'], +- str(exc))) ++ to_native(exc))) + # connect to the network + params = dict() + for para in ('ipv4_address', 'ipv6_address', 'links', 'aliases'): +@@ -2823,7 +2826,7 @@ class ContainerManager(DockerBaseClass): + self.log(params, pretty_print=True) + self.client.connect_container_to_network(container.Id, diff['parameter']['id'], **params) + except Exception as exc: +- self.fail("Error connecting container to network %s - %s" % (diff['parameter']['name'], str(exc))) ++ self.fail("Error connecting container to network %s - %s" % (diff['parameter']['name'], to_native(exc))) + return self._get_container(container.Id) + + def _purge_networks(self, container, networks): +@@ -2834,7 +2837,7 @@ class ContainerManager(DockerBaseClass): + self.client.disconnect_container_from_network(container.Id, network['name']) + except Exception as exc: + self.fail("Error disconnecting container from network %s - %s" % (network['name'], +- str(exc))) ++ to_native(exc))) + return self._get_container(container.Id) + + def container_create(self, image, create_parameters): +@@ -2849,7 +2852,7 @@ class ContainerManager(DockerBaseClass): + new_container = self.client.create_container(image, **create_parameters) + self.client.report_warnings(new_container) + except Exception as exc: +- self.fail("Error creating container: %s" % str(exc)) ++ self.fail("Error creating container: %s" % to_native(exc)) + return self._get_container(new_container['Id']) + return new_container + +@@ -2861,7 +2864,7 @@ class ContainerManager(DockerBaseClass): + try: + self.client.start(container=container_id) + except Exception as exc: +- self.fail("Error starting container %s: %s" % (container_id, str(exc))) ++ self.fail("Error starting container %s: %s" % (container_id, to_native(exc))) + + if not self.parameters.detach: + if self.client.docker_py_version >= LooseVersion('3.0'): +@@ -2913,21 +2916,21 @@ class ContainerManager(DockerBaseClass): + # New docker daemon versions do not allow containers to be removed + # if they are paused. Make sure we don't end up in an infinite loop. + if count == 3: +- self.fail("Error removing container %s (tried to unpause three times): %s" % (container_id, str(exc))) ++ self.fail("Error removing container %s (tried to unpause three times): %s" % (container_id, to_native(exc))) + count += 1 + # Unpause + try: + self.client.unpause(container=container_id) + except Exception as exc2: +- self.fail("Error unpausing container %s for removal: %s" % (container_id, str(exc2))) ++ self.fail("Error unpausing container %s for removal: %s" % (container_id, to_native(exc2))) + # Now try again + continue + if 'removal of container ' in exc.explanation and ' is already in progress' in exc.explanation: + pass + else: +- self.fail("Error removing container %s: %s" % (container_id, str(exc))) ++ self.fail("Error removing container %s: %s" % (container_id, to_native(exc))) + except Exception as exc: +- self.fail("Error removing container %s: %s" % (container_id, str(exc))) ++ self.fail("Error removing container %s: %s" % (container_id, to_native(exc))) + # We only loop when explicitly requested by 'continue' + break + return response +@@ -2943,7 +2946,7 @@ class ContainerManager(DockerBaseClass): + result = self.client.update_container(container_id, **update_parameters) + self.client.report_warnings(result) + except Exception as exc: +- self.fail("Error updating container %s: %s" % (container_id, str(exc))) ++ self.fail("Error updating container %s: %s" % (container_id, to_native(exc))) + return self._get_container(container_id) + + def container_kill(self, container_id): +@@ -2970,7 +2973,7 @@ class ContainerManager(DockerBaseClass): + else: + dummy = self.client.restart(container_id) + except Exception as exc: +- self.fail("Error restarting container %s: %s" % (container_id, str(exc))) ++ self.fail("Error restarting container %s: %s" % (container_id, to_native(exc))) + return self._get_container(container_id) + + def container_stop(self, container_id): +@@ -2993,18 +2996,18 @@ class ContainerManager(DockerBaseClass): + # New docker daemon versions do not allow containers to be removed + # if they are paused. Make sure we don't end up in an infinite loop. + if count == 3: +- self.fail("Error removing container %s (tried to unpause three times): %s" % (container_id, str(exc))) ++ self.fail("Error removing container %s (tried to unpause three times): %s" % (container_id, to_native(exc))) + count += 1 + # Unpause + try: + self.client.unpause(container=container_id) + except Exception as exc2: +- self.fail("Error unpausing container %s for removal: %s" % (container_id, str(exc2))) ++ self.fail("Error unpausing container %s for removal: %s" % (container_id, to_native(exc2))) + # Now try again + continue +- self.fail("Error stopping container %s: %s" % (container_id, str(exc))) ++ self.fail("Error stopping container %s: %s" % (container_id, to_native(exc))) + except Exception as exc: +- self.fail("Error stopping container %s: %s" % (container_id, str(exc))) ++ self.fail("Error stopping container %s: %s" % (container_id, to_native(exc))) + # We only loop when explicitly requested by 'continue' + break + return response