summaryrefslogtreecommitdiffstats
path: root/ansible_collections/community/docker/plugins/modules
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-05 16:18:34 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-05 16:18:34 +0000
commit3667197efb7b18ec842efd504785965911f8ac4b (patch)
tree0b986a4bc6879d080b100666a97cdabbc9ca1f28 /ansible_collections/community/docker/plugins/modules
parentAdding upstream version 9.5.1+dfsg. (diff)
downloadansible-upstream/10.0.0+dfsg.tar.xz
ansible-upstream/10.0.0+dfsg.zip
Adding upstream version 10.0.0+dfsg.upstream/10.0.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/community/docker/plugins/modules')
-rw-r--r--ansible_collections/community/docker/plugins/modules/docker_compose.py5
-rw-r--r--ansible_collections/community/docker/plugins/modules/docker_container.py19
-rw-r--r--ansible_collections/community/docker/plugins/modules/docker_container_exec.py3
-rw-r--r--ansible_collections/community/docker/plugins/modules/docker_image_build.py247
-rw-r--r--ansible_collections/community/docker/plugins/modules/docker_network.py35
-rw-r--r--ansible_collections/community/docker/plugins/modules/docker_prune.py60
-rw-r--r--ansible_collections/community/docker/plugins/modules/docker_swarm_service.py16
7 files changed, 375 insertions, 10 deletions
diff --git a/ansible_collections/community/docker/plugins/modules/docker_compose.py b/ansible_collections/community/docker/plugins/modules/docker_compose.py
index f8edbee4b..3af3bebb1 100644
--- a/ansible_collections/community/docker/plugins/modules/docker_compose.py
+++ b/ansible_collections/community/docker/plugins/modules/docker_compose.py
@@ -14,6 +14,11 @@ module: docker_compose
short_description: Manage multi-container Docker applications with Docker Compose V1
+deprecated:
+ removed_in: 4.0.0
+ why: This module uses docker-compose v1, which is End of Life since July 2022.
+ alternative: Migrate to M(community.docker.docker_compose_v2)
+
author: "Chris Houseknecht (@chouseknecht)"
description:
diff --git a/ansible_collections/community/docker/plugins/modules/docker_container.py b/ansible_collections/community/docker/plugins/modules/docker_container.py
index d7dbc3780..60768637f 100644
--- a/ansible_collections/community/docker/plugins/modules/docker_container.py
+++ b/ansible_collections/community/docker/plugins/modules/docker_container.py
@@ -369,7 +369,7 @@ options:
- Configure a check that is run to determine whether or not containers for this service are "healthy".
- "See the docs for the L(HEALTHCHECK Dockerfile instruction,https://docs.docker.com/engine/reference/builder/#healthcheck)
for details on how healthchecks work."
- - "O(healthcheck.interval), O(healthcheck.timeout) and O(healthcheck.start_period) are specified as durations.
+ - "O(healthcheck.interval), O(healthcheck.timeout), O(healthcheck.start_period), and O(healthcheck.start_interval) are specified as durations.
They accept duration as a string in a format that look like: V(5h34m56s), V(1m30s), and so on.
The supported units are V(us), V(ms), V(s), V(m) and V(h)."
type: dict
@@ -379,6 +379,16 @@ options:
- Command to run to check health.
- Must be either a string or a list. If it is a list, the first item must be one of V(NONE), V(CMD) or V(CMD-SHELL).
type: raw
+ test_cli_compatible:
+ description:
+ - If set to V(true), omitting O(healthcheck.test) while providing O(healthcheck) does not disable healthchecks,
+ but simply overwrites the image's values by the ones specified in O(healthcheck). This is
+ the behavior used by the Docker CLI.
+ - If set to V(false), omitting O(healthcheck.test) will disable the container's health check.
+ This is the classical behavior of the module and currently the default behavior.
+ default: false
+ type: bool
+ version_added: 3.10.0
interval:
description:
- Time between running the check.
@@ -399,6 +409,12 @@ options:
- Start period for the container to initialize before starting health-retries countdown.
- The default used by the Docker daemon is V(0s).
type: str
+ start_interval:
+ description:
+ - Time between health checks during the start period. This option requires Docker Engine version 25.0 or later.
+ - The default used by the Docker daemon is V(5s).
+ type: str
+ version_added: 3.10.0
hostname:
description:
- The container's hostname.
@@ -1196,6 +1212,7 @@ EXAMPLES = '''
timeout: 10s
retries: 3
start_period: 30s
+ start_interval: 10s
- name: Remove healthcheck from container
community.docker.docker_container:
diff --git a/ansible_collections/community/docker/plugins/modules/docker_container_exec.py b/ansible_collections/community/docker/plugins/modules/docker_container_exec.py
index 0d92dad96..251af5bcd 100644
--- a/ansible_collections/community/docker/plugins/modules/docker_container_exec.py
+++ b/ansible_collections/community/docker/plugins/modules/docker_container_exec.py
@@ -162,7 +162,6 @@ import shlex
import traceback
from ansible.module_utils.common.text.converters import to_text, to_bytes, to_native
-from ansible.module_utils.compat import selectors
from ansible.module_utils.six import string_types
from ansible_collections.community.docker.plugins.module_utils.common_api import (
@@ -170,6 +169,8 @@ from ansible_collections.community.docker.plugins.module_utils.common_api import
RequestException,
)
+from ansible_collections.community.docker.plugins.module_utils.selectors import selectors
+
from ansible_collections.community.docker.plugins.module_utils.socket_handler import (
DockerSocketHandlerModule,
)
diff --git a/ansible_collections/community/docker/plugins/modules/docker_image_build.py b/ansible_collections/community/docker/plugins/modules/docker_image_build.py
index 7f9502098..48478b550 100644
--- a/ansible_collections/community/docker/plugins/modules/docker_image_build.py
+++ b/ansible_collections/community/docker/plugins/modules/docker_image_build.py
@@ -18,6 +18,9 @@ version_added: 3.6.0
description:
- This module allows you to build Docker images using Docker's buildx plugin (BuildKit).
+ - Note that the module is B(not idempotent) in the sense of classical Ansible modules.
+ The only idempotence check is whether the built image already exists. This check can
+ be disabled with the O(rebuild) option.
extends_documentation_fragment:
- community.docker.docker.cli_documentation
@@ -89,8 +92,10 @@ options:
type: str
platform:
description:
- - Platform in the format C(os[/arch[/variant]]).
- type: str
+ - Platforms in the format C(os[/arch[/variant]]).
+ - Since community.docker 3.10.0 this can be a list of platforms, instead of just a single platform.
+ type: list
+ elements: str
shm_size:
description:
- "Size of C(/dev/shm) in format C(<number>[<unit>]). Number is positive integer.
@@ -110,7 +115,121 @@ options:
- never
- always
default: never
-
+ secrets:
+ description:
+ - Secrets to expose to the build.
+ type: list
+ elements: dict
+ version_added: 3.10.0
+ suboptions:
+ id:
+ description:
+ - The secret identifier.
+ - The secret will be made available as a file in the container under C(/run/secrets/<id>).
+ type: str
+ required: true
+ type:
+ description:
+ - Type of the secret.
+ type: str
+ choices:
+ file:
+ - Reads the secret from a file on the target.
+ - The file must be specified in O(secrets[].src).
+ env:
+ - Reads the secret from an environment variable on the target.
+ - The environment variable must be named in O(secrets[].env).
+ - Note that this requires the Buildkit plugin to have version 0.6.0 or newer.
+ value:
+ - Provides the secret from a given value O(secrets[].value).
+ - B(Note) that the secret will be passed as an environment variable to C(docker compose).
+ Use another mean of transport if you consider this not safe enough.
+ - Note that this requires the Buildkit plugin to have version 0.6.0 or newer.
+ required: true
+ src:
+ description:
+ - Source path of the secret.
+ - Only supported and required for O(secrets[].type=file).
+ type: path
+ env:
+ description:
+ - Environment value of the secret.
+ - Only supported and required for O(secrets[].type=env).
+ type: str
+ value:
+ description:
+ - Value of the secret.
+ - B(Note) that the secret will be passed as an environment variable to C(docker compose).
+ Use another mean of transport if you consider this not safe enough.
+ - Only supported and required for O(secrets[].type=value).
+ type: str
+ outputs:
+ description:
+ - Output destinations.
+ - You can provide a list of exporters to export the built image in various places.
+ Note that not all exporters might be supported by the build driver used.
+ - Note that depending on how this option is used, no image with name O(name) and tag O(tag) might
+ be created, which can cause the basic idempotency this module offers to not work.
+ - Providing an empty list to this option is equivalent to not specifying it at all.
+ The default behavior is a single entry with O(outputs[].type=image).
+ type: list
+ elements: dict
+ version_added: 3.10.0
+ suboptions:
+ type:
+ description:
+ - The type of exporter to use.
+ type: str
+ choices:
+ local:
+ - This export type writes all result files to a directory on the client.
+ The new files will be owned by the current user.
+ On multi-platform builds, all results will be put in subdirectories by their platform.
+ - The destination has to be provided in O(outputs[].dest).
+ tar:
+ - This export type export type writes all result files as a single tarball on the client.
+ On multi-platform builds, all results will be put in subdirectories by their platform.
+ - The destination has to be provided in O(outputs[].dest).
+ oci:
+ - This export type writes the result image or manifest list as an
+ L(OCI image layout, https://github.com/opencontainers/image-spec/blob/v1.0.1/image-layout.md)
+ tarball on the client.
+ - The destination has to be provided in O(outputs[].dest).
+ docker:
+ - This export type writes the single-platform result image as a Docker image specification tarball on the client.
+ Tarballs created by this exporter are also OCI compatible.
+ - The destination can be provided in O(outputs[].dest).
+ If not specified, the tar will be loaded automatically to the local image store.
+ - The Docker context where to import the result can be provided in O(outputs[].context).
+ image:
+ - This exporter writes the build result as an image or a manifest list.
+ When using this driver, the image will appear in C(docker images).
+ - The image name can be provided in O(outputs[].name). If it is not provided, the
+ - Optionally, image can be automatically pushed to a registry by setting O(outputs[].push=true).
+ required: true
+ dest:
+ description:
+ - The destination path.
+ - Required for O(outputs[].type=local), O(outputs[].type=tar), O(outputs[].type=oci).
+ - Optional for O(outputs[].type=docker).
+ type: path
+ context:
+ description:
+ - Name for the Docker context where to import the result.
+ - Optional for O(outputs[].type=docker).
+ type: str
+ name:
+ description:
+ - Name under which the image is stored under.
+ - If not provided, O(name) and O(tag) will be used.
+ - Optional for O(outputs[].type=image).
+ type: str
+ push:
+ description:
+ - Whether to push the built image to a registry.
+ - Only used for O(outputs[].type=image).
+ type: bool
+ default: false
requirements:
- "Docker CLI with Docker buildx plugin"
@@ -128,6 +247,15 @@ EXAMPLES = '''
name: localhost/python/3.12:latest
path: /home/user/images/python
dockerfile: Dockerfile-3.12
+
+- name: Build multi-platform image
+ community.docker.docker_image_build:
+ name: multi-platform-image
+ tag: "1.5.2"
+ path: /home/user/images/multi-platform
+ platform:
+ - linux/amd64
+ - linux/arm64/v8
'''
RETURN = '''
@@ -138,6 +266,7 @@ image:
sample: {}
'''
+import base64
import os
import traceback
@@ -156,6 +285,8 @@ from ansible_collections.community.docker.plugins.module_utils.util import (
is_valid_tag,
)
+from ansible_collections.community.docker.plugins.module_utils.version import LooseVersion
+
from ansible_collections.community.docker.plugins.module_utils._api.utils.utils import (
parse_repository_tag,
)
@@ -194,10 +325,26 @@ class ImageBuilder(DockerBaseClass):
self.shm_size = convert_to_bytes(parameters['shm_size'], self.client.module, 'shm_size')
self.labels = clean_dict_booleans_for_docker_api(parameters['labels'])
self.rebuild = parameters['rebuild']
+ self.secrets = parameters['secrets']
+ self.outputs = parameters['outputs']
buildx = self.client.get_client_plugin_info('buildx')
if buildx is None:
self.fail('Docker CLI {0} does not have the buildx plugin installed'.format(self.client.get_cli()))
+ buildx_version = buildx['Version'].lstrip('v')
+
+ if self.secrets:
+ for secret in self.secrets:
+ if secret['type'] in ('env', 'value'):
+ if LooseVersion(buildx_version) < LooseVersion('0.6.0'):
+ self.fail('The Docker buildx plugin has version {version}, but 0.6.0 is needed for secrets of type=env and type=value'.format(
+ version=buildx_version,
+ ))
+ if self.outputs and len(self.outputs) > 1:
+ if LooseVersion(buildx_version) < LooseVersion('0.13.0'):
+ self.fail('The Docker buildx plugin has version {version}, but 0.13.0 is needed to specify more than one output'.format(
+ version=buildx_version,
+ ))
self.path = parameters['path']
if not os.path.isdir(self.path):
@@ -230,6 +377,7 @@ class ImageBuilder(DockerBaseClass):
args.extend([option, value])
def add_args(self, args):
+ environ_update = {}
args.extend(['--tag', '%s:%s' % (self.name, self.tag)])
if self.dockerfile:
args.extend(['--file', os.path.join(self.path, self.dockerfile)])
@@ -248,11 +396,54 @@ class ImageBuilder(DockerBaseClass):
if self.target:
args.extend(['--target', self.target])
if self.platform:
- args.extend(['--platform', self.platform])
+ for platform in self.platform:
+ args.extend(['--platform', platform])
if self.shm_size:
args.extend(['--shm-size', str(self.shm_size)])
if self.labels:
self.add_list_arg(args, '--label', dict_to_list(self.labels))
+ if self.secrets:
+ random_prefix = None
+ for index, secret in enumerate(self.secrets):
+ if secret['type'] == 'file':
+ args.extend(['--secret', 'id={id},type=file,src={src}'.format(id=secret['id'], src=secret['src'])])
+ if secret['type'] == 'env':
+ args.extend(['--secret', 'id={id},type=env,env={env}'.format(id=secret['id'], env=secret['src'])])
+ if secret['type'] == 'value':
+ # We pass values on using environment variables. The user has been warned in the documentation
+ # that they should only use this mechanism when being comfortable with it.
+ if random_prefix is None:
+ # Use /dev/urandom to generate some entropy to make the environment variable's name unguessable
+ random_prefix = base64.b64encode(os.urandom(16)).decode('utf-8').replace('=', '')
+ env_name = 'ANSIBLE_DOCKER_COMPOSE_ENV_SECRET_{random}_{id}'.format(
+ random=random_prefix,
+ id=index,
+ )
+ environ_update[env_name] = secret['value']
+ args.extend(['--secret', 'id={id},type=env,env={env}'.format(id=secret['id'], env=env_name)])
+ if self.outputs:
+ for output in self.outputs:
+ if output['type'] == 'local':
+ args.extend(['--output', 'type=local,dest={dest}'.format(dest=output['dest'])])
+ if output['type'] == 'tar':
+ args.extend(['--output', 'type=tar,dest={dest}'.format(dest=output['dest'])])
+ if output['type'] == 'oci':
+ args.extend(['--output', 'type=oci,dest={dest}'.format(dest=output['dest'])])
+ if output['type'] == 'docker':
+ more = []
+ if output['dest'] is not None:
+ more.append('dest={dest}'.format(dest=output['dest']))
+ if output['dest'] is not None:
+ more.append('context={context}'.format(context=output['context']))
+ args.extend(['--output', 'type=docker,{more}'.format(more=','.join(more))])
+ if output['type'] == 'image':
+ more = []
+ if output['name'] is not None:
+ more.append('name={name}'.format(name=output['name']))
+ if output['push']:
+ more.append('push=true')
+ args.extend(['--output', 'type=image,{more}'.format(more=','.join(more))])
+ return environ_update
def build_image(self):
image = self.client.find_image(self.name, self.tag)
@@ -269,9 +460,9 @@ class ImageBuilder(DockerBaseClass):
results['changed'] = True
if not self.check_mode:
args = ['buildx', 'build', '--progress', 'plain']
- self.add_args(args)
+ environ_update = self.add_args(args)
args.extend(['--', self.path])
- rc, stdout, stderr = self.client.call_cli(*args)
+ rc, stdout, stderr = self.client.call_cli(*args, environ_update=environ_update)
if rc != 0:
self.fail('Building %s:%s failed' % (self.name, self.tag), stdout=to_native(stdout), stderr=to_native(stderr))
results['stdout'] = to_native(stdout)
@@ -294,10 +485,52 @@ def main():
etc_hosts=dict(type='dict'),
args=dict(type='dict'),
target=dict(type='str'),
- platform=dict(type='str'),
+ platform=dict(type='list', elements='str'),
shm_size=dict(type='str'),
labels=dict(type='dict'),
rebuild=dict(type='str', choices=['never', 'always'], default='never'),
+ secrets=dict(
+ type='list',
+ elements='dict',
+ options=dict(
+ id=dict(type='str', required=True),
+ type=dict(type='str', choices=['file', 'env', 'value'], required=True),
+ src=dict(type='path'),
+ env=dict(type='str'),
+ value=dict(type='str', no_log=True),
+ ),
+ required_if=[
+ ('type', 'file', ['src']),
+ ('type', 'env', ['env']),
+ ('type', 'value', ['value']),
+ ],
+ mutually_exclusive=[
+ ('src', 'env', 'value'),
+ ],
+ no_log=False,
+ ),
+ outputs=dict(
+ type='list',
+ elements='dict',
+ options=dict(
+ type=dict(type='str', choices=['local', 'tar', 'oci', 'docker', 'image'], required=True),
+ dest=dict(type='path'),
+ context=dict(type='str'),
+ name=dict(type='str'),
+ push=dict(type='bool', default=False),
+ ),
+ required_if=[
+ ('type', 'local', ['dest']),
+ ('type', 'tar', ['dest']),
+ ('type', 'oci', ['dest']),
+ ],
+ mutually_exclusive=[
+ ('dest', 'name'),
+ ('dest', 'push'),
+ ('context', 'name'),
+ ('context', 'push'),
+ ],
+ ),
)
client = AnsibleModuleDockerClient(
diff --git a/ansible_collections/community/docker/plugins/modules/docker_network.py b/ansible_collections/community/docker/plugins/modules/docker_network.py
index 5670ceea0..c5dd3b229 100644
--- a/ansible_collections/community/docker/plugins/modules/docker_network.py
+++ b/ansible_collections/community/docker/plugins/modules/docker_network.py
@@ -35,6 +35,18 @@ options:
aliases:
- network_name
+ config_from:
+ description:
+ - Specifies the config only network to use the config from.
+ type: str
+ version_added: 3.10.0
+
+ config_only:
+ description:
+ - Sets that this is a config only network.
+ type: bool
+ version_added: 3.10.0
+
connected:
description:
- List of container names or container IDs to connect to a network.
@@ -283,6 +295,8 @@ class TaskParameters(DockerBaseClass):
self.name = None
self.connected = None
+ self.config_from = None
+ self.config_only = None
self.driver = None
self.driver_options = None
self.ipam_driver = None
@@ -300,6 +314,11 @@ class TaskParameters(DockerBaseClass):
for key, value in client.module.params.items():
setattr(self, key, value)
+ # config_only sets driver to 'null' (and scope to 'local') so force that here. Otherwise we get
+ # diffs of 'null' --> 'bridge' given that the driver option defaults to 'bridge'.
+ if self.config_only:
+ self.driver = 'null'
+
def container_names_in_network(network):
return [c['Name'] for c in network['Containers'].values()] if network['Containers'] else []
@@ -401,6 +420,14 @@ class DockerNetworkManager(object):
:return: (bool, list)
'''
differences = DifferenceTracker()
+ if self.parameters.config_only is not None and self.parameters.config_only != net.get('ConfigOnly', False):
+ differences.add('config_only',
+ parameter=self.parameters.config_only,
+ active=net.get('ConfigOnly', False))
+ if self.parameters.config_from is not None and self.parameters.config_from != net.get('ConfigFrom', {}).get('Network', ''):
+ differences.add('config_from',
+ parameter=self.parameters.config_from,
+ active=net.get('ConfigFrom', {}).get('Network', ''))
if self.parameters.driver and self.parameters.driver != net['Driver']:
differences.add('driver',
parameter=self.parameters.driver,
@@ -503,6 +530,10 @@ class DockerNetworkManager(object):
'CheckDuplicate': None,
}
+ if self.parameters.config_only is not None:
+ data['ConfigOnly'] = self.parameters.config_only
+ if self.parameters.config_from:
+ data['ConfigFrom'] = {'Network': self.parameters.config_from}
if self.parameters.enable_ipv6:
data['EnableIPv6'] = True
if self.parameters.internal:
@@ -630,6 +661,8 @@ class DockerNetworkManager(object):
def main():
argument_spec = dict(
name=dict(type='str', required=True, aliases=['network_name']),
+ config_from=dict(type='str'),
+ config_only=dict(type='bool'),
connected=dict(type='list', default=[], elements='str', aliases=['containers']),
state=dict(type='str', default='present', choices=['present', 'absent']),
driver=dict(type='str', default='bridge'),
@@ -653,6 +686,8 @@ def main():
)
option_minimal_versions = dict(
+ config_from=dict(docker_api_version='1.30'),
+ config_only=dict(docker_api_version='1.30'),
scope=dict(docker_api_version='1.30'),
attachable=dict(docker_api_version='1.26'),
)
diff --git a/ansible_collections/community/docker/plugins/modules/docker_prune.py b/ansible_collections/community/docker/plugins/modules/docker_prune.py
index 1dfbf290e..a333c52fe 100644
--- a/ansible_collections/community/docker/plugins/modules/docker_prune.py
+++ b/ansible_collections/community/docker/plugins/modules/docker_prune.py
@@ -81,6 +81,28 @@ options:
- Whether to prune the builder cache.
type: bool
default: false
+ builder_cache_all:
+ description:
+ - Whether to remove all types of build cache.
+ type: bool
+ default: false
+ version_added: 3.10.0
+ builder_cache_filters:
+ description:
+ - A dictionary of filter values used for selecting images to delete.
+ - "For example, C(until: 10m)."
+ - See L(the API documentation,https://docs.docker.com/engine/api/v1.44/#tag/Image/operation/BuildPrune)
+ for more information on possible filters.
+ type: dict
+ version_added: 3.10.0
+ builder_cache_keep_storage:
+ description:
+ - Amount of disk space to keep for cache in format C(<number>[<unit>])."
+ - "Number is a positive integer. Unit can be one of V(B) (byte), V(K) (kibibyte, 1024B), V(M) (mebibyte), V(G) (gibibyte),
+ V(T) (tebibyte), or V(P) (pebibyte)."
+ - "Omitting the unit defaults to bytes."
+ type: str
+ version_added: 3.10.0
author:
- "Felix Fontein (@felixfontein)"
@@ -181,11 +203,20 @@ builder_cache_space_reclaimed:
returned: O(builder_cache=true)
type: int
sample: 0
+builder_cache_caches_deleted:
+ description:
+ - The build caches that were deleted.
+ returned: O(builder_cache=true) and API version is 1.39 or later
+ type: list
+ elements: str
+ sample: []
+ version_added: 3.10.0
'''
import traceback
from ansible.module_utils.common.text.converters import to_native
+from ansible.module_utils.common.text.formatters import human_to_bytes
from ansible_collections.community.docker.plugins.module_utils.common_api import (
AnsibleDockerClient,
@@ -209,13 +240,29 @@ def main():
volumes=dict(type='bool', default=False),
volumes_filters=dict(type='dict'),
builder_cache=dict(type='bool', default=False),
+ builder_cache_all=dict(type='bool', default=False),
+ builder_cache_filters=dict(type='dict'),
+ builder_cache_keep_storage=dict(type='str'), # convert to bytes
)
client = AnsibleDockerClient(
argument_spec=argument_spec,
+ option_minimal_versions=dict(
+ builder_cache=dict(docker_py_version='1.31'),
+ builder_cache_all=dict(docker_py_version='1.39'),
+ builder_cache_filters=dict(docker_py_version='1.31'),
+ builder_cache_keep_storage=dict(docker_py_version='1.39'),
+ ),
# supports_check_mode=True,
)
+ builder_cache_keep_storage = None
+ if client.module.params.get('builder_cache_keep_storage') is not None:
+ try:
+ builder_cache_keep_storage = human_to_bytes(client.module.params.get('builder_cache_keep_storage'))
+ except ValueError as exc:
+ client.module.fail_json(msg='Error while parsing value of builder_cache_keep_storage: {0}'.format(exc))
+
try:
result = dict()
changed = False
@@ -256,10 +303,21 @@ def main():
changed = True
if client.module.params['builder_cache']:
- res = client.post_to_json('/build/prune')
+ filters = clean_dict_booleans_for_docker_api(client.module.params.get('builder_cache_filters'))
+ params = {'filters': convert_filters(filters)}
+ if client.module.params.get('builder_cache_all'):
+ params['all'] = 'true'
+ if builder_cache_keep_storage is not None:
+ params['keep-storage'] = builder_cache_keep_storage
+ res = client.post_to_json('/build/prune', params=params)
result['builder_cache_space_reclaimed'] = res['SpaceReclaimed']
if result['builder_cache_space_reclaimed']:
changed = True
+ if 'CachesDeleted' in res:
+ # API version 1.39+: return value CachesDeleted (list of str)
+ result['builder_cache_caches_deleted'] = res['CachesDeleted']
+ if result['builder_cache_caches_deleted']:
+ changed = True
result['changed'] = changed
client.module.exit_json(**result)
diff --git a/ansible_collections/community/docker/plugins/modules/docker_swarm_service.py b/ansible_collections/community/docker/plugins/modules/docker_swarm_service.py
index 95cc10366..4660d1138 100644
--- a/ansible_collections/community/docker/plugins/modules/docker_swarm_service.py
+++ b/ansible_collections/community/docker/plugins/modules/docker_swarm_service.py
@@ -83,6 +83,11 @@ options:
- Dictionary of key value pairs.
- Corresponds to the C(--container-label) option of C(docker service create).
type: dict
+ sysctls:
+ description:
+ - Dictionary of key, value pairs.
+ version_added: 3.10.0
+ type: dict
dns:
description:
- List of custom DNS servers.
@@ -681,6 +686,7 @@ swarm_service:
"engine.labels.operatingsystem == ubuntu 14.04"
],
"container_labels": null,
+ "sysctls": null,
"dns": null,
"dns_options": null,
"dns_search": null,
@@ -1226,6 +1232,7 @@ class DockerService(DockerBaseClass):
self.log_driver_options = None
self.labels = None
self.container_labels = None
+ self.sysctls = None
self.limit_cpu = None
self.limit_memory = None
self.reserve_cpu = None
@@ -1292,6 +1299,7 @@ class DockerService(DockerBaseClass):
'placement_preferences': self.placement_preferences,
'labels': self.labels,
'container_labels': self.container_labels,
+ 'sysctls': self.sysctls,
'mode': self.mode,
'replicas': self.replicas,
'endpoint_mode': self.endpoint_mode,
@@ -1539,6 +1547,7 @@ class DockerService(DockerBaseClass):
s.tty = ap['tty']
s.labels = ap['labels']
s.container_labels = ap['container_labels']
+ s.sysctls = ap['sysctls']
s.mode = ap['mode']
s.stop_signal = ap['stop_signal']
s.user = ap['user']
@@ -1740,6 +1749,8 @@ class DockerService(DockerBaseClass):
differences.add('reserve_memory', parameter=self.reserve_memory, active=os.reserve_memory)
if self.container_labels is not None and self.container_labels != (os.container_labels or {}):
differences.add('container_labels', parameter=self.container_labels, active=os.container_labels)
+ if self.sysctls is not None and self.sysctls != (os.sysctls or {}):
+ differences.add('sysctls', parameter=self.sysctls, active=os.sysctls)
if self.stop_signal is not None and self.stop_signal != os.stop_signal:
differences.add('stop_signal', parameter=self.stop_signal, active=os.stop_signal)
if self.stop_grace_period is not None and self.stop_grace_period != os.stop_grace_period:
@@ -1934,6 +1945,8 @@ class DockerService(DockerBaseClass):
container_spec_args['user'] = self.user
if self.container_labels is not None:
container_spec_args['labels'] = self.container_labels
+ if self.sysctls is not None:
+ container_spec_args['sysctls'] = self.sysctls
if self.healthcheck is not None:
container_spec_args['healthcheck'] = types.Healthcheck(**self.healthcheck)
elif self.healthcheck_disabled:
@@ -2163,6 +2176,7 @@ class DockerServiceManager(object):
ds.read_only = task_template_data['ContainerSpec'].get('ReadOnly')
ds.cap_add = task_template_data['ContainerSpec'].get('CapabilityAdd')
ds.cap_drop = task_template_data['ContainerSpec'].get('CapabilityDrop')
+ ds.sysctls = task_template_data['ContainerSpec'].get('Sysctls')
healthcheck_data = task_template_data['ContainerSpec'].get('Healthcheck')
if healthcheck_data:
@@ -2676,6 +2690,7 @@ def main():
hosts=dict(type='dict'),
labels=dict(type='dict'),
container_labels=dict(type='dict'),
+ sysctls=dict(type='dict'),
mode=dict(
type='str',
default='replicated',
@@ -2751,6 +2766,7 @@ def main():
init=dict(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_drop=dict(docker_py_version='5.0.3', docker_api_version='1.41'),
+ sysctls=dict(docker_py_version='6.0.0', docker_api_version='1.40'),
# specials
publish_mode=dict(
docker_py_version='3.0.0',