Reformat code with black and isort.

This commit is contained in:
Felix Fontein
2025-10-06 18:34:59 +02:00
parent f45232635c
commit d65d37e9e9
132 changed files with 17581 additions and 14729 deletions
+147 -150
View File
@@ -16,40 +16,44 @@ import os
import os.path
import shlex
import string
from ansible_collections.community.docker.plugins.module_utils.version import StrictVersion
from urllib.parse import urlparse, urlunparse
from ansible_collections.community.docker.plugins.module_utils.version import (
StrictVersion,
)
from .. import errors
from ..constants import DEFAULT_HTTP_HOST
from ..constants import DEFAULT_UNIX_SOCKET
from ..constants import DEFAULT_NPIPE
from ..constants import BYTE_UNITS
from ..constants import (
BYTE_UNITS,
DEFAULT_HTTP_HOST,
DEFAULT_NPIPE,
DEFAULT_UNIX_SOCKET,
)
from ..tls import TLSConfig
from urllib.parse import urlparse, urlunparse
URLComponents = collections.namedtuple(
'URLComponents',
'scheme netloc url params query fragment',
"URLComponents",
"scheme netloc url params query fragment",
)
def create_ipam_pool(*args, **kwargs):
raise errors.DeprecatedMethod(
'utils.create_ipam_pool has been removed. Please use a '
'docker.types.IPAMPool object instead.'
"utils.create_ipam_pool has been removed. Please use a "
"docker.types.IPAMPool object instead."
)
def create_ipam_config(*args, **kwargs):
raise errors.DeprecatedMethod(
'utils.create_ipam_config has been removed. Please use a '
'docker.types.IPAMConfig object instead.'
"utils.create_ipam_config has been removed. Please use a "
"docker.types.IPAMConfig object instead."
)
def decode_json_header(header):
data = base64.b64decode(header).decode('utf-8')
data = base64.b64decode(header).decode("utf-8")
return json.loads(data)
@@ -84,29 +88,29 @@ def version_gte(v1, v2):
def _convert_port_binding(binding):
result = {'HostIp': '', 'HostPort': ''}
result = {"HostIp": "", "HostPort": ""}
if isinstance(binding, tuple):
if len(binding) == 2:
result['HostPort'] = binding[1]
result['HostIp'] = binding[0]
result["HostPort"] = binding[1]
result["HostIp"] = binding[0]
elif isinstance(binding[0], str):
result['HostIp'] = binding[0]
result["HostIp"] = binding[0]
else:
result['HostPort'] = binding[0]
result["HostPort"] = binding[0]
elif isinstance(binding, dict):
if 'HostPort' in binding:
result['HostPort'] = binding['HostPort']
if 'HostIp' in binding:
result['HostIp'] = binding['HostIp']
if "HostPort" in binding:
result["HostPort"] = binding["HostPort"]
if "HostIp" in binding:
result["HostIp"] = binding["HostIp"]
else:
raise ValueError(binding)
else:
result['HostPort'] = binding
result["HostPort"] = binding
if result['HostPort'] is None:
result['HostPort'] = ''
if result["HostPort"] is None:
result["HostPort"] = ""
else:
result['HostPort'] = str(result['HostPort'])
result["HostPort"] = str(result["HostPort"])
return result
@@ -115,8 +119,8 @@ def convert_port_bindings(port_bindings):
result = {}
for k, v in port_bindings.items():
key = str(k)
if '/' not in key:
key += '/tcp'
if "/" not in key:
key += "/tcp"
if isinstance(v, list):
result[key] = [_convert_port_binding(binding) for binding in v]
else:
@@ -131,46 +135,44 @@ def convert_volume_binds(binds):
result = []
for k, v in binds.items():
if isinstance(k, bytes):
k = k.decode('utf-8')
k = k.decode("utf-8")
if isinstance(v, dict):
if 'ro' in v and 'mode' in v:
raise ValueError(
f'Binding cannot contain both "ro" and "mode": {v!r}'
)
if "ro" in v and "mode" in v:
raise ValueError(f'Binding cannot contain both "ro" and "mode": {v!r}')
bind = v['bind']
bind = v["bind"]
if isinstance(bind, bytes):
bind = bind.decode('utf-8')
bind = bind.decode("utf-8")
if 'ro' in v:
mode = 'ro' if v['ro'] else 'rw'
elif 'mode' in v:
mode = v['mode']
if "ro" in v:
mode = "ro" if v["ro"] else "rw"
elif "mode" in v:
mode = v["mode"]
else:
mode = 'rw'
mode = "rw"
# NOTE: this is only relevant for Linux hosts
# (does not apply in Docker Desktop)
propagation_modes = [
'rshared',
'shared',
'rslave',
'slave',
'rprivate',
'private',
"rshared",
"shared",
"rslave",
"slave",
"rprivate",
"private",
]
if 'propagation' in v and v['propagation'] in propagation_modes:
if "propagation" in v and v["propagation"] in propagation_modes:
if mode:
mode = ','.join([mode, v['propagation']])
mode = ",".join([mode, v["propagation"]])
else:
mode = v['propagation']
mode = v["propagation"]
result.append(f'{k}:{bind}:{mode}')
result.append(f"{k}:{bind}:{mode}")
else:
if isinstance(v, bytes):
v = v.decode('utf-8')
result.append(f'{k}:{v}:rw')
v = v.decode("utf-8")
result.append(f"{k}:{v}:rw")
return result
@@ -180,7 +182,7 @@ def convert_tmpfs_mounts(tmpfs):
if not isinstance(tmpfs, list):
raise ValueError(
f'Expected tmpfs value to be either a list or a dict, found: {type(tmpfs).__name__}'
f"Expected tmpfs value to be either a list or a dict, found: {type(tmpfs).__name__}"
)
result = {}
@@ -205,22 +207,22 @@ def convert_service_networks(networks):
if not networks:
return networks
if not isinstance(networks, list):
raise TypeError('networks parameter must be a list.')
raise TypeError("networks parameter must be a list.")
result = []
for n in networks:
if isinstance(n, str):
n = {'Target': n}
n = {"Target": n}
result.append(n)
return result
def parse_repository_tag(repo_name):
parts = repo_name.rsplit('@', 1)
parts = repo_name.rsplit("@", 1)
if len(parts) == 2:
return tuple(parts)
parts = repo_name.rsplit(':', 1)
if len(parts) == 2 and '/' not in parts[1]:
parts = repo_name.rsplit(":", 1)
if len(parts) == 2 and "/" not in parts[1]:
return tuple(parts)
return repo_name, None
@@ -229,86 +231,81 @@ def parse_host(addr, is_win32=False, tls=False):
# Sensible defaults
if not addr and is_win32:
return DEFAULT_NPIPE
if not addr or addr.strip() == 'unix://':
if not addr or addr.strip() == "unix://":
return DEFAULT_UNIX_SOCKET
addr = addr.strip()
parsed_url = urlparse(addr)
proto = parsed_url.scheme
if not proto or any(x not in string.ascii_letters + '+' for x in proto):
if not proto or any(x not in string.ascii_letters + "+" for x in proto):
# https://bugs.python.org/issue754016
parsed_url = urlparse('//' + addr, 'tcp')
proto = 'tcp'
parsed_url = urlparse("//" + addr, "tcp")
proto = "tcp"
if proto == 'fd':
raise errors.DockerException('fd protocol is not implemented')
if proto == "fd":
raise errors.DockerException("fd protocol is not implemented")
# These protos are valid aliases for our library but not for the
# official spec
if proto == 'http' or proto == 'https':
tls = proto == 'https'
proto = 'tcp'
elif proto == 'http+unix':
proto = 'unix'
if proto == "http" or proto == "https":
tls = proto == "https"
proto = "tcp"
elif proto == "http+unix":
proto = "unix"
if proto not in ('tcp', 'unix', 'npipe', 'ssh'):
raise errors.DockerException(
f"Invalid bind address protocol: {addr}"
)
if proto not in ("tcp", "unix", "npipe", "ssh"):
raise errors.DockerException(f"Invalid bind address protocol: {addr}")
if proto == 'tcp' and not parsed_url.netloc:
if proto == "tcp" and not parsed_url.netloc:
# "tcp://" is exceptionally disallowed by convention;
# omitting a hostname for other protocols is fine
raise errors.DockerException(
f'Invalid bind address format: {addr}'
)
raise errors.DockerException(f"Invalid bind address format: {addr}")
if any([
parsed_url.params, parsed_url.query, parsed_url.fragment,
parsed_url.password
]):
raise errors.DockerException(
f'Invalid bind address format: {addr}'
)
if any(
[parsed_url.params, parsed_url.query, parsed_url.fragment, parsed_url.password]
):
raise errors.DockerException(f"Invalid bind address format: {addr}")
if parsed_url.path and proto == 'ssh':
if parsed_url.path and proto == "ssh":
raise errors.DockerException(
f'Invalid bind address format: no path allowed for this protocol: {addr}'
f"Invalid bind address format: no path allowed for this protocol: {addr}"
)
else:
path = parsed_url.path
if proto == 'unix' and parsed_url.hostname is not None:
if proto == "unix" and parsed_url.hostname is not None:
# For legacy reasons, we consider unix://path
# to be valid and equivalent to unix:///path
path = '/'.join((parsed_url.hostname, path))
path = "/".join((parsed_url.hostname, path))
netloc = parsed_url.netloc
if proto in ('tcp', 'ssh'):
if proto in ("tcp", "ssh"):
port = parsed_url.port or 0
if port <= 0:
port = 22 if proto == 'ssh' else (2375 if tls else 2376)
netloc = f'{parsed_url.netloc}:{port}'
port = 22 if proto == "ssh" else (2375 if tls else 2376)
netloc = f"{parsed_url.netloc}:{port}"
if not parsed_url.hostname:
netloc = f'{DEFAULT_HTTP_HOST}:{port}'
netloc = f"{DEFAULT_HTTP_HOST}:{port}"
# Rewrite schemes to fit library internals (requests adapters)
if proto == 'tcp':
if proto == "tcp":
proto = f"http{'s' if tls else ''}"
elif proto == 'unix':
proto = 'http+unix'
elif proto == "unix":
proto = "http+unix"
if proto in ('http+unix', 'npipe'):
return f"{proto}://{path}".rstrip('/')
return urlunparse(URLComponents(
scheme=proto,
netloc=netloc,
url=path,
params='',
query='',
fragment='',
)).rstrip('/')
if proto in ("http+unix", "npipe"):
return f"{proto}://{path}".rstrip("/")
return urlunparse(
URLComponents(
scheme=proto,
netloc=netloc,
url=path,
params="",
query="",
fragment="",
)
).rstrip("/")
def parse_devices(devices):
@@ -318,10 +315,8 @@ def parse_devices(devices):
device_list.append(device)
continue
if not isinstance(device, str):
raise errors.DockerException(
f'Invalid device type {type(device)}'
)
device_mapping = device.split(':')
raise errors.DockerException(f"Invalid device type {type(device)}")
device_mapping = device.split(":")
if device_mapping:
path_on_host = device_mapping[0]
if len(device_mapping) > 1:
@@ -331,27 +326,29 @@ def parse_devices(devices):
if len(device_mapping) > 2:
permissions = device_mapping[2]
else:
permissions = 'rwm'
device_list.append({
'PathOnHost': path_on_host,
'PathInContainer': path_in_container,
'CgroupPermissions': permissions
})
permissions = "rwm"
device_list.append(
{
"PathOnHost": path_on_host,
"PathInContainer": path_in_container,
"CgroupPermissions": permissions,
}
)
return device_list
def kwargs_from_env(ssl_version=None, assert_hostname=None, environment=None):
if not environment:
environment = os.environ
host = environment.get('DOCKER_HOST')
host = environment.get("DOCKER_HOST")
# empty string for cert path is the same as unset.
cert_path = environment.get('DOCKER_CERT_PATH') or None
cert_path = environment.get("DOCKER_CERT_PATH") or None
# empty string for tls verify counts as "false".
# Any value or 'unset' counts as true.
tls_verify = environment.get('DOCKER_TLS_VERIFY')
if tls_verify == '':
tls_verify = environment.get("DOCKER_TLS_VERIFY")
if tls_verify == "":
tls_verify = False
else:
tls_verify = tls_verify is not None
@@ -360,23 +357,25 @@ def kwargs_from_env(ssl_version=None, assert_hostname=None, environment=None):
params = {}
if host:
params['base_url'] = host
params["base_url"] = host
if not enable_tls:
return params
if not cert_path:
cert_path = os.path.join(os.path.expanduser('~'), '.docker')
cert_path = os.path.join(os.path.expanduser("~"), ".docker")
if not tls_verify and assert_hostname is None:
# assert_hostname is a subset of TLS verification,
# so if it is not set already then set it to false.
assert_hostname = False
params['tls'] = TLSConfig(
client_cert=(os.path.join(cert_path, 'cert.pem'),
os.path.join(cert_path, 'key.pem')),
ca_cert=os.path.join(cert_path, 'ca.pem'),
params["tls"] = TLSConfig(
client_cert=(
os.path.join(cert_path, "cert.pem"),
os.path.join(cert_path, "key.pem"),
),
ca_cert=os.path.join(cert_path, "ca.pem"),
verify=tls_verify,
ssl_version=ssl_version,
assert_hostname=assert_hostname,
@@ -389,13 +388,12 @@ def convert_filters(filters):
result = {}
for k, v in filters.items():
if isinstance(v, bool):
v = 'true' if v else 'false'
v = "true" if v else "false"
if not isinstance(v, list):
v = [v, ]
result[k] = [
str(item) if not isinstance(item, str) else item
for item in v
]
v = [
v,
]
result[k] = [str(item) if not isinstance(item, str) else item for item in v]
return json.dumps(result)
@@ -415,7 +413,7 @@ def parse_bytes(s):
# without a units part. Assuming that the units are bytes.
if suffix.isdigit():
digits_part = s
suffix = 'b'
suffix = "b"
else:
digits_part = s[:-1]
@@ -424,14 +422,14 @@ def parse_bytes(s):
digits = float(digits_part)
except ValueError:
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."
)
# Reconvert to long for the final result
s = int(digits * units[suffix])
else:
raise errors.DockerException(
f'The specified value for memory ({s}) should specify the units. The postfix should be one of the `b` `k` `m` `g` characters'
f"The specified value for memory ({s}) should specify the units. The postfix should be one of the `b` `k` `m` `g` characters"
)
return s
@@ -441,7 +439,7 @@ def normalize_links(links):
if isinstance(links, dict):
links = links.items()
return [f'{k}:{v}' if v else k for k, v in sorted(links)]
return [f"{k}:{v}" if v else k for k, v in sorted(links)]
def parse_env_file(env_file):
@@ -451,22 +449,24 @@ def parse_env_file(env_file):
"""
environment = {}
with open(env_file, 'r') as f:
with open(env_file, "r") as f:
for line in f:
if line[0] == '#':
if line[0] == "#":
continue
line = line.strip()
if not line:
continue
parse_line = line.split('=', 1)
parse_line = line.split("=", 1)
if len(parse_line) == 2:
k, v = parse_line
environment[k] = v
else:
raise errors.DockerException(f'Invalid line in environment file {env_file}:\n{line}')
raise errors.DockerException(
f"Invalid line in environment file {env_file}:\n{line}"
)
return environment
@@ -480,26 +480,23 @@ def format_environment(environment):
if value is None:
return key
if isinstance(value, bytes):
value = value.decode('utf-8')
value = value.decode("utf-8")
return f"{key}={value}"
return f'{key}={value}'
return [format_env(*var) for var in environment.items()]
def format_extra_hosts(extra_hosts, task=False):
# Use format dictated by Swarm API if container is part of a task
if task:
return [
f'{v} {k}' for k, v in sorted(extra_hosts.items())
]
return [f"{v} {k}" for k, v in sorted(extra_hosts.items())]
return [
f'{k}:{v}' for k, v in sorted(extra_hosts.items())
]
return [f"{k}:{v}" for k, v in sorted(extra_hosts.items())]
def create_host_config(self, *args, **kwargs):
raise errors.DeprecatedMethod(
'utils.create_host_config has been removed. Please use a '
'docker.types.HostConfig object instead.'
"utils.create_host_config has been removed. Please use a "
"docker.types.HostConfig object instead."
)