Python code modernization, 5/n (#1165)

* Address raise-missing-from.

* Address simplifiable-if-expression.

* Address unnecessary-dunder-call.

* Address unnecessary-pass.

* Address use-list-literal.

* Address unused-variable.

* Address use-dict-literal.
This commit is contained in:
Felix Fontein 2025-10-12 16:02:27 +02:00 committed by GitHub
parent cad22de628
commit c75aa5dd64
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
66 changed files with 1549 additions and 1429 deletions

View File

@ -388,18 +388,11 @@ disable=raw-checker-failed,
no-name-in-module, # TODO figure out why pylint cannot find the module no-name-in-module, # TODO figure out why pylint cannot find the module
not-an-iterable, # TODO: needs better typing info not-an-iterable, # TODO: needs better typing info
protected-access, protected-access,
raise-missing-from,
redefined-outer-name, # needed for test fixtures redefined-outer-name, # needed for test fixtures
simplifiable-if-expression,
subprocess-popen-preexec-fn, subprocess-popen-preexec-fn,
unexpected-keyword-arg, unexpected-keyword-arg,
unnecessary-dunder-call,
unnecessary-pass,
unsupported-assignment-operation, # TODO: needs better typing info unsupported-assignment-operation, # TODO: needs better typing info
unused-argument, unused-argument,
unused-variable,
use-dict-literal,
use-list-literal,
# Cannot remove yet due to inadequacy of rules # Cannot remove yet due to inadequacy of rules
inconsistent-return-statements, # doesn't notice that fail_json() does not return inconsistent-return-statements, # doesn't notice that fail_json() does not return

View File

@ -167,8 +167,8 @@ class Connection(ConnectionBase):
else: else:
try: try:
self.docker_cmd = get_bin_path("docker") self.docker_cmd = get_bin_path("docker")
except ValueError: except ValueError as exc:
raise AnsibleError("docker command not found in PATH") raise AnsibleError("docker command not found in PATH") from exc
@staticmethod @staticmethod
def _sanitize_version(version): def _sanitize_version(version):
@ -426,7 +426,7 @@ class Connection(ConnectionBase):
) )
chunks = b"" chunks = b""
for key, event in events: for key, dummy_event in events:
if key.fileobj == p.stdout: if key.fileobj == p.stdout:
chunk = p.stdout.read() chunk = p.stdout.read()
if chunk: if chunk:
@ -523,10 +523,10 @@ class Connection(ConnectionBase):
p = subprocess.Popen( p = subprocess.Popen(
args, stdin=in_file, stdout=subprocess.PIPE, stderr=subprocess.PIPE args, stdin=in_file, stdout=subprocess.PIPE, stderr=subprocess.PIPE
) )
except OSError: except OSError as exc:
raise AnsibleError( raise AnsibleError(
"docker connection requires dd command in the container to put files" "docker connection requires dd command in the container to put files"
) ) from exc
stdout, stderr = p.communicate() stdout, stderr = p.communicate()
if p.returncode != 0: if p.returncode != 0:
@ -588,10 +588,10 @@ class Connection(ConnectionBase):
stdout=out_file, stdout=out_file,
stderr=subprocess.PIPE, stderr=subprocess.PIPE,
) )
except OSError: except OSError as exc:
raise AnsibleError( raise AnsibleError(
"docker connection requires dd command in the container to put files" "docker connection requires dd command in the container to put files"
) ) from exc
stdout, stderr = pp.communicate() stdout, stderr = pp.communicate()
if pp.returncode != 0: if pp.returncode != 0:

View File

@ -158,15 +158,15 @@ class Connection(ConnectionBase):
if not_found_can_be_resource: if not_found_can_be_resource:
raise AnsibleConnectionFailure( raise AnsibleConnectionFailure(
f'Could not find container "{remote_addr}" or resource in it ({e})' f'Could not find container "{remote_addr}" or resource in it ({e})'
) ) from e
raise AnsibleConnectionFailure( raise AnsibleConnectionFailure(
f'Could not find container "{remote_addr}" ({e})' f'Could not find container "{remote_addr}" ({e})'
) ) from e
except APIError as e: except APIError as e:
if e.response is not None and e.response.status_code == 409: if e.response is not None and e.response.status_code == 409:
raise AnsibleConnectionFailure( raise AnsibleConnectionFailure(
f'The container "{remote_addr}" has been paused ({e})' f'The container "{remote_addr}" has been paused ({e})'
) ) from e
self.client.fail( self.client.fail(
f'An unexpected Docker error occurred for container "{remote_addr}": {e}' f'An unexpected Docker error occurred for container "{remote_addr}": {e}'
) )
@ -183,7 +183,7 @@ class Connection(ConnectionBase):
super().__init__(play_context, new_stdin, *args, **kwargs) super().__init__(play_context, new_stdin, *args, **kwargs)
self.client = None self.client = None
self.ids = dict() self.ids = {}
# Windows uses Powershell modules # Windows uses Powershell modules
if getattr(self._shell, "_IS_WINDOWS", False): if getattr(self._shell, "_IS_WINDOWS", False):
@ -239,7 +239,7 @@ class Connection(ConnectionBase):
host=self.get_option("remote_addr"), host=self.get_option("remote_addr"),
) )
need_stdin = True if (in_data is not None) or do_become else False need_stdin = bool((in_data is not None) or do_become)
data = { data = {
"Container": self.get_option("remote_addr"), "Container": self.get_option("remote_addr"),
@ -393,7 +393,7 @@ class Connection(ConnectionBase):
except Exception as e: except Exception as e:
raise AnsibleConnectionFailure( raise AnsibleConnectionFailure(
f'Error while determining user and group ID of current user in container "{remote_addr}": {e}\nGot value: {ids!r}' f'Error while determining user and group ID of current user in container "{remote_addr}": {e}\nGot value: {ids!r}'
) ) from e
user_id, group_id = self.ids[self.actual_user] user_id, group_id = self.ids[self.actual_user]
try: try:
@ -411,9 +411,9 @@ class Connection(ConnectionBase):
not_found_can_be_resource=True, not_found_can_be_resource=True,
) )
except DockerFileNotFound as exc: except DockerFileNotFound as exc:
raise AnsibleFileNotFound(to_native(exc)) raise AnsibleFileNotFound(to_native(exc)) from exc
except DockerFileCopyError as exc: except DockerFileCopyError as exc:
raise AnsibleConnectionFailure(to_native(exc)) raise AnsibleConnectionFailure(to_native(exc)) from exc
def fetch_file(self, in_path, out_path): def fetch_file(self, in_path, out_path):
"""Fetch a file from container to local.""" """Fetch a file from container to local."""
@ -439,9 +439,9 @@ class Connection(ConnectionBase):
not_found_can_be_resource=True, not_found_can_be_resource=True,
) )
except DockerFileNotFound as exc: except DockerFileNotFound as exc:
raise AnsibleFileNotFound(to_native(exc)) raise AnsibleFileNotFound(to_native(exc)) from exc
except DockerFileCopyError as exc: except DockerFileCopyError as exc:
raise AnsibleConnectionFailure(to_native(exc)) raise AnsibleConnectionFailure(to_native(exc)) from exc
def close(self): def close(self):
"""Terminate the connection. Nothing to do for Docker""" """Terminate the connection. Nothing to do for Docker"""

View File

@ -178,7 +178,7 @@ class Connection(ConnectionBase):
) )
chunks = b"" chunks = b""
for key, event in events: for key, dummy_event in events:
if key.fileobj == p.stdout: if key.fileobj == p.stdout:
chunk = p.stdout.read() chunk = p.stdout.read()
if chunk: if chunk:
@ -244,11 +244,13 @@ class Connection(ConnectionBase):
try: try:
with open(to_bytes(in_path, errors="surrogate_or_strict"), "rb") as in_file: with open(to_bytes(in_path, errors="surrogate_or_strict"), "rb") as in_file:
in_data = in_file.read() in_data = in_file.read()
rc, out, err = self.exec_command(cmd=["tee", out_path], in_data=in_data) rc, dummy_out, err = self.exec_command(
cmd=["tee", out_path], in_data=in_data
)
if rc != 0: if rc != 0:
raise AnsibleError(f"failed to transfer file to {out_path}: {err}") raise AnsibleError(f"failed to transfer file to {out_path}: {err}")
except IOError as e: except IOError as e:
raise AnsibleError(f"failed to transfer file to {out_path}: {e}") raise AnsibleError(f"failed to transfer file to {out_path}: {e}") from e
def fetch_file(self, in_path, out_path): def fetch_file(self, in_path, out_path):
super().fetch_file(in_path, out_path) super().fetch_file(in_path, out_path)
@ -268,7 +270,9 @@ class Connection(ConnectionBase):
) as out_file: ) as out_file:
out_file.write(out) out_file.write(out)
except IOError as e: except IOError as e:
raise AnsibleError(f"failed to transfer file to {to_native(out_path)}: {e}") raise AnsibleError(
f"failed to transfer file to {to_native(out_path)}: {e}"
) from e
def close(self): def close(self):
"""terminate the connection; nothing to do here""" """terminate the connection; nothing to do here"""

View File

@ -228,7 +228,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
} }
containers = client.get_json("/containers/json", params=params) containers = client.get_json("/containers/json", params=params)
except APIError as exc: except APIError as exc:
raise AnsibleError(f"Error listing containers: {exc}") raise AnsibleError(f"Error listing containers: {exc}") from exc
if add_legacy_groups: if add_legacy_groups:
self.inventory.add_group("running") self.inventory.add_group("running")
@ -247,26 +247,28 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
short_container_id = container_id[:13] short_container_id = container_id[:13]
try: try:
name = container.get("Names", list())[0].lstrip("/") name = container.get("Names", [])[0].lstrip("/")
full_name = name full_name = name
except IndexError: except IndexError:
name = short_container_id name = short_container_id
full_name = container_id full_name = container_id
facts = dict( facts = {
docker_name=make_unsafe(name), "docker_name": make_unsafe(name),
docker_short_id=make_unsafe(short_container_id), "docker_short_id": make_unsafe(short_container_id),
) }
full_facts = dict() full_facts = {}
try: try:
inspect = client.get_json("/containers/{0}/json", container_id) inspect = client.get_json("/containers/{0}/json", container_id)
except APIError as exc: except APIError as exc:
raise AnsibleError(f"Error inspecting container {name} - {exc}") raise AnsibleError(
f"Error inspecting container {name} - {exc}"
) from exc
state = inspect.get("State") or dict() state = inspect.get("State") or {}
config = inspect.get("Config") or dict() config = inspect.get("Config") or {}
labels = config.get("Labels") or dict() labels = config.get("Labels") or {}
running = state.get("Running") running = state.get("Running")
@ -298,7 +300,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
port_settings = network_settings.get("Ports") or {} port_settings = network_settings.get("Ports") or {}
port = port_settings.get(f"{ssh_port}/tcp")[0] port = port_settings.get(f"{ssh_port}/tcp")[0]
except (IndexError, AttributeError, TypeError): except (IndexError, AttributeError, TypeError):
port = dict() port = {}
try: try:
ip = default_ip if port["HostIp"] == "0.0.0.0" else port["HostIp"] ip = default_ip if port["HostIp"] == "0.0.0.0" else port["HostIp"]
@ -306,23 +308,23 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
ip = "" ip = ""
facts.update( facts.update(
dict( {
ansible_ssh_host=ip, "ansible_ssh_host": ip,
ansible_ssh_port=port.get("HostPort", 0), "ansible_ssh_port": port.get("HostPort", 0),
) }
) )
elif connection_type == "docker-cli": elif connection_type == "docker-cli":
facts.update( facts.update(
dict( {
ansible_host=full_name, "ansible_host": full_name,
) }
) )
ansible_connection = "community.docker.docker" ansible_connection = "community.docker.docker"
elif connection_type == "docker-api": elif connection_type == "docker-api":
facts.update( facts.update(
dict( {
ansible_host=full_name, "ansible_host": full_name,
) }
) )
facts.update(extra_facts) facts.update(extra_facts)
ansible_connection = "community.docker.docker_api" ansible_connection = "community.docker.docker_api"
@ -401,8 +403,8 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
try: try:
self._populate(client) self._populate(client)
except DockerException as e: except DockerException as e:
raise AnsibleError(f"An unexpected Docker error occurred: {e}") raise AnsibleError(f"An unexpected Docker error occurred: {e}") from e
except RequestException as e: except RequestException as e:
raise AnsibleError( raise AnsibleError(
f"An unexpected requests error occurred when trying to talk to the Docker daemon: {e}" f"An unexpected requests error occurred when trying to talk to the Docker daemon: {e}"
) ) from e

View File

@ -132,7 +132,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
try: try:
self.docker_machine_path = get_bin_path("docker-machine") self.docker_machine_path = get_bin_path("docker-machine")
except ValueError as e: except ValueError as e:
raise AnsibleError(to_native(e)) raise AnsibleError(to_native(e)) from e
command = [self.docker_machine_path] command = [self.docker_machine_path]
command.extend(args) command.extend(args)

View File

@ -184,19 +184,19 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
raise AnsibleError(msg) raise AnsibleError(msg)
def _populate(self): def _populate(self):
raw_params = dict( raw_params = {
docker_host=self.get_option("docker_host"), "docker_host": self.get_option("docker_host"),
tls=self.get_option("tls"), "tls": self.get_option("tls"),
tls_verify=self.get_option("validate_certs"), "tls_verify": self.get_option("validate_certs"),
key_path=self.get_option("client_key"), "key_path": self.get_option("client_key"),
cacert_path=self.get_option("ca_path"), "cacert_path": self.get_option("ca_path"),
cert_path=self.get_option("client_cert"), "cert_path": self.get_option("client_cert"),
tls_hostname=self.get_option("tls_hostname"), "tls_hostname": self.get_option("tls_hostname"),
api_version=self.get_option("api_version"), "api_version": self.get_option("api_version"),
timeout=self.get_option("timeout"), "timeout": self.get_option("timeout"),
use_ssh_client=self.get_option("use_ssh_client"), "use_ssh_client": self.get_option("use_ssh_client"),
debug=None, "debug": None,
) }
update_tls_hostname(raw_params) update_tls_hostname(raw_params)
connect_params = get_connect_params(raw_params, fail_function=self._fail) connect_params = get_connect_params(raw_params, fail_function=self._fail)
client = docker.DockerClient(**connect_params) client = docker.DockerClient(**connect_params)
@ -305,7 +305,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
except Exception as e: except Exception as e:
raise AnsibleError( raise AnsibleError(
f"Unable to fetch hosts from Docker swarm API, this was the original exception: {e}" f"Unable to fetch hosts from Docker swarm API, this was the original exception: {e}"
) ) from e
def verify_file(self, path): def verify_file(self, path):
"""Return the possibly of a file being consumable by this plugin.""" """Return the possibly of a file being consumable by this plugin."""

View File

@ -227,18 +227,20 @@ class APIClient(_Session, DaemonApiMixin):
try: try:
version_result = self.version(api_version=False) version_result = self.version(api_version=False)
except Exception as e: except Exception as e:
raise DockerException(f"Error while fetching server API version: {e}") raise DockerException(
f"Error while fetching server API version: {e}"
) from e
try: try:
return version_result["ApiVersion"] return version_result["ApiVersion"]
except KeyError: except KeyError:
raise DockerException( raise DockerException(
'Invalid response from docker daemon: key "ApiVersion" is missing.' 'Invalid response from docker daemon: key "ApiVersion" is missing.'
) ) from None
except Exception as e: except Exception as e:
raise DockerException( raise DockerException(
f"Error while fetching server API version: {e}. Response seems to be broken." f"Error while fetching server API version: {e}. Response seems to be broken."
) ) from e
def _set_request_timeout(self, kwargs): def _set_request_timeout(self, kwargs):
"""Prepare the kwargs for an HTTP request by inserting the timeout """Prepare the kwargs for an HTTP request by inserting the timeout

View File

@ -370,7 +370,6 @@ def _load_legacy_config(config_file):
} }
except Exception as e: # pylint: disable=broad-exception-caught except Exception as e: # pylint: disable=broad-exception-caught
log.debug(e) log.debug(e)
pass
log.debug("All parsing attempts failed - returning empty config") log.debug("All parsing attempts failed - returning empty config")
return {} return {}

View File

@ -106,7 +106,7 @@ class Context:
self.tls_cfg[name] = tls_cfg self.tls_cfg[name] = tls_cfg
def inspect(self): def inspect(self):
return self.__call__() return self()
@classmethod @classmethod
def load_context(cls, name): def load_context(cls, name):

View File

@ -71,7 +71,7 @@ class TLSConfig:
except ValueError: except ValueError:
raise errors.TLSParameterError( raise errors.TLSParameterError(
"client_cert must be a tuple of (client certificate, key file)" "client_cert must be a tuple of (client certificate, key file)"
) ) from None
if not (tls_cert and tls_key) or ( if not (tls_cert and tls_key) or (
not os.path.isfile(tls_cert) or not os.path.isfile(tls_key) not os.path.isfile(tls_cert) or not os.path.isfile(tls_key)

View File

@ -52,16 +52,16 @@ class NpipeHTTPConnectionPool(urllib3.connectionpool.HTTPConnectionPool):
try: try:
conn = self.pool.get(block=self.block, timeout=timeout) conn = self.pool.get(block=self.block, timeout=timeout)
except AttributeError: # self.pool is None except AttributeError as exc: # self.pool is None
raise urllib3.exceptions.ClosedPoolError(self, "Pool is closed.") raise urllib3.exceptions.ClosedPoolError(self, "Pool is closed.") from exc
except Empty: except Empty as exc:
if self.block: if self.block:
raise urllib3.exceptions.EmptyPoolError( raise urllib3.exceptions.EmptyPoolError(
self, self,
"Pool reached maximum size and no more connections are allowed.", "Pool reached maximum size and no more connections are allowed.",
) ) from exc
pass # Oh well, we'll create a new connection then # Oh well, we'll create a new connection then
return conn or self._new_conn() return conn or self._new_conn()

View File

@ -141,7 +141,7 @@ class NpipeSocket:
@check_closed @check_closed
def recv(self, bufsize, flags=0): def recv(self, bufsize, flags=0):
err, data = win32file.ReadFile(self._handle, bufsize) dummy_err, data = win32file.ReadFile(self._handle, bufsize)
return data return data
@check_closed @check_closed
@ -163,7 +163,7 @@ class NpipeSocket:
try: try:
overlapped = pywintypes.OVERLAPPED() overlapped = pywintypes.OVERLAPPED()
overlapped.hEvent = event overlapped.hEvent = event
err, data = win32file.ReadFile( dummy_err, dummy_data = win32file.ReadFile(
self._handle, readbuf[:nbytes] if nbytes else readbuf, overlapped self._handle, readbuf[:nbytes] if nbytes else readbuf, overlapped
) )
wait_result = win32event.WaitForSingleObject(event, self._timeout) wait_result = win32event.WaitForSingleObject(event, self._timeout)

View File

@ -159,16 +159,16 @@ class SSHConnectionPool(urllib3.connectionpool.HTTPConnectionPool):
try: try:
conn = self.pool.get(block=self.block, timeout=timeout) conn = self.pool.get(block=self.block, timeout=timeout)
except AttributeError: # self.pool is None except AttributeError as exc: # self.pool is None
raise urllib3.exceptions.ClosedPoolError(self, "Pool is closed.") raise urllib3.exceptions.ClosedPoolError(self, "Pool is closed.") from exc
except Empty: except Empty as exc:
if self.block: if self.block:
raise urllib3.exceptions.EmptyPoolError( raise urllib3.exceptions.EmptyPoolError(
self, self,
"Pool reached maximum size and no more connections are allowed.", "Pool reached maximum size and no more connections are allowed.",
) ) from exc
pass # Oh well, we'll create a new connection then # Oh well, we'll create a new connection then
return conn or self._new_conn() return conn or self._new_conn()

View File

@ -39,10 +39,10 @@ class CancellableStream:
def __next__(self): def __next__(self):
try: try:
return next(self._stream) return next(self._stream)
except urllib3.exceptions.ProtocolError: except urllib3.exceptions.ProtocolError as exc:
raise StopIteration raise StopIteration from exc
except socket.error: except socket.error as exc:
raise StopIteration raise StopIteration from exc
next = __next__ next = __next__

View File

@ -107,8 +107,8 @@ def create_archive(root, files=None, fileobj=None, gzip=False, extra_files=None)
try: try:
with open(full_path, "rb") as f: with open(full_path, "rb") as f:
t.addfile(i, f) t.addfile(i, f)
except IOError: except IOError as exc:
raise IOError(f"Can not read file in context: {full_path}") raise IOError(f"Can not read file in context: {full_path}") from exc
else: else:
# Directories, FIFOs, symlinks... do not need to be read. # Directories, FIFOs, symlinks... do not need to be read.
t.addfile(i, None) t.addfile(i, None)

View File

@ -85,4 +85,4 @@ def split_buffer(stream, splitter=None, decoder=lambda a: a):
try: try:
yield decoder(buffered) yield decoder(buffered)
except Exception as e: except Exception as e:
raise StreamParseError(e) raise StreamParseError(e) from e

View File

@ -420,10 +420,10 @@ def parse_bytes(s):
if suffix in units or suffix.isdigit(): if suffix in units or suffix.isdigit():
try: try:
digits = float(digits_part) digits = float(digits_part)
except ValueError: except ValueError as exc:
raise errors.DockerException( raise errors.DockerException(
f"Failed converting the string value for memory ({digits_part}) to an integer." f"Failed converting the string value for memory ({digits_part}) to an integer."
) ) from exc
# Reconvert to long for the final result # Reconvert to long for the final result
s = int(digits * units[suffix]) s = int(digits * units[suffix])

View File

@ -144,19 +144,19 @@ def get_connect_params(auth_data, fail_function):
"tcp://", "https://" "tcp://", "https://"
) )
result = dict( result = {
base_url=auth_data["docker_host"], "base_url": auth_data["docker_host"],
version=auth_data["api_version"], "version": auth_data["api_version"],
timeout=auth_data["timeout"], "timeout": auth_data["timeout"],
) }
if auth_data["tls_verify"]: if auth_data["tls_verify"]:
# TLS with verification # TLS with verification
tls_config = dict( tls_config = {
verify=True, "verify": True,
assert_hostname=auth_data["tls_hostname"], "assert_hostname": auth_data["tls_hostname"],
fail_function=fail_function, "fail_function": fail_function,
) }
if auth_data["cert_path"] and auth_data["key_path"]: if auth_data["cert_path"] and auth_data["key_path"]:
tls_config["client_cert"] = (auth_data["cert_path"], auth_data["key_path"]) tls_config["client_cert"] = (auth_data["cert_path"], auth_data["key_path"])
if auth_data["cacert_path"]: if auth_data["cacert_path"]:
@ -164,10 +164,10 @@ def get_connect_params(auth_data, fail_function):
result["tls"] = _get_tls_config(**tls_config) result["tls"] = _get_tls_config(**tls_config)
elif auth_data["tls"]: elif auth_data["tls"]:
# TLS without verification # TLS without verification
tls_config = dict( tls_config = {
verify=False, "verify": False,
fail_function=fail_function, "fail_function": fail_function,
) }
if auth_data["cert_path"] and auth_data["key_path"]: if auth_data["cert_path"] and auth_data["key_path"]:
tls_config["client_cert"] = (auth_data["cert_path"], auth_data["key_path"]) tls_config["client_cert"] = (auth_data["cert_path"], auth_data["key_path"])
result["tls"] = _get_tls_config(**tls_config) result["tls"] = _get_tls_config(**tls_config)
@ -312,78 +312,78 @@ class AnsibleDockerClientBase(Client):
client_params = self._get_params() client_params = self._get_params()
params = dict() params = {}
for key in DOCKER_COMMON_ARGS: for key in DOCKER_COMMON_ARGS:
params[key] = client_params.get(key) params[key] = client_params.get(key)
result = dict( result = {
docker_host=self._get_value( "docker_host": self._get_value(
"docker_host", "docker_host",
params["docker_host"], params["docker_host"],
"DOCKER_HOST", "DOCKER_HOST",
DEFAULT_DOCKER_HOST, DEFAULT_DOCKER_HOST,
value_type="str", value_type="str",
), ),
tls_hostname=self._get_value( "tls_hostname": self._get_value(
"tls_hostname", "tls_hostname",
params["tls_hostname"], params["tls_hostname"],
"DOCKER_TLS_HOSTNAME", "DOCKER_TLS_HOSTNAME",
None, None,
value_type="str", value_type="str",
), ),
api_version=self._get_value( "api_version": self._get_value(
"api_version", "api_version",
params["api_version"], params["api_version"],
"DOCKER_API_VERSION", "DOCKER_API_VERSION",
"auto", "auto",
value_type="str", value_type="str",
), ),
cacert_path=self._get_value( "cacert_path": self._get_value(
"cacert_path", "cacert_path",
params["ca_path"], params["ca_path"],
"DOCKER_CERT_PATH", "DOCKER_CERT_PATH",
None, None,
value_type="str", value_type="str",
), ),
cert_path=self._get_value( "cert_path": self._get_value(
"cert_path", "cert_path",
params["client_cert"], params["client_cert"],
"DOCKER_CERT_PATH", "DOCKER_CERT_PATH",
None, None,
value_type="str", value_type="str",
), ),
key_path=self._get_value( "key_path": self._get_value(
"key_path", "key_path",
params["client_key"], params["client_key"],
"DOCKER_CERT_PATH", "DOCKER_CERT_PATH",
None, None,
value_type="str", value_type="str",
), ),
tls=self._get_value( "tls": self._get_value(
"tls", params["tls"], "DOCKER_TLS", DEFAULT_TLS, value_type="bool" "tls", params["tls"], "DOCKER_TLS", DEFAULT_TLS, value_type="bool"
), ),
tls_verify=self._get_value( "tls_verify": self._get_value(
"validate_certs", "validate_certs",
params["validate_certs"], params["validate_certs"],
"DOCKER_TLS_VERIFY", "DOCKER_TLS_VERIFY",
DEFAULT_TLS_VERIFY, DEFAULT_TLS_VERIFY,
value_type="bool", value_type="bool",
), ),
timeout=self._get_value( "timeout": self._get_value(
"timeout", "timeout",
params["timeout"], params["timeout"],
"DOCKER_TIMEOUT", "DOCKER_TIMEOUT",
DEFAULT_TIMEOUT_SECONDS, DEFAULT_TIMEOUT_SECONDS,
value_type="int", value_type="int",
), ),
use_ssh_client=self._get_value( "use_ssh_client": self._get_value(
"use_ssh_client", "use_ssh_client",
params["use_ssh_client"], params["use_ssh_client"],
None, None,
False, False,
value_type="bool", value_type="bool",
), ),
) }
update_tls_hostname(result) update_tls_hostname(result)
@ -586,11 +586,11 @@ class AnsibleDockerClientBase(Client):
""" """
Pull an image Pull an image
""" """
kwargs = dict( kwargs = {
tag=tag, "tag": tag,
stream=True, "stream": True,
decode=True, "decode": True,
) }
if image_platform is not None: if image_platform is not None:
kwargs["platform"] = image_platform kwargs["platform"] = image_platform
self.log(f"Pulling image {name}:{tag}") self.log(f"Pulling image {name}:{tag}")
@ -654,7 +654,7 @@ class AnsibleDockerClient(AnsibleDockerClientBase):
# in case client.fail() is called. # in case client.fail() is called.
self.fail_results = fail_results or {} self.fail_results = fail_results or {}
merged_arg_spec = dict() merged_arg_spec = {}
merged_arg_spec.update(DOCKER_COMMON_ARGS) merged_arg_spec.update(DOCKER_COMMON_ARGS)
if argument_spec: if argument_spec:
merged_arg_spec.update(argument_spec) merged_arg_spec.update(argument_spec)
@ -706,12 +706,12 @@ class AnsibleDockerClient(AnsibleDockerClientBase):
return self.module.params return self.module.params
def _get_minimal_versions(self, option_minimal_versions, ignore_params=None): def _get_minimal_versions(self, option_minimal_versions, ignore_params=None):
self.option_minimal_versions = dict() self.option_minimal_versions = {}
for option in self.module.argument_spec: for option in self.module.argument_spec:
if ignore_params is not None: if ignore_params is not None:
if option in ignore_params: if option in ignore_params:
continue continue
self.option_minimal_versions[option] = dict() self.option_minimal_versions[option] = {}
self.option_minimal_versions.update(option_minimal_versions) self.option_minimal_versions.update(option_minimal_versions)
for option, data in self.option_minimal_versions.items(): for option, data in self.option_minimal_versions.items():

View File

@ -78,19 +78,19 @@ def get_connect_params(auth_data, fail_function):
"tcp://", "https://" "tcp://", "https://"
) )
result = dict( result = {
base_url=auth_data["docker_host"], "base_url": auth_data["docker_host"],
version=auth_data["api_version"], "version": auth_data["api_version"],
timeout=auth_data["timeout"], "timeout": auth_data["timeout"],
) }
if auth_data["tls_verify"]: if auth_data["tls_verify"]:
# TLS with verification # TLS with verification
tls_config = dict( tls_config = {
verify=True, "verify": True,
assert_hostname=auth_data["tls_hostname"], "assert_hostname": auth_data["tls_hostname"],
fail_function=fail_function, "fail_function": fail_function,
) }
if auth_data["cert_path"] and auth_data["key_path"]: if auth_data["cert_path"] and auth_data["key_path"]:
tls_config["client_cert"] = (auth_data["cert_path"], auth_data["key_path"]) tls_config["client_cert"] = (auth_data["cert_path"], auth_data["key_path"])
if auth_data["cacert_path"]: if auth_data["cacert_path"]:
@ -98,10 +98,10 @@ def get_connect_params(auth_data, fail_function):
result["tls"] = _get_tls_config(**tls_config) result["tls"] = _get_tls_config(**tls_config)
elif auth_data["tls"]: elif auth_data["tls"]:
# TLS without verification # TLS without verification
tls_config = dict( tls_config = {
verify=False, "verify": False,
fail_function=fail_function, "fail_function": fail_function,
) }
if auth_data["cert_path"] and auth_data["key_path"]: if auth_data["cert_path"] and auth_data["key_path"]:
tls_config["client_cert"] = (auth_data["cert_path"], auth_data["key_path"]) tls_config["client_cert"] = (auth_data["cert_path"], auth_data["key_path"])
result["tls"] = _get_tls_config(**tls_config) result["tls"] = _get_tls_config(**tls_config)
@ -203,78 +203,78 @@ class AnsibleDockerClientBase(Client):
client_params = self._get_params() client_params = self._get_params()
params = dict() params = {}
for key in DOCKER_COMMON_ARGS: for key in DOCKER_COMMON_ARGS:
params[key] = client_params.get(key) params[key] = client_params.get(key)
result = dict( result = {
docker_host=self._get_value( "docker_host": self._get_value(
"docker_host", "docker_host",
params["docker_host"], params["docker_host"],
"DOCKER_HOST", "DOCKER_HOST",
DEFAULT_DOCKER_HOST, DEFAULT_DOCKER_HOST,
value_type="str", value_type="str",
), ),
tls_hostname=self._get_value( "tls_hostname": self._get_value(
"tls_hostname", "tls_hostname",
params["tls_hostname"], params["tls_hostname"],
"DOCKER_TLS_HOSTNAME", "DOCKER_TLS_HOSTNAME",
None, None,
value_type="str", value_type="str",
), ),
api_version=self._get_value( "api_version": self._get_value(
"api_version", "api_version",
params["api_version"], params["api_version"],
"DOCKER_API_VERSION", "DOCKER_API_VERSION",
"auto", "auto",
value_type="str", value_type="str",
), ),
cacert_path=self._get_value( "cacert_path": self._get_value(
"cacert_path", "cacert_path",
params["ca_path"], params["ca_path"],
"DOCKER_CERT_PATH", "DOCKER_CERT_PATH",
None, None,
value_type="str", value_type="str",
), ),
cert_path=self._get_value( "cert_path": self._get_value(
"cert_path", "cert_path",
params["client_cert"], params["client_cert"],
"DOCKER_CERT_PATH", "DOCKER_CERT_PATH",
None, None,
value_type="str", value_type="str",
), ),
key_path=self._get_value( "key_path": self._get_value(
"key_path", "key_path",
params["client_key"], params["client_key"],
"DOCKER_CERT_PATH", "DOCKER_CERT_PATH",
None, None,
value_type="str", value_type="str",
), ),
tls=self._get_value( "tls": self._get_value(
"tls", params["tls"], "DOCKER_TLS", DEFAULT_TLS, value_type="bool" "tls", params["tls"], "DOCKER_TLS", DEFAULT_TLS, value_type="bool"
), ),
tls_verify=self._get_value( "tls_verify": self._get_value(
"validate_certs", "validate_certs",
params["validate_certs"], params["validate_certs"],
"DOCKER_TLS_VERIFY", "DOCKER_TLS_VERIFY",
DEFAULT_TLS_VERIFY, DEFAULT_TLS_VERIFY,
value_type="bool", value_type="bool",
), ),
timeout=self._get_value( "timeout": self._get_value(
"timeout", "timeout",
params["timeout"], params["timeout"],
"DOCKER_TIMEOUT", "DOCKER_TIMEOUT",
DEFAULT_TIMEOUT_SECONDS, DEFAULT_TIMEOUT_SECONDS,
value_type="int", value_type="int",
), ),
use_ssh_client=self._get_value( "use_ssh_client": self._get_value(
"use_ssh_client", "use_ssh_client",
params["use_ssh_client"], params["use_ssh_client"],
None, None,
False, False,
value_type="bool", value_type="bool",
), ),
) }
def depr(*args, **kwargs): def depr(*args, **kwargs):
self.deprecate(*args, **kwargs) self.deprecate(*args, **kwargs)
@ -504,7 +504,7 @@ class AnsibleDockerClientBase(Client):
old_tag = self.find_image(name, tag) old_tag = self.find_image(name, tag)
try: try:
repository, image_tag = parse_repository_tag(name) repository, image_tag = parse_repository_tag(name)
registry, repo_name = auth.resolve_repository_name(repository) registry, dummy_repo_name = auth.resolve_repository_name(repository)
params = { params = {
"tag": tag or image_tag or "latest", "tag": tag or image_tag or "latest",
"fromImage": repository, "fromImage": repository,
@ -564,7 +564,7 @@ class AnsibleDockerClient(AnsibleDockerClientBase):
# in case client.fail() is called. # in case client.fail() is called.
self.fail_results = fail_results or {} self.fail_results = fail_results or {}
merged_arg_spec = dict() merged_arg_spec = {}
merged_arg_spec.update(DOCKER_COMMON_ARGS) merged_arg_spec.update(DOCKER_COMMON_ARGS)
if argument_spec: if argument_spec:
merged_arg_spec.update(argument_spec) merged_arg_spec.update(argument_spec)
@ -613,12 +613,12 @@ class AnsibleDockerClient(AnsibleDockerClientBase):
return self.module.params return self.module.params
def _get_minimal_versions(self, option_minimal_versions, ignore_params=None): def _get_minimal_versions(self, option_minimal_versions, ignore_params=None):
self.option_minimal_versions = dict() self.option_minimal_versions = {}
for option in self.module.argument_spec: for option in self.module.argument_spec:
if ignore_params is not None: if ignore_params is not None:
if option in ignore_params: if option in ignore_params:
continue continue
self.option_minimal_versions[option] = dict() self.option_minimal_versions[option] = {}
self.option_minimal_versions.update(option_minimal_versions) self.option_minimal_versions.update(option_minimal_versions)
for option, data in self.option_minimal_versions.items(): for option, data in self.option_minimal_versions.items():

View File

@ -31,31 +31,40 @@ from ansible_collections.community.docker.plugins.module_utils._version import (
) )
DOCKER_COMMON_ARGS = dict( DOCKER_COMMON_ARGS = {
docker_cli=dict(type="path"), "docker_cli": {"type": "path"},
docker_host=dict( "docker_host": {
type="str", fallback=(env_fallback, ["DOCKER_HOST"]), aliases=["docker_url"] "type": "str",
), "fallback": (env_fallback, ["DOCKER_HOST"]),
tls_hostname=dict(type="str", fallback=(env_fallback, ["DOCKER_TLS_HOSTNAME"])), "aliases": ["docker_url"],
api_version=dict( },
type="str", "tls_hostname": {
default="auto", "type": "str",
fallback=(env_fallback, ["DOCKER_API_VERSION"]), "fallback": (env_fallback, ["DOCKER_TLS_HOSTNAME"]),
aliases=["docker_api_version"], },
), "api_version": {
ca_path=dict(type="path", aliases=["ca_cert", "tls_ca_cert", "cacert_path"]), "type": "str",
client_cert=dict(type="path", aliases=["tls_client_cert", "cert_path"]), "default": "auto",
client_key=dict(type="path", aliases=["tls_client_key", "key_path"]), "fallback": (env_fallback, ["DOCKER_API_VERSION"]),
tls=dict(type="bool", default=DEFAULT_TLS, fallback=(env_fallback, ["DOCKER_TLS"])), "aliases": ["docker_api_version"],
validate_certs=dict( },
type="bool", "ca_path": {"type": "path", "aliases": ["ca_cert", "tls_ca_cert", "cacert_path"]},
default=DEFAULT_TLS_VERIFY, "client_cert": {"type": "path", "aliases": ["tls_client_cert", "cert_path"]},
fallback=(env_fallback, ["DOCKER_TLS_VERIFY"]), "client_key": {"type": "path", "aliases": ["tls_client_key", "key_path"]},
aliases=["tls_verify"], "tls": {
), "type": "bool",
# debug=dict(type='bool', default=False), "default": DEFAULT_TLS,
cli_context=dict(type="str"), "fallback": (env_fallback, ["DOCKER_TLS"]),
) },
"validate_certs": {
"type": "bool",
"default": DEFAULT_TLS_VERIFY,
"fallback": (env_fallback, ["DOCKER_TLS_VERIFY"]),
"aliases": ["tls_verify"],
},
# "debug": {"type": "bool", "default: False},
"cli_context": {"type": "str"},
}
class DockerException(Exception): class DockerException(Exception):
@ -327,7 +336,7 @@ class AnsibleModuleDockerClient(AnsibleDockerClientBase):
# in case client.fail() is called. # in case client.fail() is called.
self.fail_results = fail_results or {} self.fail_results = fail_results or {}
merged_arg_spec = dict() merged_arg_spec = {}
merged_arg_spec.update(DOCKER_COMMON_ARGS) merged_arg_spec.update(DOCKER_COMMON_ARGS)
if argument_spec: if argument_spec:
merged_arg_spec.update(argument_spec) merged_arg_spec.update(argument_spec)

View File

@ -691,28 +691,28 @@ def update_failed(result, events, args, stdout, stderr, rc, cli):
def common_compose_argspec(): def common_compose_argspec():
return dict( return {
project_src=dict(type="path"), "project_src": {"type": "path"},
project_name=dict(type="str"), "project_name": {"type": "str"},
files=dict(type="list", elements="path"), "files": {"type": "list", "elements": "path"},
definition=dict(type="dict"), "definition": {"type": "dict"},
env_files=dict(type="list", elements="path"), "env_files": {"type": "list", "elements": "path"},
profiles=dict(type="list", elements="str"), "profiles": {"type": "list", "elements": "str"},
check_files_existing=dict(type="bool", default=True), "check_files_existing": {"type": "bool", "default": True},
) }
def common_compose_argspec_ex(): def common_compose_argspec_ex():
return dict( return {
argspec=common_compose_argspec(), "argspec": common_compose_argspec(),
mutually_exclusive=[("definition", "project_src"), ("definition", "files")], "mutually_exclusive": [("definition", "project_src"), ("definition", "files")],
required_one_of=[ "required_one_of": [
("definition", "project_src"), ("definition", "project_src"),
], ],
required_by={ "required_by": {
"definition": ("project_name",), "definition": ("project_name",),
}, },
) }
def combine_binary_output(*outputs): def combine_binary_output(*outputs):
@ -794,7 +794,7 @@ class BaseComposeManager(DockerBaseClass):
) )
def get_compose_version_from_cli(self): def get_compose_version_from_cli(self):
rc, version_info, stderr = self.client.call_cli( rc, version_info, dummy_stderr = self.client.call_cli(
"compose", "version", "--format", "json" "compose", "version", "--format", "json"
) )
if rc: if rc:
@ -853,7 +853,7 @@ class BaseComposeManager(DockerBaseClass):
if self.compose_version >= LooseVersion("2.23.0"): if self.compose_version >= LooseVersion("2.23.0"):
# https://github.com/docker/compose/pull/11038 # https://github.com/docker/compose/pull/11038
args.append("--no-trunc") args.append("--no-trunc")
kwargs = dict(cwd=self.project_src, check_rc=not self.use_json_events) kwargs = {"cwd": self.project_src, "check_rc": not self.use_json_events}
if self.compose_version >= LooseVersion("2.21.0"): if self.compose_version >= LooseVersion("2.21.0"):
# Breaking change in 2.21.0: https://github.com/docker/compose/pull/10918 # Breaking change in 2.21.0: https://github.com/docker/compose/pull/10918
rc, containers, stderr = self.client.call_cli_json_stream(*args, **kwargs) rc, containers, stderr = self.client.call_cli_json_stream(*args, **kwargs)
@ -882,7 +882,7 @@ class BaseComposeManager(DockerBaseClass):
def list_images(self): def list_images(self):
args = self.get_base_args() + ["images", "--format", "json"] args = self.get_base_args() + ["images", "--format", "json"]
kwargs = dict(cwd=self.project_src, check_rc=not self.use_json_events) kwargs = {"cwd": self.project_src, "check_rc": not self.use_json_events}
rc, images, stderr = self.client.call_cli_json(*args, **kwargs) rc, images, stderr = self.client.call_cli_json(*args, **kwargs)
if self.use_json_events and rc != 0: if self.use_json_events and rc != 0:
self._handle_failed_cli_call(args, rc, images, stderr) self._handle_failed_cli_call(args, rc, images, stderr)

View File

@ -285,7 +285,7 @@ def stat_file(client, container, in_path, follow_links=False, log=None):
except Exception as exc: except Exception as exc:
raise DockerUnexpectedError( raise DockerUnexpectedError(
f"When retrieving information for {in_path} from {container}, obtained header {header!r} that cannot be loaded as JSON: {exc}" f"When retrieving information for {in_path} from {container}, obtained header {header!r} that cannot be loaded as JSON: {exc}"
) ) from exc
# https://pkg.go.dev/io/fs#FileMode: bit 32 - 5 means ModeSymlink # https://pkg.go.dev/io/fs#FileMode: bit 32 - 5 means ModeSymlink
if stat_data["mode"] & (1 << (32 - 5)) != 0: if stat_data["mode"] & (1 << (32 - 5)) != 0:
@ -500,7 +500,7 @@ def _execute_command(client, container, command, log=None, check_rc=False):
def determine_user_group(client, container, log=None): def determine_user_group(client, container, log=None):
dummy, stdout, stderr = _execute_command( dummy_rc, stdout, dummy_stderr = _execute_command(
client, container, ["/bin/sh", "-c", "id -u && id -g"], check_rc=True, log=log client, container, ["/bin/sh", "-c", "id -u && id -g"], check_rc=True, log=log
) )
@ -513,7 +513,7 @@ def determine_user_group(client, container, log=None):
user_id, group_id = stdout_lines user_id, group_id = stdout_lines
try: try:
return int(user_id), int(group_id) return int(user_id), int(group_id)
except ValueError: except ValueError as exc:
raise DockerUnexpectedError( raise DockerUnexpectedError(
f'Expected two-line output with numeric IDs to obtain user and group ID for container {container}, but got "{user_id}" and "{group_id}" instead' f'Expected two-line output with numeric IDs to obtain user and group ID for container {container}, but got "{user_id}" and "{group_id}" instead'
) ) from exc

View File

@ -96,14 +96,14 @@ class _Parser:
if self.line[self.index : self.index + 2] != "\\u": if self.line[self.index : self.index + 2] != "\\u":
raise InvalidLogFmt("Invalid unicode escape start") raise InvalidLogFmt("Invalid unicode escape start")
v = 0 v = 0
for i in range(self.index + 2, self.index + 6): for dummy_index in range(self.index + 2, self.index + 6):
v <<= 4 v <<= 4
try: try:
v += _HEX_DICT[self.line[self.index]] v += _HEX_DICT[self.line[self.index]]
except KeyError: except KeyError:
raise InvalidLogFmt( raise InvalidLogFmt(
f"Invalid unicode escape digit {self.line[self.index]!r}" f"Invalid unicode escape digit {self.line[self.index]!r}"
) ) from None
self.index += 6 self.index += 6
return chr(v) return chr(v)

View File

@ -37,21 +37,21 @@ _DEFAULT_IP_REPLACEMENT_STRING = (
) )
_MOUNT_OPTION_TYPES = dict( _MOUNT_OPTION_TYPES = {
create_mountpoint=("bind",), "create_mountpoint": ("bind",),
labels=("volume",), "labels": ("volume",),
no_copy=("volume",), "no_copy": ("volume",),
non_recursive=("bind",), "non_recursive": ("bind",),
propagation=("bind",), "propagation": ("bind",),
read_only_force_recursive=("bind",), "read_only_force_recursive": ("bind",),
read_only_non_recursive=("bind",), "read_only_non_recursive": ("bind",),
subpath=("volume", "image"), "subpath": ("volume", "image"),
tmpfs_size=("tmpfs",), "tmpfs_size": ("tmpfs",),
tmpfs_mode=("tmpfs",), "tmpfs_mode": ("tmpfs",),
tmpfs_options=("tmpfs",), "tmpfs_options": ("tmpfs",),
volume_driver=("volume",), "volume_driver": ("volume",),
volume_options=("volume",), "volume_options": ("volume",),
) }
def _get_ansible_type(value_type): def _get_ansible_type(value_type):
@ -629,7 +629,7 @@ def _preprocess_ulimits(module, values):
return values return values
result = [] result = []
for limit in values["ulimits"]: for limit in values["ulimits"]:
limits = dict() limits = {}
pieces = limit.split(":") pieces = limit.split(":")
if len(pieces) >= 2: if len(pieces) >= 2:
limits["Name"] = pieces[0] limits["Name"] = pieces[0]
@ -644,7 +644,7 @@ def _preprocess_ulimits(module, values):
def _preprocess_mounts(module, values): def _preprocess_mounts(module, values):
last = dict() last = {}
def check_collision(t, name): def check_collision(t, name):
if t in last: if t in last:
@ -970,53 +970,53 @@ OPTION_DEVICE_READ_BPS = OptionGroup().add_option(
"device_read_bps", "device_read_bps",
value_type="set", value_type="set",
elements="dict", elements="dict",
ansible_suboptions=dict( ansible_suboptions={
path=dict(required=True, type="str"), "path": {"type": "str", "required": True},
rate=dict(required=True, type="str"), "rate": {"type": "str", "required": True},
), },
) )
OPTION_DEVICE_WRITE_BPS = OptionGroup().add_option( OPTION_DEVICE_WRITE_BPS = OptionGroup().add_option(
"device_write_bps", "device_write_bps",
value_type="set", value_type="set",
elements="dict", elements="dict",
ansible_suboptions=dict( ansible_suboptions={
path=dict(required=True, type="str"), "path": {"type": "str", "required": True},
rate=dict(required=True, type="str"), "rate": {"type": "str", "required": True},
), },
) )
OPTION_DEVICE_READ_IOPS = OptionGroup().add_option( OPTION_DEVICE_READ_IOPS = OptionGroup().add_option(
"device_read_iops", "device_read_iops",
value_type="set", value_type="set",
elements="dict", elements="dict",
ansible_suboptions=dict( ansible_suboptions={
path=dict(required=True, type="str"), "path": {"type": "str", "required": True},
rate=dict(required=True, type="int"), "rate": {"type": "int", "required": True},
), },
) )
OPTION_DEVICE_WRITE_IOPS = OptionGroup().add_option( OPTION_DEVICE_WRITE_IOPS = OptionGroup().add_option(
"device_write_iops", "device_write_iops",
value_type="set", value_type="set",
elements="dict", elements="dict",
ansible_suboptions=dict( ansible_suboptions={
path=dict(required=True, type="str"), "path": {"type": "str", "required": True},
rate=dict(required=True, type="int"), "rate": {"type": "int", "required": True},
), },
) )
OPTION_DEVICE_REQUESTS = OptionGroup().add_option( OPTION_DEVICE_REQUESTS = OptionGroup().add_option(
"device_requests", "device_requests",
value_type="set", value_type="set",
elements="dict", elements="dict",
ansible_suboptions=dict( ansible_suboptions={
capabilities=dict(type="list", elements="list"), "capabilities": {"type": "list", "elements": "list"},
count=dict(type="int"), "count": {"type": "int"},
device_ids=dict(type="list", elements="str"), "device_ids": {"type": "list", "elements": "str"},
driver=dict(type="str"), "driver": {"type": "str"},
options=dict(type="dict"), "options": {"type": "dict"},
), },
) )
OPTION_DEVICE_CGROUP_RULES = OptionGroup().add_option( OPTION_DEVICE_CGROUP_RULES = OptionGroup().add_option(
@ -1066,15 +1066,15 @@ OPTION_GROUPS = OptionGroup().add_option("groups", value_type="set", elements="s
OPTION_HEALTHCHECK = OptionGroup(preprocess=_preprocess_healthcheck).add_option( OPTION_HEALTHCHECK = OptionGroup(preprocess=_preprocess_healthcheck).add_option(
"healthcheck", "healthcheck",
value_type="dict", value_type="dict",
ansible_suboptions=dict( ansible_suboptions={
test=dict(type="raw"), "test": {"type": "raw"},
test_cli_compatible=dict(type="bool", default=False), "test_cli_compatible": {"type": "bool", "default": False},
interval=dict(type="str"), "interval": {"type": "str"},
timeout=dict(type="str"), "timeout": {"type": "str"},
start_period=dict(type="str"), "start_period": {"type": "str"},
start_interval=dict(type="str"), "start_interval": {"type": "str"},
retries=dict(type="int"), "retries": {"type": "int"},
), },
) )
OPTION_HOSTNAME = OptionGroup().add_option("hostname", value_type="str") OPTION_HOSTNAME = OptionGroup().add_option("hostname", value_type="str")
@ -1143,16 +1143,16 @@ OPTION_NETWORK = (
"networks", "networks",
value_type="set", value_type="set",
elements="dict", elements="dict",
ansible_suboptions=dict( ansible_suboptions={
name=dict(type="str", required=True), "name": {"type": "str", "required": True},
ipv4_address=dict(type="str"), "ipv4_address": {"type": "str"},
ipv6_address=dict(type="str"), "ipv6_address": {"type": "str"},
aliases=dict(type="list", elements="str"), "aliases": {"type": "list", "elements": "str"},
links=dict(type="list", elements="str"), "links": {"type": "list", "elements": "str"},
mac_address=dict(type="str"), "mac_address": {"type": "str"},
driver_opts=dict(type="dict"), "driver_opts": {"type": "dict"},
gw_priority=dict(type="int"), "gw_priority": {"type": "int"},
), },
) )
) )
@ -1232,35 +1232,43 @@ OPTION_MOUNTS_VOLUMES = (
"mounts", "mounts",
value_type="set", value_type="set",
elements="dict", elements="dict",
ansible_suboptions=dict( ansible_suboptions={
target=dict(type="str", required=True), "target": {"type": "str", "required": True},
source=dict(type="str"), "source": {"type": "str"},
type=dict( "type": {
type="str", "type": "str",
choices=["bind", "volume", "tmpfs", "npipe", "cluster", "image"], "choices": ["bind", "volume", "tmpfs", "npipe", "cluster", "image"],
default="volume", "default": "volume",
), },
read_only=dict(type="bool"), "read_only": {"type": "bool"},
consistency=dict( "consistency": {
type="str", choices=["default", "consistent", "cached", "delegated"] "type": "str",
), "choices": ["default", "consistent", "cached", "delegated"],
propagation=dict( },
type="str", "propagation": {
choices=["private", "rprivate", "shared", "rshared", "slave", "rslave"], "type": "str",
), "choices": [
no_copy=dict(type="bool"), "private",
labels=dict(type="dict"), "rprivate",
volume_driver=dict(type="str"), "shared",
volume_options=dict(type="dict"), "rshared",
tmpfs_size=dict(type="str"), "slave",
tmpfs_mode=dict(type="str"), "rslave",
non_recursive=dict(type="bool"), ],
create_mountpoint=dict(type="bool"), },
read_only_non_recursive=dict(type="bool"), "no_copy": {"type": "bool"},
read_only_force_recursive=dict(type="bool"), "labels": {"type": "dict"},
subpath=dict(type="str"), "volume_driver": {"type": "str"},
tmpfs_options=dict(type="list", elements="dict"), "volume_options": {"type": "dict"},
), "tmpfs_size": {"type": "str"},
"tmpfs_mode": {"type": "str"},
"non_recursive": {"type": "bool"},
"create_mountpoint": {"type": "bool"},
"read_only_non_recursive": {"type": "bool"},
"read_only_force_recursive": {"type": "bool"},
"subpath": {"type": "str"},
"tmpfs_options": {"type": "list", "elements": "dict"},
},
) )
.add_option("volumes", value_type="set", elements="str") .add_option("volumes", value_type="set", elements="str")
.add_option( .add_option(

View File

@ -398,13 +398,15 @@ class DockerAPIEngineDriver(EngineDriver):
# New docker daemon versions do not allow containers to be removed # New docker daemon versions do not allow containers to be removed
# if they are paused. Make sure we do not end up in an infinite loop. # if they are paused. Make sure we do not end up in an infinite loop.
if count == 3: if count == 3:
raise RuntimeError(f"{exc} [tried to unpause three times]") raise RuntimeError(
f"{exc} [tried to unpause three times]"
) from exc
count += 1 count += 1
# Unpause # Unpause
try: try:
self.unpause_container(client, container_id) self.unpause_container(client, container_id)
except Exception as exc2: except Exception as exc2:
raise RuntimeError(f"{exc2} [while unpausing]") raise RuntimeError(f"{exc2} [while unpausing]") from exc2
# Now try again # Now try again
continue continue
raise raise
@ -429,13 +431,15 @@ class DockerAPIEngineDriver(EngineDriver):
# New docker daemon versions do not allow containers to be removed # New docker daemon versions do not allow containers to be removed
# if they are paused. Make sure we do not end up in an infinite loop. # if they are paused. Make sure we do not end up in an infinite loop.
if count == 3: if count == 3:
raise RuntimeError(f"{exc} [tried to unpause three times]") raise RuntimeError(
f"{exc} [tried to unpause three times]"
) from exc
count += 1 count += 1
# Unpause # Unpause
try: try:
self.unpause_container(client, container_id) self.unpause_container(client, container_id)
except Exception as exc2: except Exception as exc2:
raise RuntimeError(f"{exc2} [while unpausing]") raise RuntimeError(f"{exc2} [while unpausing]") from exc2
# Now try again # Now try again
continue continue
if ( if (
@ -817,28 +821,28 @@ def _preprocess_devices(module, client, api_version, value):
parts = device.split(":") parts = device.split(":")
if len(parts) == 1: if len(parts) == 1:
expected_devices.append( expected_devices.append(
dict( {
CgroupPermissions="rwm", "CgroupPermissions": "rwm",
PathInContainer=parts[0], "PathInContainer": parts[0],
PathOnHost=parts[0], "PathOnHost": parts[0],
) }
) )
elif len(parts) == 2: elif len(parts) == 2:
parts = device.split(":") parts = device.split(":")
expected_devices.append( expected_devices.append(
dict( {
CgroupPermissions="rwm", "CgroupPermissions": "rwm",
PathInContainer=parts[1], "PathInContainer": parts[1],
PathOnHost=parts[0], "PathOnHost": parts[0],
) }
) )
else: else:
expected_devices.append( expected_devices.append(
dict( {
CgroupPermissions=parts[2], "CgroupPermissions": parts[2],
PathInContainer=parts[1], "PathInContainer": parts[1],
PathOnHost=parts[0], "PathOnHost": parts[0],
) }
) )
return expected_devices return expected_devices
@ -1186,7 +1190,7 @@ def _get_expected_values_mounts(
expected_values["mounts"] = values["mounts"] expected_values["mounts"] = values["mounts"]
# volumes # volumes
expected_vols = dict() expected_vols = {}
if image and image["Config"].get("Volumes"): if image and image["Config"].get("Volumes"):
expected_vols.update(image["Config"].get("Volumes")) expected_vols.update(image["Config"].get("Volumes"))
if "volumes" in values: if "volumes" in values:
@ -1400,9 +1404,7 @@ def _get_values_ports(module, container, api_version, options, image, host_info)
# "ExposedPorts": null returns None type & causes AttributeError - PR #5517 # "ExposedPorts": null returns None type & causes AttributeError - PR #5517
if config.get("ExposedPorts") is not None: if config.get("ExposedPorts") is not None:
expected_exposed = [ expected_exposed = [_normalize_port(p) for p in config.get("ExposedPorts", {})]
_normalize_port(p) for p in config.get("ExposedPorts", dict()).keys()
]
else: else:
expected_exposed = [] expected_exposed = []

View File

@ -42,7 +42,7 @@ class Container(DockerBaseClass):
@property @property
def exists(self): def exists(self):
return True if self.container else False return bool(self.container)
@property @property
def removing(self): def removing(self):
@ -232,17 +232,17 @@ class ContainerManager(DockerBaseClass):
"name" "name"
] ]
if self.param_container_default_behavior == "compatibility": if self.param_container_default_behavior == "compatibility":
old_default_values = dict( old_default_values = {
auto_remove=False, "auto_remove": False,
detach=True, "detach": True,
init=False, "init": False,
interactive=False, "interactive": False,
memory="0", "memory": "0",
paused=False, "paused": False,
privileged=False, "privileged": False,
read_only=False, "read_only": False,
tty=False, "tty": False,
) }
for param, value in old_default_values.items(): for param, value in old_default_values.items():
if self.module.params[param] is None: if self.module.params[param] is None:
self.module.params[param] = value self.module.params[param] = value
@ -487,7 +487,7 @@ class ContainerManager(DockerBaseClass):
) )
container = self._get_container(container.id) container = self._get_container(container.id)
self.results["changed"] = True self.results["changed"] = True
self.results["actions"].append(dict(set_paused=self.param_paused)) self.results["actions"].append({"set_paused": self.param_paused})
self.facts = container.raw self.facts = container.raw
@ -577,19 +577,19 @@ class ContainerManager(DockerBaseClass):
if already_to_latest: if already_to_latest:
self.results["changed"] = False self.results["changed"] = False
self.results["actions"].append( self.results["actions"].append(
dict(pulled_image=f"{repository}:{tag}", changed=False) {"pulled_image": f"{repository}:{tag}", "changed": False}
) )
else: else:
self.results["changed"] = True self.results["changed"] = True
self.results["actions"].append( self.results["actions"].append(
dict(pulled_image=f"{repository}:{tag}", changed=True) {"pulled_image": f"{repository}:{tag}", "changed": True}
) )
elif not image or self.param_pull_check_mode_behavior == "always": elif not image or self.param_pull_check_mode_behavior == "always":
# If the image is not there, or pull_check_mode_behavior == 'always', claim we'll # If the image is not there, or pull_check_mode_behavior == 'always', claim we'll
# pull. (Implicitly: if the image is there, claim it already was latest unless # pull. (Implicitly: if the image is there, claim it already was latest unless
# pull_check_mode_behavior == 'always'.) # pull_check_mode_behavior == 'always'.)
self.results["changed"] = True self.results["changed"] = True
action = dict(pulled_image=f"{repository}:{tag}") action = {"pulled_image": f"{repository}:{tag}"}
if not image: if not image:
action["changed"] = True action["changed"] = True
self.results["actions"].append(action) self.results["actions"].append(action)
@ -817,7 +817,7 @@ class ContainerManager(DockerBaseClass):
network_info = connected_networks.get(network["name"]) network_info = connected_networks.get(network["name"])
if network_info is None: if network_info is None:
different = True different = True
differences.append(dict(parameter=network, container=None)) differences.append({"parameter": network, "container": None})
else: else:
diff = False diff = False
network_info_ipam = network_info.get("IPAMConfig") or {} network_info_ipam = network_info.get("IPAMConfig") or {}
@ -855,17 +855,17 @@ class ContainerManager(DockerBaseClass):
if diff: if diff:
different = True different = True
differences.append( differences.append(
dict( {
parameter=network, "parameter": network,
container=dict( "container": {
name=network["name"], "name": network["name"],
ipv4_address=network_info_ipam.get("IPv4Address"), "ipv4_address": network_info_ipam.get("IPv4Address"),
ipv6_address=network_info_ipam.get("IPv6Address"), "ipv6_address": network_info_ipam.get("IPv6Address"),
aliases=network_info.get("Aliases"), "aliases": network_info.get("Aliases"),
links=network_info.get("Links"), "links": network_info.get("Links"),
mac_address=network_info.get("MacAddress"), "mac_address": network_info.get("MacAddress"),
), },
) }
) )
return different, differences return different, differences
@ -892,7 +892,7 @@ class ContainerManager(DockerBaseClass):
if not keep: if not keep:
extra = True extra = True
extra_networks.append( extra_networks.append(
dict(name=network, id=network_config["NetworkID"]) {"name": network, "id": network_config["NetworkID"]}
) )
return extra, extra_networks return extra, extra_networks
@ -905,11 +905,11 @@ class ContainerManager(DockerBaseClass):
if has_network_differences: if has_network_differences:
if self.diff.get("differences"): if self.diff.get("differences"):
self.diff["differences"].append( self.diff["differences"].append(
dict(network_differences=network_differences) {"network_differences": network_differences}
) )
else: else:
self.diff["differences"] = [ self.diff["differences"] = [
dict(network_differences=network_differences) {"network_differences": network_differences}
] ]
for netdiff in network_differences: for netdiff in network_differences:
self.diff_tracker.add( self.diff_tracker.add(
@ -928,9 +928,9 @@ class ContainerManager(DockerBaseClass):
has_extra_networks, extra_networks = self.has_extra_networks(container) has_extra_networks, extra_networks = self.has_extra_networks(container)
if has_extra_networks: if has_extra_networks:
if self.diff.get("differences"): if self.diff.get("differences"):
self.diff["differences"].append(dict(purge_networks=extra_networks)) self.diff["differences"].append({"purge_networks": extra_networks})
else: else:
self.diff["differences"] = [dict(purge_networks=extra_networks)] self.diff["differences"] = [{"purge_networks": extra_networks}]
for extra_network in extra_networks: for extra_network in extra_networks:
self.diff_tracker.add( self.diff_tracker.add(
f"network.{extra_network['name']}", active=extra_network f"network.{extra_network['name']}", active=extra_network
@ -944,7 +944,7 @@ class ContainerManager(DockerBaseClass):
# remove the container from the network, if connected # remove the container from the network, if connected
if diff.get("container"): if diff.get("container"):
self.results["actions"].append( self.results["actions"].append(
dict(removed_from_network=diff["parameter"]["name"]) {"removed_from_network": diff["parameter"]["name"]}
) )
if not self.check_mode: if not self.check_mode:
try: try:
@ -957,10 +957,10 @@ class ContainerManager(DockerBaseClass):
) )
# connect to the network # connect to the network
self.results["actions"].append( self.results["actions"].append(
dict( {
added_to_network=diff["parameter"]["name"], "added_to_network": diff["parameter"]["name"],
network_parameters=diff["parameter"], "network_parameters": diff["parameter"],
) }
) )
if not self.check_mode: if not self.check_mode:
params = { params = {
@ -984,7 +984,7 @@ class ContainerManager(DockerBaseClass):
def _purge_networks(self, container, networks): def _purge_networks(self, container, networks):
for network in networks: for network in networks:
self.results["actions"].append(dict(removed_from_network=network["name"])) self.results["actions"].append({"removed_from_network": network["name"]})
if not self.check_mode: if not self.check_mode:
try: try:
self.engine_driver.disconnect_container_from_network( self.engine_driver.disconnect_container_from_network(
@ -1015,11 +1015,11 @@ class ContainerManager(DockerBaseClass):
if key not in ("name", "id") if key not in ("name", "id")
} }
self.results["actions"].append( self.results["actions"].append(
dict( {
created="Created container", "created": "Created container",
create_parameters=create_parameters, "create_parameters": create_parameters,
networks=networks, "networks": networks,
) }
) )
self.results["changed"] = True self.results["changed"] = True
new_container = None new_container = None
@ -1035,7 +1035,7 @@ class ContainerManager(DockerBaseClass):
def container_start(self, container_id): def container_start(self, container_id):
self.log(f"start container {container_id}") self.log(f"start container {container_id}")
self.results["actions"].append(dict(started=container_id)) self.results["actions"].append({"started": container_id})
self.results["changed"] = True self.results["changed"] = True
if not self.check_mode: if not self.check_mode:
try: try:
@ -1069,7 +1069,7 @@ class ContainerManager(DockerBaseClass):
if insp.raw: if insp.raw:
insp.raw["Output"] = output insp.raw["Output"] = output
else: else:
insp.raw = dict(Output=output) insp.raw = {"Output": output}
if status != 0: if status != 0:
# Set `failed` to True and return output as msg # Set `failed` to True and return output as msg
self.results["failed"] = True self.results["failed"] = True
@ -1083,9 +1083,12 @@ class ContainerManager(DockerBaseClass):
f"remove container container:{container_id} v:{volume_state} link:{link} force{force}" f"remove container container:{container_id} v:{volume_state} link:{link} force{force}"
) )
self.results["actions"].append( self.results["actions"].append(
dict( {
removed=container_id, volume_state=volume_state, link=link, force=force "removed": container_id,
) "volume_state": volume_state,
"link": link,
"force": force,
}
) )
self.results["changed"] = True self.results["changed"] = True
if not self.check_mode: if not self.check_mode:
@ -1105,7 +1108,7 @@ class ContainerManager(DockerBaseClass):
self.log(f"update container {container_id}") self.log(f"update container {container_id}")
self.log(update_parameters, pretty_print=True) self.log(update_parameters, pretty_print=True)
self.results["actions"].append( self.results["actions"].append(
dict(updated=container_id, update_parameters=update_parameters) {"updated": container_id, "update_parameters": update_parameters}
) )
self.results["changed"] = True self.results["changed"] = True
if not self.check_mode: if not self.check_mode:
@ -1119,7 +1122,7 @@ class ContainerManager(DockerBaseClass):
def container_kill(self, container_id): def container_kill(self, container_id):
self.results["actions"].append( self.results["actions"].append(
dict(killed=container_id, signal=self.param_kill_signal) {"killed": container_id, "signal": self.param_kill_signal}
) )
self.results["changed"] = True self.results["changed"] = True
if not self.check_mode: if not self.check_mode:
@ -1132,7 +1135,7 @@ class ContainerManager(DockerBaseClass):
def container_restart(self, container_id): def container_restart(self, container_id):
self.results["actions"].append( self.results["actions"].append(
dict(restarted=container_id, timeout=self.module.params["stop_timeout"]) {"restarted": container_id, "timeout": self.module.params["stop_timeout"]}
) )
self.results["changed"] = True self.results["changed"] = True
if not self.check_mode: if not self.check_mode:
@ -1149,7 +1152,7 @@ class ContainerManager(DockerBaseClass):
self.container_kill(container_id) self.container_kill(container_id)
return return
self.results["actions"].append( self.results["actions"].append(
dict(stopped=container_id, timeout=self.module.params["stop_timeout"]) {"stopped": container_id, "timeout": self.module.params["stop_timeout"]}
) )
self.results["changed"] = True self.results["changed"] = True
if not self.check_mode: if not self.check_mode:
@ -1163,57 +1166,63 @@ class ContainerManager(DockerBaseClass):
def run_module(engine_driver): def run_module(engine_driver):
module, active_options, client = engine_driver.setup( module, active_options, client = engine_driver.setup(
argument_spec=dict( argument_spec={
cleanup=dict(type="bool", default=False), "cleanup": {"type": "bool", "default": False},
comparisons=dict(type="dict"), "comparisons": {"type": "dict"},
container_default_behavior=dict( "container_default_behavior": {
type="str", "type": "str",
default="no_defaults", "default": "no_defaults",
choices=["compatibility", "no_defaults"], "choices": ["compatibility", "no_defaults"],
), },
command_handling=dict( "command_handling": {
type="str", choices=["compatibility", "correct"], default="correct" "type": "str",
), "choices": ["compatibility", "correct"],
default_host_ip=dict(type="str"), "default": "correct",
force_kill=dict(type="bool", default=False, aliases=["forcekill"]), },
image=dict(type="str"), "default_host_ip": {"type": "str"},
image_comparison=dict( "force_kill": {"type": "bool", "default": False, "aliases": ["forcekill"]},
type="str", "image": {"type": "str"},
choices=["desired-image", "current-image"], "image_comparison": {
default="desired-image", "type": "str",
), "choices": ["desired-image", "current-image"],
image_label_mismatch=dict( "default": "desired-image",
type="str", choices=["ignore", "fail"], default="ignore" },
), "image_label_mismatch": {
image_name_mismatch=dict( "type": "str",
type="str", choices=["ignore", "recreate"], default="recreate" "choices": ["ignore", "fail"],
), "default": "ignore",
keep_volumes=dict(type="bool", default=True), },
kill_signal=dict(type="str"), "image_name_mismatch": {
name=dict(type="str", required=True), "type": "str",
networks_cli_compatible=dict(type="bool", default=True), "choices": ["ignore", "recreate"],
output_logs=dict(type="bool", default=False), "default": "recreate",
paused=dict(type="bool"), },
pull=dict( "keep_volumes": {"type": "bool", "default": True},
type="raw", "kill_signal": {"type": "str"},
choices=["never", "missing", "always", True, False], "name": {"type": "str", "required": True},
default="missing", "networks_cli_compatible": {"type": "bool", "default": True},
), "output_logs": {"type": "bool", "default": False},
pull_check_mode_behavior=dict( "paused": {"type": "bool"},
type="str", "pull": {
choices=["image_not_present", "always"], "type": "raw",
default="image_not_present", "choices": ["never", "missing", "always", True, False],
), "default": "missing",
recreate=dict(type="bool", default=False), },
removal_wait_timeout=dict(type="float"), "pull_check_mode_behavior": {
restart=dict(type="bool", default=False), "type": "str",
state=dict( "choices": ["image_not_present", "always"],
type="str", "default": "image_not_present",
default="started", },
choices=["absent", "present", "healthy", "started", "stopped"], "recreate": {"type": "bool", "default": False},
), "removal_wait_timeout": {"type": "float"},
healthy_wait_timeout=dict(type="float", default=300), "restart": {"type": "bool", "default": False},
), "state": {
"type": "str",
"default": "started",
"choices": ["absent", "present", "healthy", "started", "stopped"],
},
"healthy_wait_timeout": {"type": "float", "default": 300},
},
required_if=[ required_if=[
("state", "present", ["image"]), ("state", "present", ["image"]),
], ],

View File

@ -23,38 +23,45 @@ DEFAULT_TLS_VERIFY = False
DEFAULT_TLS_HOSTNAME = "localhost" # deprecated DEFAULT_TLS_HOSTNAME = "localhost" # deprecated
DEFAULT_TIMEOUT_SECONDS = 60 DEFAULT_TIMEOUT_SECONDS = 60
DOCKER_COMMON_ARGS = dict( DOCKER_COMMON_ARGS = {
docker_host=dict( "docker_host": {
type="str", "type": "str",
default=DEFAULT_DOCKER_HOST, "default": DEFAULT_DOCKER_HOST,
fallback=(env_fallback, ["DOCKER_HOST"]), "fallback": (env_fallback, ["DOCKER_HOST"]),
aliases=["docker_url"], "aliases": ["docker_url"],
), },
tls_hostname=dict(type="str", fallback=(env_fallback, ["DOCKER_TLS_HOSTNAME"])), "tls_hostname": {
api_version=dict( "type": "str",
type="str", "fallback": (env_fallback, ["DOCKER_TLS_HOSTNAME"]),
default="auto", },
fallback=(env_fallback, ["DOCKER_API_VERSION"]), "api_version": {
aliases=["docker_api_version"], "type": "str",
), "default": "auto",
timeout=dict( "fallback": (env_fallback, ["DOCKER_API_VERSION"]),
type="int", "aliases": ["docker_api_version"],
default=DEFAULT_TIMEOUT_SECONDS, },
fallback=(env_fallback, ["DOCKER_TIMEOUT"]), "timeout": {
), "type": "int",
ca_path=dict(type="path", aliases=["ca_cert", "tls_ca_cert", "cacert_path"]), "default": DEFAULT_TIMEOUT_SECONDS,
client_cert=dict(type="path", aliases=["tls_client_cert", "cert_path"]), "fallback": (env_fallback, ["DOCKER_TIMEOUT"]),
client_key=dict(type="path", aliases=["tls_client_key", "key_path"]), },
tls=dict(type="bool", default=DEFAULT_TLS, fallback=(env_fallback, ["DOCKER_TLS"])), "ca_path": {"type": "path", "aliases": ["ca_cert", "tls_ca_cert", "cacert_path"]},
use_ssh_client=dict(type="bool", default=False), "client_cert": {"type": "path", "aliases": ["tls_client_cert", "cert_path"]},
validate_certs=dict( "client_key": {"type": "path", "aliases": ["tls_client_key", "key_path"]},
type="bool", "tls": {
default=DEFAULT_TLS_VERIFY, "type": "bool",
fallback=(env_fallback, ["DOCKER_TLS_VERIFY"]), "default": DEFAULT_TLS,
aliases=["tls_verify"], "fallback": (env_fallback, ["DOCKER_TLS"]),
), },
debug=dict(type="bool", default=False), "use_ssh_client": {"type": "bool", "default": False},
) "validate_certs": {
"type": "bool",
"default": DEFAULT_TLS_VERIFY,
"fallback": (env_fallback, ["DOCKER_TLS_VERIFY"]),
"aliases": ["tls_verify"],
},
"debug": {"type": "bool", "default": False},
}
DOCKER_COMMON_ARGS_VARS = { DOCKER_COMMON_ARGS_VARS = {
option_name: f"ansible_docker_{option_name}" option_name: f"ansible_docker_{option_name}"
@ -245,11 +252,11 @@ class DifferenceTracker:
def add(self, name, parameter=None, active=None): def add(self, name, parameter=None, active=None):
self._diff.append( self._diff.append(
dict( {
name=name, "name": name,
parameter=parameter, "parameter": parameter,
active=active, "active": active,
) }
) )
def merge(self, other_tracker): def merge(self, other_tracker):
@ -263,8 +270,8 @@ class DifferenceTracker:
""" """
Return texts ``before`` and ``after``. Return texts ``before`` and ``after``.
""" """
before = dict() before = {}
after = dict() after = {}
for item in self._diff: for item in self._diff:
before[item["name"]] = item["active"] before[item["name"]] = item["active"]
after[item["name"]] = item["parameter"] after[item["name"]] = item["parameter"]
@ -282,11 +289,11 @@ class DifferenceTracker:
""" """
result = [] result = []
for entry in self._diff: for entry in self._diff:
item = dict() item = {}
item[entry["name"]] = dict( item[entry["name"]] = {
parameter=entry["parameter"], "parameter": entry["parameter"],
container=entry["active"], "container": entry["active"],
) }
result.append(item) result.append(item)
return result return result
@ -335,7 +342,7 @@ def clean_dict_booleans_for_docker_api(data, allow_sequences=False):
return "false" return "false"
return str(value) return str(value)
result = dict() result = {}
if data is not None: if data is not None:
for k, v in data.items(): for k, v in data.items():
result[str(k)] = ( result[str(k)] = (
@ -389,7 +396,7 @@ def normalize_healthcheck(healthcheck, normalize_test=False):
""" """
Return dictionary of healthcheck parameters. Return dictionary of healthcheck parameters.
""" """
result = dict() result = {}
# All supported healthcheck parameters # All supported healthcheck parameters
options = ( options = (
@ -420,10 +427,10 @@ def normalize_healthcheck(healthcheck, normalize_test=False):
if key == "retries": if key == "retries":
try: try:
value = int(value) value = int(value)
except ValueError: except ValueError as exc:
raise ValueError( raise ValueError(
f'Cannot parse number of retries for healthcheck. Expected an integer, got "{value}".' f'Cannot parse number of retries for healthcheck. Expected an integer, got "{value}".'
) ) from exc
if key == "test" and value and normalize_test: if key == "test" and value and normalize_test:
value = normalize_healthcheck_test(value) value = normalize_healthcheck_test(value)
result[key] = value result[key] = value

View File

@ -80,7 +80,7 @@ from ansible.module_utils.basic import AnsibleModule
def main(): def main():
module = AnsibleModule(dict(), supports_check_mode=True) module = AnsibleModule({}, supports_check_mode=True)
cpuset_path = "/proc/self/cpuset" cpuset_path = "/proc/self/cpuset"
mountinfo_path = "/proc/self/mountinfo" mountinfo_path = "/proc/self/mountinfo"
@ -136,11 +136,11 @@ def main():
container_type = "podman" container_type = "podman"
module.exit_json( module.exit_json(
ansible_facts=dict( ansible_facts={
ansible_module_running_in_container=container_id != "", "ansible_module_running_in_container": container_id != "",
ansible_module_container_id=container_id, "ansible_module_container_id": container_id,
ansible_module_container_type=container_type, "ansible_module_container_type": container_type,
) }
) )

View File

@ -550,7 +550,7 @@ class ServicesManager(BaseComposeManager):
return args return args
def cmd_up(self): def cmd_up(self):
result = dict() result = {}
args = self.get_up_cmd(self.check_mode) args = self.get_up_cmd(self.check_mode)
rc, stdout, stderr = self.client.call_cli(*args, cwd=self.project_src) rc, stdout, stderr = self.client.call_cli(*args, cwd=self.project_src)
events = self.parse_events(stderr, dry_run=self.check_mode, nonzero_rc=rc != 0) events = self.parse_events(stderr, dry_run=self.check_mode, nonzero_rc=rc != 0)
@ -587,7 +587,7 @@ class ServicesManager(BaseComposeManager):
# Since 'docker compose stop' **always** claims it is stopping containers, even if they are already # Since 'docker compose stop' **always** claims it is stopping containers, even if they are already
# stopped, we have to do this a bit more complicated. # stopped, we have to do this a bit more complicated.
result = dict() result = {}
# Make sure all containers are created # Make sure all containers are created
args_1 = self.get_up_cmd(self.check_mode, no_start=True) args_1 = self.get_up_cmd(self.check_mode, no_start=True)
rc_1, stdout_1, stderr_1 = self.client.call_cli(*args_1, cwd=self.project_src) rc_1, stdout_1, stderr_1 = self.client.call_cli(*args_1, cwd=self.project_src)
@ -644,7 +644,7 @@ class ServicesManager(BaseComposeManager):
return args return args
def cmd_restart(self): def cmd_restart(self):
result = dict() result = {}
args = self.get_restart_cmd(self.check_mode) args = self.get_restart_cmd(self.check_mode)
rc, stdout, stderr = self.client.call_cli(*args, cwd=self.project_src) rc, stdout, stderr = self.client.call_cli(*args, cwd=self.project_src)
events = self.parse_events(stderr, dry_run=self.check_mode, nonzero_rc=rc != 0) events = self.parse_events(stderr, dry_run=self.check_mode, nonzero_rc=rc != 0)
@ -671,7 +671,7 @@ class ServicesManager(BaseComposeManager):
return args return args
def cmd_down(self): def cmd_down(self):
result = dict() result = {}
args = self.get_down_cmd(self.check_mode) args = self.get_down_cmd(self.check_mode)
rc, stdout, stderr = self.client.call_cli(*args, cwd=self.project_src) rc, stdout, stderr = self.client.call_cli(*args, cwd=self.project_src)
events = self.parse_events(stderr, dry_run=self.check_mode, nonzero_rc=rc != 0) events = self.parse_events(stderr, dry_run=self.check_mode, nonzero_rc=rc != 0)
@ -682,32 +682,40 @@ class ServicesManager(BaseComposeManager):
def main(): def main():
argument_spec = dict( argument_spec = {
state=dict( "state": {
type="str", "type": "str",
default="present", "default": "present",
choices=["absent", "present", "stopped", "restarted"], "choices": ["absent", "present", "stopped", "restarted"],
), },
dependencies=dict(type="bool", default=True), "dependencies": {"type": "bool", "default": True},
pull=dict( "pull": {
type="str", "type": "str",
choices=["always", "missing", "never", "policy"], "choices": ["always", "missing", "never", "policy"],
default="policy", "default": "policy",
), },
build=dict(type="str", choices=["always", "never", "policy"], default="policy"), "build": {
recreate=dict(type="str", default="auto", choices=["always", "never", "auto"]), "type": "str",
renew_anon_volumes=dict(type="bool", default=False), "choices": ["always", "never", "policy"],
remove_images=dict(type="str", choices=["all", "local"]), "default": "policy",
remove_volumes=dict(type="bool", default=False), },
remove_orphans=dict(type="bool", default=False), "recreate": {
timeout=dict(type="int"), "type": "str",
services=dict(type="list", elements="str"), "default": "auto",
scale=dict(type="dict"), "choices": ["always", "never", "auto"],
wait=dict(type="bool", default=False), },
wait_timeout=dict(type="int"), "renew_anon_volumes": {"type": "bool", "default": False},
ignore_build_events=dict(type="bool", default=True), "remove_images": {"type": "str", "choices": ["all", "local"]},
assume_yes=dict(type="bool", default=False), "remove_volumes": {"type": "bool", "default": False},
) "remove_orphans": {"type": "bool", "default": False},
"timeout": {"type": "int"},
"services": {"type": "list", "elements": "str"},
"scale": {"type": "dict"},
"wait": {"type": "bool", "default": False},
"wait_timeout": {"type": "int"},
"ignore_build_events": {"type": "bool", "default": True},
"assume_yes": {"type": "bool", "default": False},
}
argspec_ex = common_compose_argspec_ex() argspec_ex = common_compose_argspec_ex()
argument_spec.update(argspec_ex.pop("argspec")) argument_spec.update(argspec_ex.pop("argspec"))

View File

@ -263,21 +263,21 @@ class ExecManager(BaseComposeManager):
def main(): def main():
argument_spec = dict( argument_spec = {
service=dict(type="str", required=True), "service": {"type": "str", "required": True},
index=dict(type="int"), "index": {"type": "int"},
argv=dict(type="list", elements="str"), "argv": {"type": "list", "elements": "str"},
command=dict(type="str"), "command": {"type": "str"},
chdir=dict(type="str"), "chdir": {"type": "str"},
detach=dict(type="bool", default=False), "detach": {"type": "bool", "default": False},
user=dict(type="str"), "user": {"type": "str"},
stdin=dict(type="str"), "stdin": {"type": "str"},
stdin_add_newline=dict(type="bool", default=True), "stdin_add_newline": {"type": "bool", "default": True},
strip_empty_ends=dict(type="bool", default=True), "strip_empty_ends": {"type": "bool", "default": True},
privileged=dict(type="bool", default=False), "privileged": {"type": "bool", "default": False},
tty=dict(type="bool", default=True), "tty": {"type": "bool", "default": True},
env=dict(type="dict"), "env": {"type": "dict"},
) }
argspec_ex = common_compose_argspec_ex() argspec_ex = common_compose_argspec_ex()
argument_spec.update(argspec_ex.pop("argspec")) argument_spec.update(argspec_ex.pop("argspec"))

View File

@ -162,7 +162,7 @@ class PullManager(BaseComposeManager):
return args return args
def run(self): def run(self):
result = dict() result = {}
args = self.get_pull_cmd(self.check_mode) args = self.get_pull_cmd(self.check_mode)
rc, stdout, stderr = self.client.call_cli(*args, cwd=self.project_src) rc, stdout, stderr = self.client.call_cli(*args, cwd=self.project_src)
events = self.parse_events(stderr, dry_run=self.check_mode, nonzero_rc=rc != 0) events = self.parse_events(stderr, dry_run=self.check_mode, nonzero_rc=rc != 0)
@ -180,12 +180,16 @@ class PullManager(BaseComposeManager):
def main(): def main():
argument_spec = dict( argument_spec = {
policy=dict(type="str", choices=["always", "missing"], default="always"), "policy": {
ignore_buildable=dict(type="bool", default=False), "type": "str",
include_deps=dict(type="bool", default=False), "choices": ["always", "missing"],
services=dict(type="list", elements="str"), "default": "always",
) },
"ignore_buildable": {"type": "bool", "default": False},
"include_deps": {"type": "bool", "default": False},
"services": {"type": "list", "elements": "str"},
}
argspec_ex = common_compose_argspec_ex() argspec_ex = common_compose_argspec_ex()
argument_spec.update(argspec_ex.pop("argspec")) argument_spec.update(argspec_ex.pop("argspec"))

View File

@ -383,34 +383,34 @@ class ExecManager(BaseComposeManager):
def main(): def main():
argument_spec = dict( argument_spec = {
service=dict(type="str", required=True), "service": {"type": "str", "required": True},
argv=dict(type="list", elements="str"), "argv": {"type": "list", "elements": "str"},
command=dict(type="str"), "command": {"type": "str"},
build=dict(type="bool", default=False), "build": {"type": "bool", "default": False},
cap_add=dict(type="list", elements="str"), "cap_add": {"type": "list", "elements": "str"},
cap_drop=dict(type="list", elements="str"), "cap_drop": {"type": "list", "elements": "str"},
entrypoint=dict(type="str"), "entrypoint": {"type": "str"},
interactive=dict(type="bool", default=True), "interactive": {"type": "bool", "default": True},
labels=dict(type="list", elements="str"), "labels": {"type": "list", "elements": "str"},
name=dict(type="str"), "name": {"type": "str"},
no_deps=dict(type="bool", default=False), "no_deps": {"type": "bool", "default": False},
publish=dict(type="list", elements="str"), "publish": {"type": "list", "elements": "str"},
quiet_pull=dict(type="bool", default=False), "quiet_pull": {"type": "bool", "default": False},
remove_orphans=dict(type="bool", default=False), "remove_orphans": {"type": "bool", "default": False},
cleanup=dict(type="bool", default=False), "cleanup": {"type": "bool", "default": False},
service_ports=dict(type="bool", default=False), "service_ports": {"type": "bool", "default": False},
use_aliases=dict(type="bool", default=False), "use_aliases": {"type": "bool", "default": False},
volumes=dict(type="list", elements="str"), "volumes": {"type": "list", "elements": "str"},
chdir=dict(type="str"), "chdir": {"type": "str"},
detach=dict(type="bool", default=False), "detach": {"type": "bool", "default": False},
user=dict(type="str"), "user": {"type": "str"},
stdin=dict(type="str"), "stdin": {"type": "str"},
stdin_add_newline=dict(type="bool", default=True), "stdin_add_newline": {"type": "bool", "default": True},
strip_empty_ends=dict(type="bool", default=True), "strip_empty_ends": {"type": "bool", "default": True},
tty=dict(type="bool", default=True), "tty": {"type": "bool", "default": True},
env=dict(type="dict"), "env": {"type": "dict"},
) }
argspec_ex = common_compose_argspec_ex() argspec_ex = common_compose_argspec_ex()
argument_spec.update(argspec_ex.pop("argspec")) argument_spec.update(argspec_ex.pop("argspec"))

View File

@ -387,18 +387,22 @@ class ConfigManager(DockerBaseClass):
def main(): def main():
argument_spec = dict( argument_spec = {
name=dict(type="str", required=True), "name": {"type": "str", "required": True},
state=dict(type="str", default="present", choices=["absent", "present"]), "state": {
data=dict(type="str"), "type": "str",
data_is_b64=dict(type="bool", default=False), "default": "present",
data_src=dict(type="path"), "choices": ["absent", "present"],
labels=dict(type="dict"), },
force=dict(type="bool", default=False), "data": {"type": "str"},
rolling_versions=dict(type="bool", default=False), "data_is_b64": {"type": "bool", "default": False},
versions_to_keep=dict(type="int", default=5), "data_src": {"type": "path"},
template_driver=dict(type="str", choices=["golang"]), "labels": {"type": "dict"},
) "force": {"type": "bool", "default": False},
"rolling_versions": {"type": "bool", "default": False},
"versions_to_keep": {"type": "int", "default": 5},
"template_driver": {"type": "str", "choices": ["golang"]},
}
required_if = [ required_if = [
("state", "present", ["data", "data_src"], True), ("state", "present", ["data", "data_src"], True),
@ -408,9 +412,9 @@ def main():
("data", "data_src"), ("data", "data_src"),
] ]
option_minimal_versions = dict( option_minimal_versions = {
template_driver=dict(docker_py_version="5.0.3", docker_api_version="1.37"), "template_driver": {"docker_py_version": "5.0.3", "docker_api_version": "1.37"},
) }
client = AnsibleDockerClient( client = AnsibleDockerClient(
argument_spec=argument_spec, argument_spec=argument_spec,
@ -424,9 +428,9 @@ def main():
sanitize_labels(client.module.params["labels"], "labels", client) sanitize_labels(client.module.params["labels"], "labels", client)
try: try:
results = dict( results = {
changed=False, "changed": False,
) }
ConfigManager(client, results)() ConfigManager(client, results)()
client.module.exit_json(**results) client.module.exit_json(**results)

View File

@ -484,7 +484,7 @@ def is_file_idempotent(
) )
except OSError as exc: except OSError as exc:
if exc.errno == 2: if exc.errno == 2:
raise DockerFileNotFound(f"Cannot find local file {managed_path}") raise DockerFileNotFound(f"Cannot find local file {managed_path}") from exc
raise raise
if mode is None: if mode is None:
mode = stat.S_IMODE(file_stat.st_mode) mode = stat.S_IMODE(file_stat.st_mode)
@ -752,10 +752,10 @@ def copy_file_into_container(
follow_links=local_follow_links, follow_links=local_follow_links,
) )
result = dict( result = {
container_path=container_path, "container_path": container_path,
changed=changed, "changed": changed,
) }
if diff: if diff:
result["diff"] = diff result["diff"] = diff
client.module.exit_json(**result) client.module.exit_json(**result)
@ -992,10 +992,10 @@ def copy_content_into_container(
mode=mode, mode=mode,
) )
result = dict( result = {
container_path=container_path, "container_path": container_path,
changed=changed, "changed": changed,
) }
if diff: if diff:
# Since the content is no_log, make sure that the before/after strings look sufficiently different # Since the content is no_log, make sure that the before/after strings look sufficiently different
key = generate_insecure_key() key = generate_insecure_key()
@ -1022,26 +1022,26 @@ def parse_octal_string_only(mode):
def main(): def main():
argument_spec = dict( argument_spec = {
container=dict(type="str", required=True), "container": {"type": "str", "required": True},
path=dict(type="path"), "path": {"type": "path"},
container_path=dict(type="str", required=True), "container_path": {"type": "str", "required": True},
follow=dict(type="bool", default=False), "follow": {"type": "bool", "default": False},
local_follow=dict(type="bool", default=True), "local_follow": {"type": "bool", "default": True},
owner_id=dict(type="int"), "owner_id": {"type": "int"},
group_id=dict(type="int"), "group_id": {"type": "int"},
mode=dict(type="raw"), "mode": {"type": "raw"},
mode_parse=dict( "mode_parse": {
type="str", "type": "str",
choices=["legacy", "modern", "octal_string_only"], "choices": ["legacy", "modern", "octal_string_only"],
default="legacy", "default": "legacy",
), },
force=dict(type="bool"), "force": {"type": "bool"},
content=dict(type="str", no_log=True), "content": {"type": "str", "no_log": True},
content_is_b64=dict(type="bool", default=False), "content_is_b64": {"type": "bool", "default": False},
# Undocumented parameters for use by the action plugin # Undocumented parameters for use by the action plugin
_max_file_size_for_diff=dict(type="int"), "_max_file_size_for_diff": {"type": "int"},
) }
client = AnsibleDockerClient( client = AnsibleDockerClient(
argument_spec=argument_spec, argument_spec=argument_spec,

View File

@ -187,23 +187,23 @@ from ansible_collections.community.docker.plugins.module_utils._socket_handler i
def main(): def main():
argument_spec = dict( argument_spec = {
container=dict(type="str", required=True), "container": {"type": "str", "required": True},
argv=dict(type="list", elements="str"), "argv": {"type": "list", "elements": "str"},
command=dict(type="str"), "command": {"type": "str"},
chdir=dict(type="str"), "chdir": {"type": "str"},
detach=dict(type="bool", default=False), "detach": {"type": "bool", "default": False},
user=dict(type="str"), "user": {"type": "str"},
stdin=dict(type="str"), "stdin": {"type": "str"},
stdin_add_newline=dict(type="bool", default=True), "stdin_add_newline": {"type": "bool", "default": True},
strip_empty_ends=dict(type="bool", default=True), "strip_empty_ends": {"type": "bool", "default": True},
tty=dict(type="bool", default=False), "tty": {"type": "bool", "default": False},
env=dict(type="dict"), "env": {"type": "dict"},
) }
option_minimal_versions = dict( option_minimal_versions = {
chdir=dict(docker_api_version="1.35"), "chdir": {"docker_api_version": "1.35"},
) }
client = AnsibleDockerClient( client = AnsibleDockerClient(
argument_spec=argument_spec, argument_spec=argument_spec,

View File

@ -87,9 +87,9 @@ from ansible_collections.community.docker.plugins.module_utils._common_api impor
def main(): def main():
argument_spec = dict( argument_spec = {
name=dict(type="str", required=True), "name": {"type": "str", "required": True},
) }
client = AnsibleDockerClient( client = AnsibleDockerClient(
argument_spec=argument_spec, argument_spec=argument_spec,
@ -101,7 +101,7 @@ def main():
client.module.exit_json( client.module.exit_json(
changed=False, changed=False,
exists=(True if container else False), exists=bool(container),
container=container, container=container,
) )
except DockerException as e: except DockerException as e:

View File

@ -204,10 +204,6 @@ def tls_context_to_json(context):
} }
def to_bool(value):
return True if value else False
def context_to_json(context, current): def context_to_json(context, current):
module_config = {} module_config = {}
if "docker" in context.endpoints: if "docker" in context.endpoints:
@ -240,7 +236,7 @@ def context_to_json(context, current):
module_config["validate_certs"] = tls_cfg.verify module_config["validate_certs"] = tls_cfg.verify
module_config["tls"] = True module_config["tls"] = True
else: else:
module_config["tls"] = to_bool(endpoint.get("SkipTLSVerify")) module_config["tls"] = bool(endpoint.get("SkipTLSVerify"))
return { return {
"current": current, "current": current,
"name": context.name, "name": context.name,
@ -252,11 +248,11 @@ def context_to_json(context, current):
def main(): def main():
argument_spec = dict( argument_spec = {
only_current=dict(type="bool", default=False), "only_current": {"type": "bool", "default": False},
name=dict(type="str"), "name": {"type": "str"},
cli_context=dict(type="str"), "cli_context": {"type": "str"},
) }
module = AnsibleModule( module = AnsibleModule(
argument_spec=argument_spec, argument_spec=argument_spec,

View File

@ -271,7 +271,7 @@ class DockerHostManager(DockerBaseClass):
try: try:
if self.verbose_output: if self.verbose_output:
return self.client.df() return self.client.df()
return dict(LayersSize=self.client.df()["LayersSize"]) return {"LayersSize": self.client.df()["LayersSize"]}
except APIError as exc: except APIError as exc:
self.client.fail(f"Error inspecting docker host: {exc}") self.client.fail(f"Error inspecting docker host: {exc}")
@ -292,7 +292,7 @@ class DockerHostManager(DockerBaseClass):
header_images = ["Id", "RepoTags", "Created", "Size"] header_images = ["Id", "RepoTags", "Created", "Size"]
header_networks = ["Id", "Driver", "Name", "Scope"] header_networks = ["Id", "Driver", "Name", "Scope"]
filter_arg = dict() filter_arg = {}
if filters: if filters:
filter_arg["filters"] = filters filter_arg["filters"] = filters
try: try:
@ -330,7 +330,7 @@ class DockerHostManager(DockerBaseClass):
return items return items
for item in items: for item in items:
item_record = dict() item_record = {}
if docker_object == "containers": if docker_object == "containers":
for key in header_containers: for key in header_containers:
@ -350,26 +350,26 @@ class DockerHostManager(DockerBaseClass):
def main(): def main():
argument_spec = dict( argument_spec = {
containers=dict(type="bool", default=False), "containers": {"type": "bool", "default": False},
containers_all=dict(type="bool", default=False), "containers_all": {"type": "bool", "default": False},
containers_filters=dict(type="dict"), "containers_filters": {"type": "dict"},
images=dict(type="bool", default=False), "images": {"type": "bool", "default": False},
images_filters=dict(type="dict"), "images_filters": {"type": "dict"},
networks=dict(type="bool", default=False), "networks": {"type": "bool", "default": False},
networks_filters=dict(type="dict"), "networks_filters": {"type": "dict"},
volumes=dict(type="bool", default=False), "volumes": {"type": "bool", "default": False},
volumes_filters=dict(type="dict"), "volumes_filters": {"type": "dict"},
disk_usage=dict(type="bool", default=False), "disk_usage": {"type": "bool", "default": False},
verbose_output=dict(type="bool", default=False), "verbose_output": {"type": "bool", "default": False},
) }
client = AnsibleDockerClient( client = AnsibleDockerClient(
argument_spec=argument_spec, argument_spec=argument_spec,
supports_check_mode=True, supports_check_mode=True,
fail_results=dict( fail_results={
can_talk_to_docker=False, "can_talk_to_docker": False,
), },
) )
if ( if (
client.module.params["api_version"] is None client.module.params["api_version"] is None
@ -379,9 +379,9 @@ def main():
client.fail_results["can_talk_to_docker"] = True client.fail_results["can_talk_to_docker"] = True
try: try:
results = dict( results = {
changed=False, "changed": False,
) }
DockerHostManager(client, results) DockerHostManager(client, results)
client.module.exit_json(**results) client.module.exit_json(**results)

View File

@ -442,8 +442,8 @@ class ImageManager(DockerBaseClass):
self.check_mode = self.client.check_mode self.check_mode = self.client.check_mode
self.source = parameters["source"] self.source = parameters["source"]
build = parameters["build"] or dict() build = parameters["build"] or {}
pull = parameters["pull"] or dict() pull = parameters["pull"] or {}
self.archive_path = parameters["archive_path"] self.archive_path = parameters["archive_path"]
self.cache_from = build.get("cache_from") self.cache_from = build.get("cache_from")
self.container_limits = build.get("container_limits") self.container_limits = build.get("container_limits")
@ -796,7 +796,7 @@ class ImageManager(DockerBaseClass):
self.fail(f"Error pushing image {repository}: {exc}") self.fail(f"Error pushing image {repository}: {exc}")
self.results["image"] = self.client.find_image(name=repository, tag=tag) self.results["image"] = self.client.find_image(name=repository, tag=tag)
if not self.results["image"]: if not self.results["image"]:
self.results["image"] = dict() self.results["image"] = {}
self.results["image"]["push_status"] = status self.results["image"]["push_status"] = status
def tag_image(self, name, tag, repository, push=False): def tag_image(self, name, tag, repository, push=False):
@ -1079,54 +1079,58 @@ class ImageManager(DockerBaseClass):
def main(): def main():
argument_spec = dict( argument_spec = {
source=dict(type="str", choices=["build", "load", "pull", "local"]), "source": {"type": "str", "choices": ["build", "load", "pull", "local"]},
build=dict( "build": {
type="dict", "type": "dict",
options=dict( "options": {
cache_from=dict(type="list", elements="str"), "cache_from": {"type": "list", "elements": "str"},
container_limits=dict( "container_limits": {
type="dict", "type": "dict",
options=dict( "options": {
memory=dict(type="str"), "memory": {"type": "str"},
memswap=dict(type="str"), "memswap": {"type": "str"},
cpushares=dict(type="int"), "cpushares": {"type": "int"},
cpusetcpus=dict(type="str"), "cpusetcpus": {"type": "str"},
), },
), },
dockerfile=dict(type="str"), "dockerfile": {"type": "str"},
http_timeout=dict(type="int"), "http_timeout": {"type": "int"},
network=dict(type="str"), "network": {"type": "str"},
nocache=dict(type="bool", default=False), "nocache": {"type": "bool", "default": False},
path=dict(type="path", required=True), "path": {"type": "path", "required": True},
pull=dict(type="bool", default=False), "pull": {"type": "bool", "default": False},
rm=dict(type="bool", default=True), "rm": {"type": "bool", "default": True},
args=dict(type="dict"), "args": {"type": "dict"},
use_config_proxy=dict(type="bool"), "use_config_proxy": {"type": "bool"},
target=dict(type="str"), "target": {"type": "str"},
etc_hosts=dict(type="dict"), "etc_hosts": {"type": "dict"},
platform=dict(type="str"), "platform": {"type": "str"},
shm_size=dict(type="str"), "shm_size": {"type": "str"},
labels=dict(type="dict"), "labels": {"type": "dict"},
), },
), },
archive_path=dict(type="path"), "archive_path": {"type": "path"},
force_source=dict(type="bool", default=False), "force_source": {"type": "bool", "default": False},
force_absent=dict(type="bool", default=False), "force_absent": {"type": "bool", "default": False},
force_tag=dict(type="bool", default=False), "force_tag": {"type": "bool", "default": False},
load_path=dict(type="path"), "load_path": {"type": "path"},
name=dict(type="str", required=True), "name": {"type": "str", "required": True},
pull=dict( "pull": {
type="dict", "type": "dict",
options=dict( "options": {
platform=dict(type="str"), "platform": {"type": "str"},
), },
), },
push=dict(type="bool", default=False), "push": {"type": "bool", "default": False},
repository=dict(type="str"), "repository": {"type": "str"},
state=dict(type="str", default="present", choices=["absent", "present"]), "state": {
tag=dict(type="str", default="latest"), "type": "str",
) "default": "present",
"choices": ["absent", "present"],
},
"tag": {"type": "str", "default": "latest"},
}
required_if = [ required_if = [
("state", "present", ["source"]), ("state", "present", ["source"]),
@ -1151,16 +1155,20 @@ def main():
and client.module.params["pull"].get("platform") is not None and client.module.params["pull"].get("platform") is not None
) )
option_minimal_versions = dict() option_minimal_versions = {
option_minimal_versions["build.etc_hosts"] = dict( "build.etc_hosts": {
docker_api_version="1.27", detect_usage=detect_etc_hosts "docker_api_version": "1.27",
) "detect_usage": detect_etc_hosts,
option_minimal_versions["build.platform"] = dict( },
docker_api_version="1.32", detect_usage=detect_build_platform "build.platform": {
) "docker_api_version": "1.32",
option_minimal_versions["pull.platform"] = dict( "detect_usage": detect_build_platform,
docker_api_version="1.32", detect_usage=detect_pull_platform },
) "pull.platform": {
"docker_api_version": "1.32",
"detect_usage": detect_pull_platform,
},
}
client = AnsibleDockerClient( client = AnsibleDockerClient(
argument_spec=argument_spec, argument_spec=argument_spec,
@ -1181,7 +1189,7 @@ def main():
) )
try: try:
results = dict(changed=False, actions=[], image={}) results = {"changed": False, "actions": [], "image": {}}
ImageManager(client, results) ImageManager(client, results)
client.module.exit_json(**results) client.module.exit_json(**results)

View File

@ -514,11 +514,11 @@ class ImageBuilder(DockerBaseClass):
def build_image(self): def build_image(self):
image = self.client.find_image(self.name, self.tag) image = self.client.find_image(self.name, self.tag)
results = dict( results = {
changed=False, "changed": False,
actions=[], "actions": [],
image=image or {}, "image": image or {},
) }
if image: if image:
if self.rebuild == "never": if self.rebuild == "never":
@ -548,69 +548,73 @@ class ImageBuilder(DockerBaseClass):
def main(): def main():
argument_spec = dict( argument_spec = {
name=dict(type="str", required=True), "name": {"type": "str", "required": True},
tag=dict(type="str", default="latest"), "tag": {"type": "str", "default": "latest"},
path=dict(type="path", required=True), "path": {"type": "path", "required": True},
dockerfile=dict(type="str"), "dockerfile": {"type": "str"},
cache_from=dict(type="list", elements="str"), "cache_from": {"type": "list", "elements": "str"},
pull=dict(type="bool", default=False), "pull": {"type": "bool", "default": False},
network=dict(type="str"), "network": {"type": "str"},
nocache=dict(type="bool", default=False), "nocache": {"type": "bool", "default": False},
etc_hosts=dict(type="dict"), "etc_hosts": {"type": "dict"},
args=dict(type="dict"), "args": {"type": "dict"},
target=dict(type="str"), "target": {"type": "str"},
platform=dict(type="list", elements="str"), "platform": {"type": "list", "elements": "str"},
shm_size=dict(type="str"), "shm_size": {"type": "str"},
labels=dict(type="dict"), "labels": {"type": "dict"},
rebuild=dict(type="str", choices=["never", "always"], default="never"), "rebuild": {"type": "str", "choices": ["never", "always"], "default": "never"},
secrets=dict( "secrets": {
type="list", "type": "list",
elements="dict", "elements": "dict",
options=dict( "options": {
id=dict(type="str", required=True), "id": {"type": "str", "required": True},
type=dict(type="str", choices=["file", "env", "value"], required=True), "type": {
src=dict(type="path"), "type": "str",
env=dict(type="str"), "choices": ["file", "env", "value"],
value=dict(type="str", no_log=True), "required": True,
), },
required_if=[ "src": {"type": "path"},
"env": {"type": "str"},
"value": {"type": "str", "no_log": True},
},
"required_if": [
("type", "file", ["src"]), ("type", "file", ["src"]),
("type", "env", ["env"]), ("type", "env", ["env"]),
("type", "value", ["value"]), ("type", "value", ["value"]),
], ],
mutually_exclusive=[ "mutually_exclusive": [
("src", "env", "value"), ("src", "env", "value"),
], ],
no_log=False, "no_log": False,
), },
outputs=dict( "outputs": {
type="list", "type": "list",
elements="dict", "elements": "dict",
options=dict( "options": {
type=dict( "type": {
type="str", "type": "str",
choices=["local", "tar", "oci", "docker", "image"], "choices": ["local", "tar", "oci", "docker", "image"],
required=True, "required": True,
), },
dest=dict(type="path"), "dest": {"type": "path"},
context=dict(type="str"), "context": {"type": "str"},
name=dict(type="list", elements="str"), "name": {"type": "list", "elements": "str"},
push=dict(type="bool", default=False), "push": {"type": "bool", "default": False},
), },
required_if=[ "required_if": [
("type", "local", ["dest"]), ("type", "local", ["dest"]),
("type", "tar", ["dest"]), ("type", "tar", ["dest"]),
("type", "oci", ["dest"]), ("type", "oci", ["dest"]),
], ],
mutually_exclusive=[ "mutually_exclusive": [
("dest", "name"), ("dest", "name"),
("dest", "push"), ("dest", "push"),
("context", "name"), ("context", "name"),
("context", "push"), ("context", "push"),
], ],
), },
) }
client = AnsibleModuleDockerClient( client = AnsibleModuleDockerClient(
argument_spec=argument_spec, argument_spec=argument_spec,

View File

@ -261,12 +261,17 @@ class ImageExportManager(DockerBaseClass):
def main(): def main():
argument_spec = dict( argument_spec = {
path=dict(type="path"), "path": {"type": "path"},
force=dict(type="bool", default=False), "force": {"type": "bool", "default": False},
names=dict(type="list", elements="str", required=True, aliases=["name"]), "names": {
tag=dict(type="str", default="latest"), "type": "list",
) "elements": "str",
"required": True,
"aliases": ["name"],
},
"tag": {"type": "str", "default": "latest"},
}
client = AnsibleDockerClient( client = AnsibleDockerClient(
argument_spec=argument_spec, argument_spec=argument_spec,

View File

@ -219,9 +219,9 @@ class ImageManager(DockerBaseClass):
def main(): def main():
argument_spec = dict( argument_spec = {
name=dict(type="list", elements="str"), "name": {"type": "list", "elements": "str"},
) }
client = AnsibleDockerClient( client = AnsibleDockerClient(
argument_spec=argument_spec, argument_spec=argument_spec,
@ -229,7 +229,7 @@ def main():
) )
try: try:
results = dict(changed=False, images=[]) results = {"changed": False, "images": []}
ImageManager(client, results) ImageManager(client, results)
client.module.exit_json(**results) client.module.exit_json(**results)

View File

@ -181,17 +181,17 @@ class ImageManager(DockerBaseClass):
def main(): def main():
client = AnsibleDockerClient( client = AnsibleDockerClient(
argument_spec=dict( argument_spec={
path=dict(type="path", required=True), "path": {"type": "path", "required": True},
), },
supports_check_mode=False, supports_check_mode=False,
) )
try: try:
results = dict( results = {
image_names=[], "image_names": [],
images=[], "images": [],
) }
ImageManager(client, results) ImageManager(client, results)
client.module.exit_json(**results) client.module.exit_json(**results)

View File

@ -149,12 +149,12 @@ class ImagePuller(DockerBaseClass):
def pull(self): def pull(self):
image = self.client.find_image(name=self.name, tag=self.tag) image = self.client.find_image(name=self.name, tag=self.tag)
results = dict( results = {
changed=False, "changed": False,
actions=[], "actions": [],
image=image or {}, "image": image or {},
diff=dict(before=image_info(image), after=image_info(image)), "diff": {"before": image_info(image), "after": image_info(image)},
) }
if image and self.pull_mode == "not_present": if image and self.pull_mode == "not_present":
if self.platform is None: if self.platform is None:
@ -178,7 +178,7 @@ class ImagePuller(DockerBaseClass):
results["actions"].append(f"Pulled image {self.name}:{self.tag}") results["actions"].append(f"Pulled image {self.name}:{self.tag}")
if self.check_mode: if self.check_mode:
results["changed"] = True results["changed"] = True
results["diff"]["after"] = image_info(dict(Id="unknown")) results["diff"]["after"] = image_info({"Id": "unknown"})
else: else:
results["image"], not_changed = self.client.pull_image( results["image"], not_changed = self.client.pull_image(
self.name, tag=self.tag, image_platform=self.platform self.name, tag=self.tag, image_platform=self.platform
@ -190,16 +190,20 @@ class ImagePuller(DockerBaseClass):
def main(): def main():
argument_spec = dict( argument_spec = {
name=dict(type="str", required=True), "name": {"type": "str", "required": True},
tag=dict(type="str", default="latest"), "tag": {"type": "str", "default": "latest"},
platform=dict(type="str"), "platform": {"type": "str"},
pull=dict(type="str", choices=["always", "not_present"], default="always"), "pull": {
) "type": "str",
"choices": ["always", "not_present"],
"default": "always",
},
}
option_minimal_versions = dict( option_minimal_versions = {
platform=dict(docker_api_version="1.32"), "platform": {"docker_api_version": "1.32"},
) }
client = AnsibleDockerClient( client = AnsibleDockerClient(
argument_spec=argument_spec, argument_spec=argument_spec,

View File

@ -127,11 +127,11 @@ class ImagePusher(DockerBaseClass):
if not image: if not image:
self.client.fail(f"Cannot find image {self.name}:{self.tag}") self.client.fail(f"Cannot find image {self.name}:{self.tag}")
results = dict( results = {
changed=False, "changed": False,
actions=[], "actions": [],
image=image, "image": image,
) }
push_registry, push_repo = resolve_repository_name(self.name) push_registry, push_repo = resolve_repository_name(self.name)
try: try:
@ -175,10 +175,10 @@ class ImagePusher(DockerBaseClass):
def main(): def main():
argument_spec = dict( argument_spec = {
name=dict(type="str", required=True), "name": {"type": "str", "required": True},
tag=dict(type="str", default="latest"), "tag": {"type": "str", "default": "latest"},
) }
client = AnsibleDockerClient( client = AnsibleDockerClient(
argument_spec=argument_spec, argument_spec=argument_spec,

View File

@ -147,22 +147,22 @@ class ImageRemover(DockerBaseClass):
def get_diff_state(self, image): def get_diff_state(self, image):
if not image: if not image:
return dict(exists=False) return {"exists": False}
return dict( return {
exists=True, "exists": True,
id=image["Id"], "id": image["Id"],
tags=sorted(image.get("RepoTags") or []), "tags": sorted(image.get("RepoTags") or []),
digests=sorted(image.get("RepoDigests") or []), "digests": sorted(image.get("RepoDigests") or []),
) }
def absent(self): def absent(self):
results = dict( results = {
changed=False, "changed": False,
actions=[], "actions": [],
image={}, "image": {},
deleted=[], "deleted": [],
untagged=[], "untagged": [],
) }
name = self.name name = self.name
if is_image_name_id(name): if is_image_name_id(name):
@ -173,7 +173,7 @@ class ImageRemover(DockerBaseClass):
name = f"{self.name}:{self.tag}" name = f"{self.name}:{self.tag}"
if self.diff: if self.diff:
results["diff"] = dict(before=self.get_diff_state(image)) results["diff"] = {"before": self.get_diff_state(image)}
if not image: if not image:
if self.diff: if self.diff:
@ -256,12 +256,12 @@ class ImageRemover(DockerBaseClass):
def main(): def main():
argument_spec = dict( argument_spec = {
name=dict(type="str", required=True), "name": {"type": "str", "required": True},
tag=dict(type="str", default="latest"), "tag": {"type": "str", "default": "latest"},
force=dict(type="bool", default=False), "force": {"type": "bool", "default": False},
prune=dict(type="bool", default=True), "prune": {"type": "bool", "default": True},
) }
client = AnsibleDockerClient( client = AnsibleDockerClient(
argument_spec=argument_spec, argument_spec=argument_spec,

View File

@ -133,7 +133,7 @@ def convert_to_bytes(value, module, name, unlimited_value=None):
def image_info(name, tag, image): def image_info(name, tag, image):
result = dict(name=name, tag=tag) result = {"name": name, "tag": tag}
if image: if image:
result["id"] = image["Id"] result["id"] = image["Id"]
else: else:
@ -231,13 +231,13 @@ class ImageTagger(DockerBaseClass):
before = [] before = []
after = [] after = []
tagged_images = [] tagged_images = []
results = dict( results = {
changed=False, "changed": False,
actions=[], "actions": [],
image=image, "image": image,
tagged_images=tagged_images, "tagged_images": tagged_images,
diff=dict(before=dict(images=before), after=dict(images=after)), "diff": {"before": {"images": before}, "after": {"images": after}},
) }
for repository, tag in self.repositories: for repository, tag in self.repositories:
tagged, msg, old_image = self.tag_image(image, repository, tag) tagged, msg, old_image = self.tag_image(image, repository, tag)
before.append(image_info(repository, tag, old_image)) before.append(image_info(repository, tag, old_image))
@ -257,14 +257,16 @@ class ImageTagger(DockerBaseClass):
def main(): def main():
argument_spec = dict( argument_spec = {
name=dict(type="str", required=True), "name": {"type": "str", "required": True},
tag=dict(type="str", default="latest"), "tag": {"type": "str", "default": "latest"},
repository=dict(type="list", elements="str", required=True), "repository": {"type": "list", "elements": "str", "required": True},
existing_images=dict( "existing_images": {
type="str", choices=["keep", "overwrite"], default="overwrite" "type": "str",
), "choices": ["keep", "overwrite"],
) "default": "overwrite",
},
}
client = AnsibleDockerClient( client = AnsibleDockerClient(
argument_spec=argument_spec, argument_spec=argument_spec,

View File

@ -158,7 +158,7 @@ class DockerFileStore:
self._config_path = config_path self._config_path = config_path
# Make sure we have a minimal config if none is available. # Make sure we have a minimal config if none is available.
self._config = dict(auths=dict()) self._config = {"auths": {}}
try: try:
# Attempt to read the existing config. # Attempt to read the existing config.
@ -166,7 +166,7 @@ class DockerFileStore:
config = json.load(f) config = json.load(f)
except (ValueError, IOError): except (ValueError, IOError):
# No config found or an invalid config found so we'll ignore it. # No config found or an invalid config found so we'll ignore it.
config = dict() config = {}
# Update our internal config with what ever was loaded. # Update our internal config with what ever was loaded.
self._config.update(config) self._config.update(config)
@ -191,7 +191,7 @@ class DockerFileStore:
(username, password) = decode_auth(server_creds["auth"]) (username, password) = decode_auth(server_creds["auth"])
return dict(Username=username, Secret=password) return {"Username": username, "Secret": password}
def _write(self): def _write(self):
""" """
@ -219,9 +219,9 @@ class DockerFileStore:
# build up the auth structure # build up the auth structure
if "auths" not in self._config: if "auths" not in self._config:
self._config["auths"] = dict() self._config["auths"] = {}
self._config["auths"][server] = dict(auth=tauth) self._config["auths"][server] = {"auth": tauth}
self._write() self._write()
@ -368,7 +368,7 @@ class LoginManager(DockerBaseClass):
current = store.get(self.registry_url) current = store.get(self.registry_url)
except CredentialsNotFound: except CredentialsNotFound:
# get raises an exception on not found. # get raises an exception on not found.
current = dict(Username="", Secret="") current = {"Username": "", "Secret": ""}
if ( if (
current["Username"] != self.username current["Username"] != self.username
@ -410,18 +410,26 @@ class LoginManager(DockerBaseClass):
def main(): def main():
argument_spec = dict( argument_spec = {
registry_url=dict( "registry_url": {
type="str", default=DEFAULT_DOCKER_REGISTRY, aliases=["registry", "url"] "type": "str",
), "default": DEFAULT_DOCKER_REGISTRY,
username=dict(type="str"), "aliases": ["registry", "url"],
password=dict(type="str", no_log=True), },
reauthorize=dict(type="bool", default=False, aliases=["reauth"]), "username": {"type": "str"},
state=dict(type="str", default="present", choices=["present", "absent"]), "password": {"type": "str", "no_log": True},
config_path=dict( "reauthorize": {"type": "bool", "default": False, "aliases": ["reauth"]},
type="path", default="~/.docker/config.json", aliases=["dockercfg_path"] "state": {
), "type": "str",
) "default": "present",
"choices": ["present", "absent"],
},
"config_path": {
"type": "path",
"default": "~/.docker/config.json",
"aliases": ["dockercfg_path"],
},
}
required_if = [ required_if = [
("state", "present", ["username", "password"]), ("state", "present", ["username", "password"]),
@ -434,7 +442,7 @@ def main():
) )
try: try:
results = dict(changed=False, actions=[], login_result={}) results = {"changed": False, "actions": [], "login_result": {}}
manager = LoginManager(client, results) manager = LoginManager(client, results)
manager.run() manager.run()

View File

@ -395,7 +395,7 @@ class DockerNetworkManager:
self.results = {"changed": False, "actions": []} self.results = {"changed": False, "actions": []}
self.diff = self.client.module._diff self.diff = self.client.module._diff
self.diff_tracker = DifferenceTracker() self.diff_tracker = DifferenceTracker()
self.diff_result = dict() self.diff_result = {}
self.existing_network = self.get_existing_network() self.existing_network = self.get_existing_network()
@ -511,13 +511,13 @@ class DockerNetworkManager:
# Put network's IPAM config into the same format as module's IPAM config # Put network's IPAM config into the same format as module's IPAM config
net_ipam_configs = [] net_ipam_configs = []
for net_ipam_config in net["IPAM"]["Config"]: for net_ipam_config in net["IPAM"]["Config"]:
config = dict() config = {}
for k, v in net_ipam_config.items(): for k, v in net_ipam_config.items():
config[normalize_ipam_config_key(k)] = v config[normalize_ipam_config_key(k)] = v
net_ipam_configs.append(config) net_ipam_configs.append(config)
# Compare lists of dicts as sets of dicts # Compare lists of dicts as sets of dicts
for idx, ipam_config in enumerate(self.parameters.ipam_config): for idx, ipam_config in enumerate(self.parameters.ipam_config):
net_config = dict() net_config = {}
for net_ipam_config in net_ipam_configs: for net_ipam_config in net_ipam_configs:
if dicts_are_essentially_equal(ipam_config, net_ipam_config): if dicts_are_essentially_equal(ipam_config, net_ipam_config):
net_config = net_ipam_config net_config = net_ipam_config
@ -779,45 +779,54 @@ class DockerNetworkManager:
def main(): def main():
argument_spec = dict( argument_spec = {
name=dict(type="str", required=True, aliases=["network_name"]), "name": {"type": "str", "required": True, "aliases": ["network_name"]},
config_from=dict(type="str"), "config_from": {"type": "str"},
config_only=dict(type="bool"), "config_only": {"type": "bool"},
connected=dict(type="list", default=[], elements="str", aliases=["containers"]), "connected": {
state=dict(type="str", default="present", choices=["present", "absent"]), "type": "list",
driver=dict(type="str", default="bridge"), "default": [],
driver_options=dict(type="dict", default={}), "elements": "str",
force=dict(type="bool", default=False), "aliases": ["containers"],
appends=dict(type="bool", default=False, aliases=["incremental"]), },
ipam_driver=dict(type="str"), "state": {
ipam_driver_options=dict(type="dict"), "type": "str",
ipam_config=dict( "default": "present",
type="list", "choices": ["present", "absent"],
elements="dict", },
options=dict( "driver": {"type": "str", "default": "bridge"},
subnet=dict(type="str"), "driver_options": {"type": "dict", "default": {}},
iprange=dict(type="str"), "force": {"type": "bool", "default": False},
gateway=dict(type="str"), "appends": {"type": "bool", "default": False, "aliases": ["incremental"]},
aux_addresses=dict(type="dict"), "ipam_driver": {"type": "str"},
), "ipam_driver_options": {"type": "dict"},
), "ipam_config": {
enable_ipv4=dict(type="bool"), "type": "list",
enable_ipv6=dict(type="bool"), "elements": "dict",
internal=dict(type="bool"), "options": {
labels=dict(type="dict", default={}), "subnet": {"type": "str"},
debug=dict(type="bool", default=False), "iprange": {"type": "str"},
scope=dict(type="str", choices=["local", "global", "swarm"]), "gateway": {"type": "str"},
attachable=dict(type="bool"), "aux_addresses": {"type": "dict"},
ingress=dict(type="bool"), },
) },
"enable_ipv4": {"type": "bool"},
"enable_ipv6": {"type": "bool"},
"internal": {"type": "bool"},
"labels": {"type": "dict", "default": {}},
"debug": {"type": "bool", "default": False},
"scope": {"type": "str", "choices": ["local", "global", "swarm"]},
"attachable": {"type": "bool"},
"ingress": {"type": "bool"},
}
option_minimal_versions = dict( option_minimal_versions = {
config_from=dict(docker_api_version="1.30"), "config_from": {"docker_api_version": "1.30"},
config_only=dict(docker_api_version="1.30"), "config_only": {"docker_api_version": "1.30"},
scope=dict(docker_api_version="1.30"), "scope": {"docker_api_version": "1.30"},
attachable=dict(docker_api_version="1.26"), "attachable": {"docker_api_version": "1.26"},
enable_ipv4=dict(docker_api_version="1.47"), "enable_ipv4": {"docker_api_version": "1.47"},
) }
client = AnsibleDockerClient( client = AnsibleDockerClient(
argument_spec=argument_spec, argument_spec=argument_spec,

View File

@ -108,9 +108,9 @@ from ansible_collections.community.docker.plugins.module_utils._common_api impor
def main(): def main():
argument_spec = dict( argument_spec = {
name=dict(type="str", required=True), "name": {"type": "str", "required": True},
) }
client = AnsibleDockerClient( client = AnsibleDockerClient(
argument_spec=argument_spec, argument_spec=argument_spec,
@ -122,7 +122,7 @@ def main():
client.module.exit_json( client.module.exit_json(
changed=False, changed=False,
exists=(True if network else False), exists=bool(network),
network=network, network=network,
) )
except DockerException as e: except DockerException as e:

View File

@ -206,11 +206,11 @@ class SwarmNodeManager(DockerBaseClass):
self.client.fail(f"Failed to get node information for {exc}") self.client.fail(f"Failed to get node information for {exc}")
changed = False changed = False
node_spec = dict( node_spec = {
Availability=self.parameters.availability, "Availability": self.parameters.availability,
Role=self.parameters.role, "Role": self.parameters.role,
Labels=self.parameters.labels, "Labels": self.parameters.labels,
) }
if self.parameters.role is None: if self.parameters.role is None:
node_spec["Role"] = node_info["Spec"]["Role"] node_spec["Role"] = node_info["Spec"]["Role"]
@ -278,14 +278,18 @@ class SwarmNodeManager(DockerBaseClass):
def main(): def main():
argument_spec = dict( argument_spec = {
hostname=dict(type="str", required=True), "hostname": {"type": "str", "required": True},
labels=dict(type="dict"), "labels": {"type": "dict"},
labels_state=dict(type="str", default="merge", choices=["merge", "replace"]), "labels_state": {
labels_to_remove=dict(type="list", elements="str"), "type": "str",
availability=dict(type="str", choices=["active", "pause", "drain"]), "default": "merge",
role=dict(type="str", choices=["worker", "manager"]), "choices": ["merge", "replace"],
) },
"labels_to_remove": {"type": "list", "elements": "str"},
"availability": {"type": "str", "choices": ["active", "pause", "drain"]},
"role": {"type": "str", "choices": ["worker", "manager"]},
}
client = AnsibleDockerSwarmClient( client = AnsibleDockerSwarmClient(
argument_spec=argument_spec, argument_spec=argument_spec,
@ -294,9 +298,9 @@ def main():
) )
try: try:
results = dict( results = {
changed=False, "changed": False,
) }
SwarmNodeManager(client, results) SwarmNodeManager(client, results)
client.module.exit_json(**results) client.module.exit_json(**results)

View File

@ -131,10 +131,10 @@ def get_node_facts(client):
def main(): def main():
argument_spec = dict( argument_spec = {
name=dict(type="list", elements="str"), "name": {"type": "list", "elements": "str"},
self=dict(type="bool", default=False), "self": {"type": "bool", "default": False},
) }
client = AnsibleDockerSwarmClient( client = AnsibleDockerSwarmClient(
argument_spec=argument_spec, argument_spec=argument_spec,

View File

@ -185,7 +185,7 @@ class DockerPluginManager:
self.check_mode = self.client.check_mode self.check_mode = self.client.check_mode
self.diff = self.client.module._diff self.diff = self.client.module._diff
self.diff_tracker = DifferenceTracker() self.diff_tracker = DifferenceTracker()
self.diff_result = dict() self.diff_result = {}
self.actions = [] self.actions = []
self.changed = False self.changed = False
@ -255,7 +255,7 @@ class DockerPluginManager:
try: try:
# Get privileges # Get privileges
headers = {} headers = {}
registry, repo_name = auth.resolve_repository_name( registry, dummy_repo_name = auth.resolve_repository_name(
self.parameters.plugin_name self.parameters.plugin_name
) )
header = auth.get_config_header(self.client, registry) header = auth.get_config_header(self.client, registry)
@ -416,19 +416,19 @@ class DockerPluginManager:
def main(): def main():
argument_spec = dict( argument_spec = {
alias=dict(type="str"), "alias": {"type": "str"},
plugin_name=dict(type="str", required=True), "plugin_name": {"type": "str", "required": True},
state=dict( "state": {
type="str", "type": "str",
default="present", "default": "present",
choices=["present", "absent", "enable", "disable"], "choices": ["present", "absent", "enable", "disable"],
), },
plugin_options=dict(type="dict", default={}), "plugin_options": {"type": "dict", "default": {}},
debug=dict(type="bool", default=False), "debug": {"type": "bool", "default": False},
force_remove=dict(type="bool", default=False), "force_remove": {"type": "bool", "default": False},
enable_timeout=dict(type="int", default=0), "enable_timeout": {"type": "int", "default": 0},
) }
client = AnsibleDockerClient( client = AnsibleDockerClient(
argument_spec=argument_spec, argument_spec=argument_spec,
supports_check_mode=True, supports_check_mode=True,

View File

@ -248,29 +248,29 @@ from ansible_collections.community.docker.plugins.module_utils._util import (
def main(): def main():
argument_spec = dict( argument_spec = {
containers=dict(type="bool", default=False), "containers": {"type": "bool", "default": False},
containers_filters=dict(type="dict"), "containers_filters": {"type": "dict"},
images=dict(type="bool", default=False), "images": {"type": "bool", "default": False},
images_filters=dict(type="dict"), "images_filters": {"type": "dict"},
networks=dict(type="bool", default=False), "networks": {"type": "bool", "default": False},
networks_filters=dict(type="dict"), "networks_filters": {"type": "dict"},
volumes=dict(type="bool", default=False), "volumes": {"type": "bool", "default": False},
volumes_filters=dict(type="dict"), "volumes_filters": {"type": "dict"},
builder_cache=dict(type="bool", default=False), "builder_cache": {"type": "bool", "default": False},
builder_cache_all=dict(type="bool", default=False), "builder_cache_all": {"type": "bool", "default": False},
builder_cache_filters=dict(type="dict"), "builder_cache_filters": {"type": "dict"},
builder_cache_keep_storage=dict(type="str"), # convert to bytes "builder_cache_keep_storage": {"type": "str"}, # convert to bytes
) }
client = AnsibleDockerClient( client = AnsibleDockerClient(
argument_spec=argument_spec, argument_spec=argument_spec,
option_minimal_versions=dict( option_minimal_versions={
builder_cache=dict(docker_py_version="1.31"), "builder_cache": {"docker_py_version": "1.31"},
builder_cache_all=dict(docker_py_version="1.39"), "builder_cache_all": {"docker_py_version": "1.39"},
builder_cache_filters=dict(docker_py_version="1.31"), "builder_cache_filters": {"docker_py_version": "1.31"},
builder_cache_keep_storage=dict(docker_py_version="1.39"), "builder_cache_keep_storage": {"docker_py_version": "1.39"},
), },
# supports_check_mode=True, # supports_check_mode=True,
) )
@ -286,7 +286,7 @@ def main():
) )
try: try:
result = dict() result = {}
changed = False changed = False
if client.module.params["containers"]: if client.module.params["containers"]:

View File

@ -366,17 +366,21 @@ class SecretManager(DockerBaseClass):
def main(): def main():
argument_spec = dict( argument_spec = {
name=dict(type="str", required=True), "name": {"type": "str", "required": True},
state=dict(type="str", default="present", choices=["absent", "present"]), "state": {
data=dict(type="str", no_log=True), "type": "str",
data_is_b64=dict(type="bool", default=False), "default": "present",
data_src=dict(type="path"), "choices": ["absent", "present"],
labels=dict(type="dict"), },
force=dict(type="bool", default=False), "data": {"type": "str", "no_log": True},
rolling_versions=dict(type="bool", default=False), "data_is_b64": {"type": "bool", "default": False},
versions_to_keep=dict(type="int", default=5), "data_src": {"type": "path"},
) "labels": {"type": "dict"},
"force": {"type": "bool", "default": False},
"rolling_versions": {"type": "bool", "default": False},
"versions_to_keep": {"type": "int", "default": 5},
}
required_if = [ required_if = [
("state", "present", ["data", "data_src"], True), ("state", "present", ["data", "data_src"], True),
@ -396,7 +400,7 @@ def main():
sanitize_labels(client.module.params["labels"], "labels", client) sanitize_labels(client.module.params["labels"], "labels", client)
try: try:
results = dict(changed=False, secret_id="", secret_name="") results = {"changed": False, "secret_id": "", "secret_name": ""}
SecretManager(client, results)() SecretManager(client, results)()
client.module.exit_json(**results) client.module.exit_json(**results)

View File

@ -184,7 +184,7 @@ except ImportError:
def docker_stack_services(client, stack_name): def docker_stack_services(client, stack_name):
rc, out, err = client.call_cli( dummy_rc, out, err = client.call_cli(
"stack", "services", stack_name, "--format", "{{.Name}}" "stack", "services", stack_name, "--format", "{{.Name}}"
) )
if to_native(err) == f"Nothing found in stack: {stack_name}\n": if to_native(err) == f"Nothing found in stack: {stack_name}\n":
@ -193,7 +193,7 @@ def docker_stack_services(client, stack_name):
def docker_service_inspect(client, service_name): def docker_service_inspect(client, service_name):
rc, out, err = client.call_cli("service", "inspect", service_name) rc, out, dummy_err = client.call_cli("service", "inspect", service_name)
if rc != 0: if rc != 0:
return None return None
ret = json.loads(out)[0]["Spec"] ret = json.loads(out)[0]["Spec"]
@ -240,15 +240,19 @@ def docker_stack_rm(client, stack_name, retries, interval):
def main(): def main():
client = AnsibleModuleDockerClient( client = AnsibleModuleDockerClient(
argument_spec={ argument_spec={
"name": dict(type="str", required=True), "name": {"type": "str", "required": True},
"compose": dict(type="list", elements="raw", default=[]), "compose": {"type": "list", "elements": "raw", "default": []},
"prune": dict(type="bool", default=False), "prune": {"type": "bool", "default": False},
"detach": dict(type="bool", default=True), "detach": {"type": "bool", "default": True},
"with_registry_auth": dict(type="bool", default=False), "with_registry_auth": {"type": "bool", "default": False},
"resolve_image": dict(type="str", choices=["always", "changed", "never"]), "resolve_image": {"type": "str", "choices": ["always", "changed", "never"]},
"state": dict(type="str", default="present", choices=["present", "absent"]), "state": {
"absent_retries": dict(type="int", default=0), "type": "str",
"absent_retries_interval": dict(type="int", default=1), "default": "present",
"choices": ["present", "absent"],
},
"absent_retries": {"type": "int", "default": 0},
"absent_retries_interval": {"type": "int", "default": 1},
}, },
supports_check_mode=False, supports_check_mode=False,
) )
@ -273,7 +277,7 @@ def main():
) )
compose_files = [] compose_files = []
for i, compose_def in enumerate(compose): for compose_def in compose:
if isinstance(compose_def, dict): if isinstance(compose_def, dict):
compose_file_fd, compose_file = tempfile.mkstemp() compose_file_fd, compose_file = tempfile.mkstemp()
client.module.add_cleanup_file(compose_file) client.module.add_cleanup_file(compose_file)

View File

@ -104,7 +104,7 @@ def docker_stack_task(module, stack_name):
def main(): def main():
client = AnsibleModuleDockerClient( client = AnsibleModuleDockerClient(
argument_spec={"name": dict(type="str", required=True)}, argument_spec={"name": {"type": "str", "required": True}},
supports_check_mode=True, supports_check_mode=True,
) )

View File

@ -359,17 +359,17 @@ class TaskParameters(DockerBaseClass):
def update_from_swarm_info(self, swarm_info): def update_from_swarm_info(self, swarm_info):
spec = swarm_info["Spec"] spec = swarm_info["Spec"]
ca_config = spec.get("CAConfig") or dict() ca_config = spec.get("CAConfig") or {}
if self.node_cert_expiry is None: if self.node_cert_expiry is None:
self.node_cert_expiry = ca_config.get("NodeCertExpiry") self.node_cert_expiry = ca_config.get("NodeCertExpiry")
if self.ca_force_rotate is None: if self.ca_force_rotate is None:
self.ca_force_rotate = ca_config.get("ForceRotate") self.ca_force_rotate = ca_config.get("ForceRotate")
dispatcher = spec.get("Dispatcher") or dict() dispatcher = spec.get("Dispatcher") or {}
if self.dispatcher_heartbeat_period is None: if self.dispatcher_heartbeat_period is None:
self.dispatcher_heartbeat_period = dispatcher.get("HeartbeatPeriod") self.dispatcher_heartbeat_period = dispatcher.get("HeartbeatPeriod")
raft = spec.get("Raft") or dict() raft = spec.get("Raft") or {}
if self.snapshot_interval is None: if self.snapshot_interval is None:
self.snapshot_interval = raft.get("SnapshotInterval") self.snapshot_interval = raft.get("SnapshotInterval")
if self.keep_old_snapshots is None: if self.keep_old_snapshots is None:
@ -381,13 +381,13 @@ class TaskParameters(DockerBaseClass):
if self.election_tick is None: if self.election_tick is None:
self.election_tick = raft.get("ElectionTick") self.election_tick = raft.get("ElectionTick")
orchestration = spec.get("Orchestration") or dict() orchestration = spec.get("Orchestration") or {}
if self.task_history_retention_limit is None: if self.task_history_retention_limit is None:
self.task_history_retention_limit = orchestration.get( self.task_history_retention_limit = orchestration.get(
"TaskHistoryRetentionLimit" "TaskHistoryRetentionLimit"
) )
encryption_config = spec.get("EncryptionConfig") or dict() encryption_config = spec.get("EncryptionConfig") or {}
if self.autolock_managers is None: if self.autolock_managers is None:
self.autolock_managers = encryption_config.get("AutoLockManagers") self.autolock_managers = encryption_config.get("AutoLockManagers")
@ -401,24 +401,24 @@ class TaskParameters(DockerBaseClass):
self.log_driver = spec["TaskDefaults"]["LogDriver"] self.log_driver = spec["TaskDefaults"]["LogDriver"]
def update_parameters(self, client): def update_parameters(self, client):
assign = dict( assign = {
snapshot_interval="snapshot_interval", "snapshot_interval": "snapshot_interval",
task_history_retention_limit="task_history_retention_limit", "task_history_retention_limit": "task_history_retention_limit",
keep_old_snapshots="keep_old_snapshots", "keep_old_snapshots": "keep_old_snapshots",
log_entries_for_slow_followers="log_entries_for_slow_followers", "log_entries_for_slow_followers": "log_entries_for_slow_followers",
heartbeat_tick="heartbeat_tick", "heartbeat_tick": "heartbeat_tick",
election_tick="election_tick", "election_tick": "election_tick",
dispatcher_heartbeat_period="dispatcher_heartbeat_period", "dispatcher_heartbeat_period": "dispatcher_heartbeat_period",
node_cert_expiry="node_cert_expiry", "node_cert_expiry": "node_cert_expiry",
name="name", "name": "name",
labels="labels", "labels": "labels",
signing_ca_cert="signing_ca_cert", "signing_ca_cert": "signing_ca_cert",
signing_ca_key="signing_ca_key", "signing_ca_key": "signing_ca_key",
ca_force_rotate="ca_force_rotate", "ca_force_rotate": "ca_force_rotate",
autolock_managers="autolock_managers", "autolock_managers": "autolock_managers",
log_driver="log_driver", "log_driver": "log_driver",
) }
params = dict() params = {}
for dest, source in assign.items(): for dest, source in assign.items():
if not client.option_minimal_versions[source]["supported"]: if not client.option_minimal_versions[source]["supported"]:
continue continue
@ -489,7 +489,7 @@ class SwarmManager(DockerBaseClass):
choice_map.get(self.state)() choice_map.get(self.state)()
if self.client.module._diff or self.parameters.debug: if self.client.module._diff or self.parameters.debug:
diff = dict() diff = {}
diff["before"], diff["after"] = self.differences.get_before_after() diff["before"], diff["after"] = self.differences.get_before_after()
self.results["diff"] = diff self.results["diff"] = diff
@ -660,62 +660,65 @@ def _detect_remove_operation(client):
def main(): def main():
argument_spec = dict( argument_spec = {
advertise_addr=dict(type="str"), "advertise_addr": {"type": "str"},
data_path_addr=dict(type="str"), "data_path_addr": {"type": "str"},
data_path_port=dict(type="int"), "data_path_port": {"type": "int"},
state=dict( "state": {
type="str", "type": "str",
default="present", "default": "present",
choices=["present", "join", "absent", "remove"], "choices": ["present", "join", "absent", "remove"],
), },
force=dict(type="bool", default=False), "force": {"type": "bool", "default": False},
listen_addr=dict(type="str", default="0.0.0.0:2377"), "listen_addr": {"type": "str", "default": "0.0.0.0:2377"},
remote_addrs=dict(type="list", elements="str"), "remote_addrs": {"type": "list", "elements": "str"},
join_token=dict(type="str", no_log=True), "join_token": {"type": "str", "no_log": True},
snapshot_interval=dict(type="int"), "snapshot_interval": {"type": "int"},
task_history_retention_limit=dict(type="int"), "task_history_retention_limit": {"type": "int"},
keep_old_snapshots=dict(type="int"), "keep_old_snapshots": {"type": "int"},
log_entries_for_slow_followers=dict(type="int"), "log_entries_for_slow_followers": {"type": "int"},
heartbeat_tick=dict(type="int"), "heartbeat_tick": {"type": "int"},
election_tick=dict(type="int"), "election_tick": {"type": "int"},
dispatcher_heartbeat_period=dict(type="int"), "dispatcher_heartbeat_period": {"type": "int"},
node_cert_expiry=dict(type="int"), "node_cert_expiry": {"type": "int"},
name=dict(type="str"), "name": {"type": "str"},
labels=dict(type="dict"), "labels": {"type": "dict"},
signing_ca_cert=dict(type="str"), "signing_ca_cert": {"type": "str"},
signing_ca_key=dict(type="str", no_log=True), "signing_ca_key": {"type": "str", "no_log": True},
ca_force_rotate=dict(type="int"), "ca_force_rotate": {"type": "int"},
autolock_managers=dict(type="bool"), "autolock_managers": {"type": "bool"},
node_id=dict(type="str"), "node_id": {"type": "str"},
rotate_worker_token=dict(type="bool", default=False), "rotate_worker_token": {"type": "bool", "default": False},
rotate_manager_token=dict(type="bool", default=False), "rotate_manager_token": {"type": "bool", "default": False},
default_addr_pool=dict(type="list", elements="str"), "default_addr_pool": {"type": "list", "elements": "str"},
subnet_size=dict(type="int"), "subnet_size": {"type": "int"},
) }
required_if = [ required_if = [
("state", "join", ["remote_addrs", "join_token"]), ("state", "join", ["remote_addrs", "join_token"]),
("state", "remove", ["node_id"]), ("state", "remove", ["node_id"]),
] ]
option_minimal_versions = dict( option_minimal_versions = {
labels=dict(docker_py_version="2.6.0", docker_api_version="1.32"), "labels": {"docker_py_version": "2.6.0", "docker_api_version": "1.32"},
signing_ca_cert=dict(docker_py_version="2.6.0", docker_api_version="1.30"), "signing_ca_cert": {"docker_py_version": "2.6.0", "docker_api_version": "1.30"},
signing_ca_key=dict(docker_py_version="2.6.0", docker_api_version="1.30"), "signing_ca_key": {"docker_py_version": "2.6.0", "docker_api_version": "1.30"},
ca_force_rotate=dict(docker_py_version="2.6.0", docker_api_version="1.30"), "ca_force_rotate": {"docker_py_version": "2.6.0", "docker_api_version": "1.30"},
autolock_managers=dict(docker_py_version="2.6.0"), "autolock_managers": {"docker_py_version": "2.6.0"},
log_driver=dict(docker_py_version="2.6.0"), "log_driver": {"docker_py_version": "2.6.0"},
remove_operation=dict( "remove_operation": {
docker_py_version="2.4.0", "docker_py_version": "2.4.0",
detect_usage=_detect_remove_operation, "detect_usage": _detect_remove_operation,
usage_msg="remove swarm nodes", "usage_msg": "remove swarm nodes",
), },
default_addr_pool=dict(docker_py_version="4.0.0", docker_api_version="1.39"), "default_addr_pool": {
subnet_size=dict(docker_py_version="4.0.0", docker_api_version="1.39"), "docker_py_version": "4.0.0",
data_path_addr=dict(docker_py_version="4.0.0", docker_api_version="1.30"), "docker_api_version": "1.39",
data_path_port=dict(docker_py_version="6.0.0", docker_api_version="1.40"), },
) "subnet_size": {"docker_py_version": "4.0.0", "docker_api_version": "1.39"},
"data_path_addr": {"docker_py_version": "4.0.0", "docker_api_version": "1.30"},
"data_path_port": {"docker_py_version": "6.0.0", "docker_api_version": "1.40"},
}
client = AnsibleDockerSwarmClient( client = AnsibleDockerSwarmClient(
argument_spec=argument_spec, argument_spec=argument_spec,
@ -727,7 +730,7 @@ def main():
sanitize_labels(client.module.params["labels"], "labels", client) sanitize_labels(client.module.params["labels"], "labels", client)
try: try:
results = dict(changed=False, result="", actions=[]) results = {"changed": False, "result": "", "actions": []}
SwarmManager(client, results)() SwarmManager(client, results)()
client.module.exit_json(**results) client.module.exit_json(**results)

View File

@ -261,7 +261,7 @@ class DockerSwarmManager(DockerBaseClass):
return items return items
for item in items: for item in items:
item_record = dict() item_record = {}
if docker_object == "nodes": if docker_object == "nodes":
item_record = self.get_essential_facts_nodes(item) item_record = self.get_essential_facts_nodes(item)
@ -277,7 +277,7 @@ class DockerSwarmManager(DockerBaseClass):
@staticmethod @staticmethod
def get_essential_facts_nodes(item): def get_essential_facts_nodes(item):
object_essentials = dict() object_essentials = {}
object_essentials["ID"] = item.get("ID") object_essentials["ID"] = item.get("ID")
object_essentials["Hostname"] = item["Description"]["Hostname"] object_essentials["Hostname"] = item["Description"]["Hostname"]
@ -299,7 +299,7 @@ class DockerSwarmManager(DockerBaseClass):
return object_essentials return object_essentials
def get_essential_facts_tasks(self, item): def get_essential_facts_tasks(self, item):
object_essentials = dict() object_essentials = {}
object_essentials["ID"] = item["ID"] object_essentials["ID"] = item["ID"]
# Returning container ID to not trigger another connection to host # Returning container ID to not trigger another connection to host
@ -320,7 +320,7 @@ class DockerSwarmManager(DockerBaseClass):
@staticmethod @staticmethod
def get_essential_facts_services(item): def get_essential_facts_services(item):
object_essentials = dict() object_essentials = {}
object_essentials["ID"] = item["ID"] object_essentials["ID"] = item["ID"]
object_essentials["Name"] = item["Spec"]["Name"] object_essentials["Name"] = item["Spec"]["Name"]
@ -349,39 +349,39 @@ class DockerSwarmManager(DockerBaseClass):
def main(): def main():
argument_spec = dict( argument_spec = {
nodes=dict(type="bool", default=False), "nodes": {"type": "bool", "default": False},
nodes_filters=dict(type="dict"), "nodes_filters": {"type": "dict"},
tasks=dict(type="bool", default=False), "tasks": {"type": "bool", "default": False},
tasks_filters=dict(type="dict"), "tasks_filters": {"type": "dict"},
services=dict(type="bool", default=False), "services": {"type": "bool", "default": False},
services_filters=dict(type="dict"), "services_filters": {"type": "dict"},
unlock_key=dict(type="bool", default=False), "unlock_key": {"type": "bool", "default": False},
verbose_output=dict(type="bool", default=False), "verbose_output": {"type": "bool", "default": False},
) }
option_minimal_versions = dict( option_minimal_versions = {
unlock_key=dict(docker_py_version="2.7.0"), "unlock_key": {"docker_py_version": "2.7.0"},
) }
client = AnsibleDockerSwarmClient( client = AnsibleDockerSwarmClient(
argument_spec=argument_spec, argument_spec=argument_spec,
supports_check_mode=True, supports_check_mode=True,
min_docker_version="1.10.0", min_docker_version="1.10.0",
option_minimal_versions=option_minimal_versions, option_minimal_versions=option_minimal_versions,
fail_results=dict( fail_results={
can_talk_to_docker=False, "can_talk_to_docker": False,
docker_swarm_active=False, "docker_swarm_active": False,
docker_swarm_manager=False, "docker_swarm_manager": False,
), },
) )
client.fail_results["can_talk_to_docker"] = True client.fail_results["can_talk_to_docker"] = True
client.fail_results["docker_swarm_active"] = client.check_if_swarm_node() client.fail_results["docker_swarm_active"] = client.check_if_swarm_node()
client.fail_results["docker_swarm_manager"] = client.check_if_swarm_manager() client.fail_results["docker_swarm_manager"] = client.check_if_swarm_manager()
try: try:
results = dict( results = {
changed=False, "changed": False,
) }
DockerSwarmManager(client, results) DockerSwarmManager(client, results)
results.update(client.fail_results) results.update(client.fail_results)

View File

@ -919,10 +919,10 @@ def get_docker_environment(env, env_files):
for item in env: for item in env:
try: try:
name, value = item.split("=", 1) name, value = item.split("=", 1)
except ValueError: except ValueError as exc:
raise ValueError( raise ValueError(
"Invalid environment variable found in list, needs to be in format KEY=VALUE." "Invalid environment variable found in list, needs to be in format KEY=VALUE."
) ) from exc
env_dict[name] = value env_dict[name] = value
elif env is not None: elif env is not None:
raise ValueError( raise ValueError(
@ -983,7 +983,7 @@ def get_docker_networks(networks, network_ids):
try: try:
parsed_network["id"] = network_ids[network_name] parsed_network["id"] = network_ids[network_name]
except KeyError as e: except KeyError as e:
raise ValueError(f"Could not find a network named: {e}.") raise ValueError(f"Could not find a network named: {e}.") from None
parsed_networks.append(parsed_network) parsed_networks.append(parsed_network)
return parsed_networks or [] return parsed_networks or []
@ -1019,9 +1019,9 @@ def has_dict_changed(new_dict, old_dict):
return True return True
if not old_dict and new_dict: if not old_dict and new_dict:
return True return True
defined_options = dict( defined_options = {
(option, value) for option, value in new_dict.items() if value is not None option: value for option, value in new_dict.items() if value is not None
) }
for option, value in defined_options.items(): for option, value in defined_options.items():
old_value = old_dict.get(option) old_value = old_dict.get(option)
if not value and not old_value: if not value and not old_value:
@ -1370,7 +1370,9 @@ class DockerService(DockerBaseClass):
try: try:
memory = human_to_bytes(memory) memory = human_to_bytes(memory)
except ValueError as exc: except ValueError as exc:
raise ValueError(f"Failed to convert limit_memory to bytes: {exc}") raise ValueError(
f"Failed to convert limit_memory to bytes: {exc}"
) from exc
return { return {
"limit_cpu": cpus, "limit_cpu": cpus,
"limit_memory": memory, "limit_memory": memory,
@ -1392,7 +1394,9 @@ class DockerService(DockerBaseClass):
try: try:
memory = human_to_bytes(memory) memory = human_to_bytes(memory)
except ValueError as exc: except ValueError as exc:
raise ValueError(f"Failed to convert reserve_memory to bytes: {exc}") raise ValueError(
f"Failed to convert reserve_memory to bytes: {exc}"
) from exc
return { return {
"reserve_cpu": cpus, "reserve_cpu": cpus,
"reserve_memory": memory, "reserve_memory": memory,
@ -1559,7 +1563,7 @@ class DockerService(DockerBaseClass):
except ValueError as exc: except ValueError as exc:
raise ValueError( raise ValueError(
f"Failed to convert tmpfs_size to bytes: {exc}" f"Failed to convert tmpfs_size to bytes: {exc}"
) ) from exc
service_m["tmpfs_size"] = tmpfs_size service_m["tmpfs_size"] = tmpfs_size
s.mounts.append(service_m) s.mounts.append(service_m)
@ -1855,12 +1859,12 @@ class DockerService(DockerBaseClass):
if not publish_item.get("mode"): if not publish_item.get("mode"):
ignored_keys.add("mode") ignored_keys.add("mode")
# Create copies of publish_item dicts where keys specified in ignored_keys are left out # Create copies of publish_item dicts where keys specified in ignored_keys are left out
filtered_old_publish_item = dict( filtered_old_publish_item = {
(k, v) for k, v in old_publish_item.items() if k not in ignored_keys k: v for k, v in old_publish_item.items() if k not in ignored_keys
) }
filtered_publish_item = dict( filtered_publish_item = {
(k, v) for k, v in publish_item.items() if k not in ignored_keys k: v for k, v in publish_item.items() if k not in ignored_keys
) }
if filtered_publish_item != filtered_old_publish_item: if filtered_publish_item != filtered_old_publish_item:
return True return True
return False return False
@ -2213,11 +2217,11 @@ class DockerServiceManager:
"StartPeriod": "start_period", "StartPeriod": "start_period",
"Retries": "retries", "Retries": "retries",
} }
healthcheck = dict( healthcheck = {
(options[key], value) options[key]: value
for key, value in healthcheck_data.items() for key, value in healthcheck_data.items()
if value is not None and key in options if value is not None and key in options
) }
ds.healthcheck = healthcheck ds.healthcheck = healthcheck
update_config_data = raw_data["Spec"].get("UpdateConfig") update_config_data = raw_data["Spec"].get("UpdateConfig")
@ -2258,7 +2262,7 @@ class DockerServiceManager:
) )
for host in hosts for host in hosts
] ]
ds.hosts = dict((hostname, ip) for ip, hostname in hosts) ds.hosts = {hostname: ip for ip, hostname in hosts}
ds.tty = task_template_data["ContainerSpec"].get("TTY") ds.tty = task_template_data["ContainerSpec"].get("TTY")
placement = task_template_data.get("Placement") placement = task_template_data.get("Placement")
@ -2268,10 +2272,10 @@ class DockerServiceManager:
placement_preferences = [] placement_preferences = []
for preference in placement.get("Preferences", []): for preference in placement.get("Preferences", []):
placement_preferences.append( placement_preferences.append(
dict( {
(key.lower(), value["SpreadDescriptor"]) key.lower(): value["SpreadDescriptor"]
for key, value in preference.items() for key, value in preference.items()
) }
) )
ds.placement_preferences = placement_preferences or None ds.placement_preferences = placement_preferences or None
@ -2345,10 +2349,9 @@ class DockerServiceManager:
volume_options = mount_data.get("VolumeOptions", {}) volume_options = mount_data.get("VolumeOptions", {})
tmpfs_options = mount_data.get("TmpfsOptions", {}) tmpfs_options = mount_data.get("TmpfsOptions", {})
driver_config = volume_options.get("DriverConfig", {}) driver_config = volume_options.get("DriverConfig", {})
driver_config = ( driver_config = {
dict((key.lower(), value) for key, value in driver_config.items()) key.lower(): value for key, value in driver_config.items()
or None } or None
)
ds.mounts.append( ds.mounts.append(
{ {
"source": mount_data.get("Source", ""), "source": mount_data.get("Source", ""),
@ -2444,9 +2447,7 @@ class DockerServiceManager:
return f"{name}@{digest}" return f"{name}@{digest}"
def get_networks_names_ids(self): def get_networks_names_ids(self):
return dict( return {network["Name"]: network["Id"] for network in self.client.networks()}
(network["Name"], network["Id"]) for network in self.client.networks()
)
def get_missing_secret_ids(self): def get_missing_secret_ids(self):
""" """
@ -2460,11 +2461,11 @@ class DockerServiceManager:
if not secret_names: if not secret_names:
return {} return {}
secrets = self.client.secrets(filters={"name": secret_names}) secrets = self.client.secrets(filters={"name": secret_names})
secrets = dict( secrets = {
(secret["Spec"]["Name"], secret["ID"]) secret["Spec"]["Name"]: secret["ID"]
for secret in secrets for secret in secrets
if secret["Spec"]["Name"] in secret_names if secret["Spec"]["Name"] in secret_names
) }
for secret_name in secret_names: for secret_name in secret_names:
if secret_name not in secrets: if secret_name not in secrets:
self.client.fail(f'Could not find a secret named "{secret_name}"') self.client.fail(f'Could not find a secret named "{secret_name}"')
@ -2482,11 +2483,11 @@ class DockerServiceManager:
if not config_names: if not config_names:
return {} return {}
configs = self.client.configs(filters={"name": config_names}) configs = self.client.configs(filters={"name": config_names})
configs = dict( configs = {
(config["Spec"]["Name"], config["ID"]) config["Spec"]["Name"]: config["ID"]
for config in configs for config in configs
if config["Spec"]["Name"] in config_names if config["Spec"]["Name"] in config_names
) }
for config_name in config_names: for config_name in config_names:
if config_name not in configs: if config_name not in configs:
self.client.fail(f'Could not find a config named "{config_name}"') self.client.fail(f'Could not find a config named "{config_name}"')
@ -2627,26 +2628,30 @@ def _detect_update_config_failure_action_rollback(client):
def main(): def main():
argument_spec = dict( argument_spec = {
name=dict(type="str", required=True), "name": {"type": "str", "required": True},
image=dict(type="str"), "image": {"type": "str"},
state=dict(type="str", default="present", choices=["present", "absent"]), "state": {
mounts=dict( "type": "str",
type="list", "default": "present",
elements="dict", "choices": ["present", "absent"],
options=dict( },
source=dict(type="str"), "mounts": {
target=dict(type="str", required=True), "type": "list",
type=dict( "elements": "dict",
type="str", "options": {
default="bind", "source": {"type": "str"},
choices=["bind", "volume", "tmpfs", "npipe"], "target": {"type": "str", "required": True},
), "type": {
readonly=dict(type="bool"), "type": "str",
labels=dict(type="dict"), "default": "bind",
propagation=dict( "choices": ["bind", "volume", "tmpfs", "npipe"],
type="str", },
choices=[ "readonly": {"type": "bool"},
"labels": {"type": "dict"},
"propagation": {
"type": "str",
"choices": [
"shared", "shared",
"slave", "slave",
"private", "private",
@ -2654,266 +2659,273 @@ def main():
"rslave", "rslave",
"rprivate", "rprivate",
], ],
), },
no_copy=dict(type="bool"), "no_copy": {"type": "bool"},
driver_config=dict( "driver_config": {
type="dict", "type": "dict",
options=dict(name=dict(type="str"), options=dict(type="dict")), "options": {"name": {"type": "str"}, "options": {"type": "dict"}},
), },
tmpfs_size=dict(type="str"), "tmpfs_size": {"type": "str"},
tmpfs_mode=dict(type="int"), "tmpfs_mode": {"type": "int"},
), },
), },
configs=dict( "configs": {
type="list", "type": "list",
elements="dict", "elements": "dict",
options=dict( "options": {
config_id=dict(type="str"), "config_id": {"type": "str"},
config_name=dict(type="str", required=True), "config_name": {"type": "str", "required": True},
filename=dict(type="str"), "filename": {"type": "str"},
uid=dict(type="str"), "uid": {"type": "str"},
gid=dict(type="str"), "gid": {"type": "str"},
mode=dict(type="int"), "mode": {"type": "int"},
), },
), },
secrets=dict( "secrets": {
type="list", "type": "list",
elements="dict", "elements": "dict",
no_log=False, "no_log": False,
options=dict( "options": {
secret_id=dict(type="str", no_log=False), "secret_id": {"type": "str", "no_log": False},
secret_name=dict(type="str", required=True, no_log=False), "secret_name": {"type": "str", "required": True, "no_log": False},
filename=dict(type="str"), "filename": {"type": "str"},
uid=dict(type="str"), "uid": {"type": "str"},
gid=dict(type="str"), "gid": {"type": "str"},
mode=dict(type="int"), "mode": {"type": "int"},
), },
), },
networks=dict(type="list", elements="raw"), "networks": {"type": "list", "elements": "raw"},
command=dict(type="raw"), "command": {"type": "raw"},
args=dict(type="list", elements="str"), "args": {"type": "list", "elements": "str"},
env=dict(type="raw"), "env": {"type": "raw"},
env_files=dict(type="list", elements="path"), "env_files": {"type": "list", "elements": "path"},
force_update=dict(type="bool", default=False), "force_update": {"type": "bool", "default": False},
groups=dict(type="list", elements="str"), "groups": {"type": "list", "elements": "str"},
logging=dict( "logging": {
type="dict", "type": "dict",
options=dict( "options": {
driver=dict(type="str"), "driver": {"type": "str"},
options=dict(type="dict"), "options": {"type": "dict"},
), },
), },
publish=dict( "publish": {
type="list", "type": "list",
elements="dict", "elements": "dict",
options=dict( "options": {
published_port=dict(type="int", required=False), "published_port": {"type": "int", "required": False},
target_port=dict(type="int", required=True), "target_port": {"type": "int", "required": True},
protocol=dict(type="str", default="tcp", choices=["tcp", "udp"]), "protocol": {
mode=dict(type="str", choices=["ingress", "host"]), "type": "str",
), "default": "tcp",
), "choices": ["tcp", "udp"],
placement=dict( },
type="dict", "mode": {"type": "str", "choices": ["ingress", "host"]},
options=dict( },
constraints=dict(type="list", elements="str"), },
preferences=dict(type="list", elements="dict"), "placement": {
replicas_max_per_node=dict(type="int"), "type": "dict",
), "options": {
), "constraints": {"type": "list", "elements": "str"},
tty=dict(type="bool"), "preferences": {"type": "list", "elements": "dict"},
dns=dict(type="list", elements="str"), "replicas_max_per_node": {"type": "int"},
dns_search=dict(type="list", elements="str"), },
dns_options=dict(type="list", elements="str"), },
healthcheck=dict( "tty": {"type": "bool"},
type="dict", "dns": {"type": "list", "elements": "str"},
options=dict( "dns_search": {"type": "list", "elements": "str"},
test=dict(type="raw"), "dns_options": {"type": "list", "elements": "str"},
interval=dict(type="str"), "healthcheck": {
timeout=dict(type="str"), "type": "dict",
start_period=dict(type="str"), "options": {
retries=dict(type="int"), "test": {"type": "raw"},
), "interval": {"type": "str"},
), "timeout": {"type": "str"},
hostname=dict(type="str"), "start_period": {"type": "str"},
hosts=dict(type="dict"), "retries": {"type": "int"},
labels=dict(type="dict"), },
container_labels=dict(type="dict"), },
sysctls=dict(type="dict"), "hostname": {"type": "str"},
mode=dict( "hosts": {"type": "dict"},
type="str", "labels": {"type": "dict"},
default="replicated", "container_labels": {"type": "dict"},
choices=["replicated", "global", "replicated-job"], "sysctls": {"type": "dict"},
), "mode": {
replicas=dict(type="int", default=-1), "type": "str",
endpoint_mode=dict(type="str", choices=["vip", "dnsrr"]), "default": "replicated",
stop_grace_period=dict(type="str"), "choices": ["replicated", "global", "replicated-job"],
stop_signal=dict(type="str"), },
limits=dict( "replicas": {"type": "int", "default": -1},
type="dict", "endpoint_mode": {"type": "str", "choices": ["vip", "dnsrr"]},
options=dict( "stop_grace_period": {"type": "str"},
cpus=dict(type="float"), "stop_signal": {"type": "str"},
memory=dict(type="str"), "limits": {
), "type": "dict",
), "options": {
read_only=dict(type="bool"), "cpus": {"type": "float"},
reservations=dict( "memory": {"type": "str"},
type="dict", },
options=dict( },
cpus=dict(type="float"), "read_only": {"type": "bool"},
memory=dict(type="str"), "reservations": {
), "type": "dict",
), "options": {
resolve_image=dict(type="bool", default=False), "cpus": {"type": "float"},
restart_config=dict( "memory": {"type": "str"},
type="dict", },
options=dict( },
condition=dict(type="str", choices=["none", "on-failure", "any"]), "resolve_image": {"type": "bool", "default": False},
delay=dict(type="str"), "restart_config": {
max_attempts=dict(type="int"), "type": "dict",
window=dict(type="str"), "options": {
), "condition": {"type": "str", "choices": ["none", "on-failure", "any"]},
), "delay": {"type": "str"},
rollback_config=dict( "max_attempts": {"type": "int"},
type="dict", "window": {"type": "str"},
options=dict( },
parallelism=dict(type="int"), },
delay=dict(type="str"), "rollback_config": {
failure_action=dict(type="str", choices=["continue", "pause"]), "type": "dict",
monitor=dict(type="str"), "options": {
max_failure_ratio=dict(type="float"), "parallelism": {"type": "int"},
order=dict(type="str"), "delay": {"type": "str"},
), "failure_action": {"type": "str", "choices": ["continue", "pause"]},
), "monitor": {"type": "str"},
update_config=dict( "max_failure_ratio": {"type": "float"},
type="dict", "order": {"type": "str"},
options=dict( },
parallelism=dict(type="int"), },
delay=dict(type="str"), "update_config": {
failure_action=dict( "type": "dict",
type="str", choices=["continue", "pause", "rollback"] "options": {
), "parallelism": {"type": "int"},
monitor=dict(type="str"), "delay": {"type": "str"},
max_failure_ratio=dict(type="float"), "failure_action": {
order=dict(type="str"), "type": "str",
), "choices": ["continue", "pause", "rollback"],
), },
user=dict(type="str"), "monitor": {"type": "str"},
working_dir=dict(type="str"), "max_failure_ratio": {"type": "float"},
init=dict(type="bool"), "order": {"type": "str"},
cap_add=dict(type="list", elements="str"), },
cap_drop=dict(type="list", elements="str"), },
) "user": {"type": "str"},
"working_dir": {"type": "str"},
"init": {"type": "bool"},
"cap_add": {"type": "list", "elements": "str"},
"cap_drop": {"type": "list", "elements": "str"},
}
option_minimal_versions = dict( option_minimal_versions = {
dns=dict(docker_py_version="2.6.0"), "dns": {"docker_py_version": "2.6.0"},
dns_options=dict(docker_py_version="2.6.0"), "dns_options": {"docker_py_version": "2.6.0"},
dns_search=dict(docker_py_version="2.6.0"), "dns_search": {"docker_py_version": "2.6.0"},
endpoint_mode=dict(docker_py_version="3.0.0"), "endpoint_mode": {"docker_py_version": "3.0.0"},
force_update=dict(docker_py_version="2.1.0"), "force_update": {"docker_py_version": "2.1.0"},
healthcheck=dict(docker_py_version="2.6.0"), "healthcheck": {"docker_py_version": "2.6.0"},
hostname=dict(docker_py_version="2.2.0"), "hostname": {"docker_py_version": "2.2.0"},
hosts=dict(docker_py_version="2.6.0"), "hosts": {"docker_py_version": "2.6.0"},
groups=dict(docker_py_version="2.6.0"), "groups": {"docker_py_version": "2.6.0"},
tty=dict(docker_py_version="2.4.0"), "tty": {"docker_py_version": "2.4.0"},
secrets=dict(docker_py_version="2.4.0"), "secrets": {"docker_py_version": "2.4.0"},
configs=dict(docker_py_version="2.6.0", docker_api_version="1.30"), "configs": {"docker_py_version": "2.6.0", "docker_api_version": "1.30"},
stop_signal=dict(docker_py_version="2.6.0", docker_api_version="1.28"), "stop_signal": {"docker_py_version": "2.6.0", "docker_api_version": "1.28"},
publish=dict(docker_py_version="3.0.0"), "publish": {"docker_py_version": "3.0.0"},
read_only=dict(docker_py_version="2.6.0", docker_api_version="1.28"), "read_only": {"docker_py_version": "2.6.0", "docker_api_version": "1.28"},
resolve_image=dict(docker_api_version="1.30", docker_py_version="3.2.0"), "resolve_image": {"docker_api_version": "1.30", "docker_py_version": "3.2.0"},
rollback_config=dict(docker_py_version="3.5.0", docker_api_version="1.28"), "rollback_config": {"docker_py_version": "3.5.0", "docker_api_version": "1.28"},
init=dict(docker_py_version="4.0.0", docker_api_version="1.37"), "init": {"docker_py_version": "4.0.0", "docker_api_version": "1.37"},
cap_add=dict(docker_py_version="5.0.3", docker_api_version="1.41"), "cap_add": {"docker_py_version": "5.0.3", "docker_api_version": "1.41"},
cap_drop=dict(docker_py_version="5.0.3", docker_api_version="1.41"), "cap_drop": {"docker_py_version": "5.0.3", "docker_api_version": "1.41"},
sysctls=dict(docker_py_version="6.0.0", docker_api_version="1.40"), "sysctls": {"docker_py_version": "6.0.0", "docker_api_version": "1.40"},
# specials # specials
publish_mode=dict( "publish_mode": {
docker_py_version="3.0.0", "docker_py_version": "3.0.0",
detect_usage=_detect_publish_mode_usage, "detect_usage": _detect_publish_mode_usage,
usage_msg="set publish.mode", "usage_msg": "set publish.mode",
), },
healthcheck_start_period=dict( "healthcheck_start_period": {
docker_py_version="2.6.0", "docker_py_version": "2.6.0",
docker_api_version="1.29", "docker_api_version": "1.29",
detect_usage=_detect_healthcheck_start_period, "detect_usage": _detect_healthcheck_start_period,
usage_msg="set healthcheck.start_period", "usage_msg": "set healthcheck.start_period",
), },
update_config_max_failure_ratio=dict( "update_config_max_failure_ratio": {
docker_py_version="2.1.0", "docker_py_version": "2.1.0",
detect_usage=lambda c: (c.module.params["update_config"] or {}).get( "detect_usage": lambda c: (c.module.params["update_config"] or {}).get(
"max_failure_ratio" "max_failure_ratio"
) )
is not None, is not None,
usage_msg="set update_config.max_failure_ratio", "usage_msg": "set update_config.max_failure_ratio",
), },
update_config_failure_action=dict( "update_config_failure_action": {
docker_py_version="3.5.0", "docker_py_version": "3.5.0",
docker_api_version="1.28", "docker_api_version": "1.28",
detect_usage=_detect_update_config_failure_action_rollback, "detect_usage": _detect_update_config_failure_action_rollback,
usage_msg="set update_config.failure_action.rollback", "usage_msg": "set update_config.failure_action.rollback",
), },
update_config_monitor=dict( "update_config_monitor": {
docker_py_version="2.1.0", "docker_py_version": "2.1.0",
detect_usage=lambda c: (c.module.params["update_config"] or {}).get( "detect_usage": lambda c: (c.module.params["update_config"] or {}).get(
"monitor" "monitor"
) )
is not None, is not None,
usage_msg="set update_config.monitor", "usage_msg": "set update_config.monitor",
), },
update_config_order=dict( "update_config_order": {
docker_py_version="2.7.0", "docker_py_version": "2.7.0",
docker_api_version="1.29", "docker_api_version": "1.29",
detect_usage=lambda c: (c.module.params["update_config"] or {}).get("order") "detect_usage": lambda c: (c.module.params["update_config"] or {}).get(
is not None,
usage_msg="set update_config.order",
),
placement_config_preferences=dict(
docker_py_version="2.4.0",
docker_api_version="1.27",
detect_usage=lambda c: (c.module.params["placement"] or {}).get(
"preferences"
)
is not None,
usage_msg="set placement.preferences",
),
placement_config_constraints=dict(
docker_py_version="2.4.0",
detect_usage=lambda c: (c.module.params["placement"] or {}).get(
"constraints"
)
is not None,
usage_msg="set placement.constraints",
),
placement_config_replicas_max_per_node=dict(
docker_py_version="4.4.3",
docker_api_version="1.40",
detect_usage=lambda c: (c.module.params["placement"] or {}).get(
"replicas_max_per_node"
)
is not None,
usage_msg="set placement.replicas_max_per_node",
),
mounts_tmpfs=dict(
docker_py_version="2.6.0",
detect_usage=_detect_mount_tmpfs_usage,
usage_msg="set mounts.tmpfs",
),
rollback_config_order=dict(
docker_api_version="1.29",
detect_usage=lambda c: (c.module.params["rollback_config"] or {}).get(
"order" "order"
) )
is not None, is not None,
usage_msg="set rollback_config.order", "usage_msg": "set update_config.order",
), },
mode_replicated_job=dict( "placement_config_preferences": {
docker_py_version="6.0.0", "docker_py_version": "2.4.0",
docker_api_version="1.41", "docker_api_version": "1.27",
detect_usage=lambda c: c.module.params.get("mode") == "replicated-job", "detect_usage": lambda c: (c.module.params["placement"] or {}).get(
usage_msg="set mode", "preferences"
), )
) is not None,
"usage_msg": "set placement.preferences",
},
"placement_config_constraints": {
"docker_py_version": "2.4.0",
"detect_usage": lambda c: (c.module.params["placement"] or {}).get(
"constraints"
)
is not None,
"usage_msg": "set placement.constraints",
},
"placement_config_replicas_max_per_node": {
"docker_py_version": "4.4.3",
"docker_api_version": "1.40",
"detect_usage": lambda c: (c.module.params["placement"] or {}).get(
"replicas_max_per_node"
)
is not None,
"usage_msg": "set placement.replicas_max_per_node",
},
"mounts_tmpfs": {
"docker_py_version": "2.6.0",
"detect_usage": _detect_mount_tmpfs_usage,
"usage_msg": "set mounts.tmpfs",
},
"rollback_config_order": {
"docker_api_version": "1.29",
"detect_usage": lambda c: (c.module.params["rollback_config"] or {}).get(
"order"
)
is not None,
"usage_msg": "set rollback_config.order",
},
"mode_replicated_job": {
"docker_py_version": "6.0.0",
"docker_api_version": "1.41",
"detect_usage": lambda c: c.module.params.get("mode") == "replicated-job",
"usage_msg": "set mode",
},
}
required_if = [("state", "present", ["image"])] required_if = [("state", "present", ["image"])]
client = AnsibleDockerClient( client = AnsibleDockerClient(
@ -2928,16 +2940,16 @@ def main():
dsm = DockerServiceManager(client) dsm = DockerServiceManager(client)
msg, changed, rebuilt, changes, facts = dsm.run_safe() msg, changed, rebuilt, changes, facts = dsm.run_safe()
results = dict( results = {
msg=msg, "msg": msg,
changed=changed, "changed": changed,
rebuilt=rebuilt, "rebuilt": rebuilt,
changes=changes, "changes": changes,
swarm_service=facts, "swarm_service": facts,
) }
if client.module._diff: if client.module._diff:
before, after = dsm.diff_tracker.get_before_after() before, after = dsm.diff_tracker.get_before_after()
results["diff"] = dict(before=before, after=after) results["diff"] = {"before": before, "after": after}
client.module.exit_json(**results) client.module.exit_json(**results)
except DockerException as e: except DockerException as e:

View File

@ -85,9 +85,9 @@ def get_service_info(client):
def main(): def main():
argument_spec = dict( argument_spec = {
name=dict(type="str", required=True), "name": {"type": "str", "required": True},
) }
client = AnsibleDockerSwarmClient( client = AnsibleDockerSwarmClient(
argument_spec=argument_spec, argument_spec=argument_spec,

View File

@ -161,7 +161,7 @@ class DockerVolumeManager:
self.results = {"changed": False, "actions": []} self.results = {"changed": False, "actions": []}
self.diff = self.client.module._diff self.diff = self.client.module._diff
self.diff_tracker = DifferenceTracker() self.diff_tracker = DifferenceTracker()
self.diff_result = dict() self.diff_result = {}
self.existing_volume = self.get_existing_volume() self.existing_volume = self.get_existing_volume()
@ -309,17 +309,23 @@ class DockerVolumeManager:
def main(): def main():
argument_spec = dict( argument_spec = {
volume_name=dict(type="str", required=True, aliases=["name"]), "volume_name": {"type": "str", "required": True, "aliases": ["name"]},
state=dict(type="str", default="present", choices=["present", "absent"]), "state": {
driver=dict(type="str", default="local"), "type": "str",
driver_options=dict(type="dict", default={}), "default": "present",
labels=dict(type="dict"), "choices": ["present", "absent"],
recreate=dict( },
type="str", default="never", choices=["always", "never", "options-changed"] "driver": {"type": "str", "default": "local"},
), "driver_options": {"type": "dict", "default": {}},
debug=dict(type="bool", default=False), "labels": {"type": "dict"},
) "recreate": {
"type": "str",
"default": "never",
"choices": ["always", "never", "options-changed"],
},
"debug": {"type": "bool", "default": False},
}
client = AnsibleDockerClient( client = AnsibleDockerClient(
argument_spec=argument_spec, argument_spec=argument_spec,

View File

@ -92,9 +92,9 @@ def get_existing_volume(client, volume_name):
def main(): def main():
argument_spec = dict( argument_spec = {
name=dict(type="str", required=True, aliases=["volume_name"]), "name": {"type": "str", "required": True, "aliases": ["volume_name"]},
) }
client = AnsibleDockerClient( client = AnsibleDockerClient(
argument_spec=argument_spec, argument_spec=argument_spec,
@ -106,7 +106,7 @@ def main():
client.module.exit_json( client.module.exit_json(
changed=False, changed=False,
exists=(True if volume else False), exists=bool(volume),
volume=volume, volume=volume,
) )
except DockerException as e: except DockerException as e:

View File

@ -364,7 +364,7 @@ class UnixSocketStreamTest(unittest.TestCase):
try: try:
while not self.stop_server: while not self.stop_server:
try: try:
connection, client_address = self.server_socket.accept() connection, dummy_client_address = self.server_socket.accept()
except socket.error: except socket.error:
# Probably no connection to accept yet # Probably no connection to accept yet
time.sleep(0.01) time.sleep(0.01)

View File

@ -807,7 +807,7 @@ class InMemoryStore(Store):
try: try:
return self.__store[server] return self.__store[server]
except KeyError: except KeyError:
raise CredentialsNotFound() raise CredentialsNotFound() from None
def store(self, server, username, secret): def store(self, server, username, secret):
self.__store[server] = { self.__store[server] = {