1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

docker_image: improve usage (#52894)

* Add source option.

* Split force parameter into force_source, force_absent and force_tag.

* Move all build-related options into a suboption called build.

* Add changelog.
This commit is contained in:
Felix Fontein 2019-03-14 10:46:38 +01:00 committed by John R Barker
parent fa7c8ce0b4
commit 35e7fb776a
5 changed files with 378 additions and 108 deletions

View file

@ -1,2 +1,2 @@
minor_changes: minor_changes:
- "docker_image - Add ``cache_from`` option." - "docker_image - Add ``build.cache_from`` option."

View file

@ -0,0 +1,4 @@
minor_changes:
- "docker_image - the ``source`` option has been added to clarify the action performed by the module."
- "docker_image - the ``force`` option has been deprecated; more specific options ``force_source``, ``force_absent`` and ``force_tag`` have been added instead."
- "docker_image - all build-related options have been moved into a suboption ``build``. This affects the ``dockerfile``, ``http_timeout``, ``nocache``, ``path``, ``pull``, ``rm``, and ``buildargs`` options."

View file

@ -21,41 +21,161 @@ short_description: Manage docker images.
version_added: "1.5" version_added: "1.5"
description: description:
- Build, load or pull an image, making the image available for creating containers. Also supports tagging an - Build, load or pull an image, making the image available for creating containers. Also supports tagging an
image into a repository and archiving an image to a .tar file. image into a repository and archiving an image to a .tar file.
- Since Ansible 2.8, it is recommended to explicitly specify the image's source (C(source=build),
C(source=load), C(source=pull) or C(source=local)). This will be required from Ansible 2.12 on.
options: options:
source:
description:
- "Determines where the module will try to retrieve the image from."
- "Use C(build) to build the image from a C(Dockerfile). I(path) must
be specified when this value is used."
- "Use C(load) to load the image from a C(.tar) file. I(load_path) must
be specified when this value is used."
- "Use C(pull) to pull the image from a registry."
- "Use C(local) to make sure that the image is already available on the local
docker daemon, i.e. do not try to build, pull or load the image."
- "Before Ansible 2.12, the value of this option will be auto-detected
to be backwards compatible, but a warning will be issued if it is not
explicitly specified. From Ansible 2.12 on, auto-detection will be disabled
and this option will be made mandatory."
type: str
choices:
- build
- load
- pull
- local
version_added: "2.8"
build:
description:
- "Specifies options used for building images."
type: dict
suboptions:
cache_from:
description:
- List of image names to consider as cache source.
type: list
dockerfile:
description:
- Use with state C(present) to provide an alternate name for the Dockerfile to use when building an image.
type: str
http_timeout:
description:
- Timeout for HTTP requests during the image build operation. Provide a positive integer value for the number of
seconds.
type: int
path:
description:
- Use with state 'present' to build an image. Will be the path to a directory containing the context and
Dockerfile for building an image.
type: path
required: yes
pull:
description:
- When building an image downloads any updates to the FROM image in Dockerfile.
type: bool
default: yes
rm:
description:
- Remove intermediate containers after build.
type: bool
default: yes
network:
description:
- The network to use for C(RUN) build instructions.
type: str
nocache:
description:
- Do not use cache when building an image.
type: bool
default: no
args:
description:
- Provide a dictionary of C(key:value) build arguments that map to Dockerfile ARG directive.
- Docker expects the value to be a string. For convenience any non-string values will be converted to strings.
- Requires Docker API >= 1.21.
type: dict
container_limits:
description:
- A dictionary of limits applied to each container created by the build process.
type: dict
suboptions:
memory:
description:
- Set memory limit for build.
type: int
memswap:
description:
- Total memory (memory + swap), -1 to disable swap.
type: int
cpushares:
description:
- CPU shares (relative weight).
type: int
cpusetcpus:
description:
- CPUs in which to allow execution, e.g., "0-3", "0,1".
type: str
version_added: "2.8"
archive_path: archive_path:
description: description:
- Use with state C(present) to archive an image to a .tar file. - Use with state C(present) to archive an image to a .tar file.
type: path type: path
version_added: "2.1" version_added: "2.1"
cache_from:
description:
- List of image names to consider as cache source.
type: list
version_added: "2.8"
load_path: load_path:
description: description:
- Use with state C(present) to load an image from a .tar file. - Use with state C(present) to load an image from a .tar file.
- Set I(source) to C(load) if you want to load the image. The option will
be set automatically before Ansible 2.12 if this option is used (except
if I(path) is specified as well, in which case building will take precedence).
From Ansible 2.12 on, you have to set I(source) to C(load).
type: path type: path
version_added: "2.2" version_added: "2.2"
dockerfile: dockerfile:
description: description:
- Use with state C(present) to provide an alternate name for the Dockerfile to use when building an image. - Use with state C(present) to provide an alternate name for the Dockerfile to use when building an image.
- Please use I(build.dockerfile) instead. This option will be removed in Ansible 2.12.
type: str type: str
version_added: "2.0" version_added: "2.0"
force: force:
description: description:
- Use with state I(absent) to un-tag and remove all images matching the specified name. Use with state - Use with state I(absent) to un-tag and remove all images matching the specified name. Use with state
C(present) to build, load or pull an image when the image already exists. C(present) to build, load or pull an image when the image already exists. Also use with state C(present)
to force tagging an image.
- Please stop using this option, and use the more specialized force options
I(force_source), I(force_absent) and I(force_tag) instead.
- This option will be removed in Ansible 2.12.
type: bool type: bool
default: no
version_added: "2.1" version_added: "2.1"
force_source:
description:
- Use with state C(present) to build, load or pull an image (depending on the
value of the I(source) option) when the image already exists.
type: bool
default: false
version_added: "2.8"
force_absent:
description:
- Use with state I(absent) to un-tag and remove all images matching the specified name.
type: bool
default: false
version_added: "2.8"
force_tag:
description:
- Use with state C(present) to force tagging an image.
- Please stop using this option, and use the more specialized force options
I(force_source), I(force_absent) and I(force_tag) instead.
- This option will be removed in Ansible 2.12.
type: bool
default: false
version_added: "2.8"
http_timeout: http_timeout:
description: description:
- Timeout for HTTP requests during the image build operation. Provide a positive integer value for the number of - Timeout for HTTP requests during the image build operation. Provide a positive integer value for the number of
seconds. seconds.
- Please use I(build.http_timeout) instead. This option will be removed in Ansible 2.12.
type: int type: int
version_added: "2.1" version_added: "2.1"
name: name:
@ -69,12 +189,17 @@ options:
description: description:
- Use with state 'present' to build an image. Will be the path to a directory containing the context and - Use with state 'present' to build an image. Will be the path to a directory containing the context and
Dockerfile for building an image. Dockerfile for building an image.
- Set I(source) to C(build) if you want to build the image. The option will
be set automatically before Ansible 2.12 if this option is used. From Ansible 2.12
on, you have to set I(source) to C(build).
- Please use I(build.path) instead. This option will be removed in Ansible 2.12.
type: path type: path
aliases: aliases:
- build_path - build_path
pull: pull:
description: description:
- When building an image downloads any updates to the FROM image in Dockerfile. - When building an image downloads any updates to the FROM image in Dockerfile.
- Please use I(build.pull) instead. This option will be removed in Ansible 2.12.
type: bool type: bool
default: yes default: yes
version_added: "2.1" version_added: "2.1"
@ -87,17 +212,14 @@ options:
rm: rm:
description: description:
- Remove intermediate containers after build. - Remove intermediate containers after build.
- Please use I(build.rm) instead. This option will be removed in Ansible 2.12.
type: bool type: bool
default: yes default: yes
version_added: "2.1" version_added: "2.1"
network:
description:
- The network to use for C(RUN) build instructions.
type: str
version_added: "2.8"
nocache: nocache:
description: description:
- Do not use cache when building an image. - Do not use cache when building an image.
- Please use I(build.nocache) instead. This option will be removed in Ansible 2.12.
type: bool type: bool
default: no default: no
repository: repository:
@ -136,11 +258,13 @@ options:
- Provide a dictionary of C(key:value) build arguments that map to Dockerfile ARG directive. - Provide a dictionary of C(key:value) build arguments that map to Dockerfile ARG directive.
- Docker expects the value to be a string. For convenience any non-string values will be converted to strings. - Docker expects the value to be a string. For convenience any non-string values will be converted to strings.
- Requires Docker API >= 1.21. - Requires Docker API >= 1.21.
- Please use I(build.args) instead. This option will be removed in Ansible 2.12.
type: dict type: dict
version_added: "2.2" version_added: "2.2"
container_limits: container_limits:
description: description:
- A dictionary of limits applied to each container created by the build process. - A dictionary of limits applied to each container created by the build process.
- Please use I(build.container_limits) instead. This option will be removed in Ansible 2.12.
type: dict type: dict
suboptions: suboptions:
memory: memory:
@ -194,26 +318,30 @@ EXAMPLES = '''
- name: pull an image - name: pull an image
docker_image: docker_image:
name: pacur/centos-7 name: pacur/centos-7
source: pull
- name: Tag and push to docker hub - name: Tag and push to docker hub
docker_image: docker_image:
name: pacur/centos-7:56 name: pacur/centos-7:56
repository: dcoppenhagan/myimage:7.56 repository: dcoppenhagan/myimage:7.56
push: yes push: yes
source: local
- name: Tag and push to local registry - name: Tag and push to local registry
docker_image: docker_image:
# Image will be centos:7 # Image will be centos:7
name: centos name: centos
# Will be pushed to localhost:5000/centos:7 # Will be pushed to localhost:5000/centos:7
repository: localhost:5000/centos repository: localhost:5000/centos
tag: 7 tag: 7
push: yes push: yes
source: local
- name: Add tag latest to image - name: Add tag latest to image
docker_image: docker_image:
name: myimage:7.1.2 name: myimage:7.1.2
repository: myimage:latest repository: myimage:latest
source: local
- name: Remove image - name: Remove image
docker_image: docker_image:
@ -223,16 +351,19 @@ EXAMPLES = '''
- name: Build an image and push it to a private repo - name: Build an image and push it to a private repo
docker_image: docker_image:
path: ./sinatra build:
path: ./sinatra
name: registry.ansible.com/chouseknecht/sinatra name: registry.ansible.com/chouseknecht/sinatra
tag: v1 tag: v1
push: yes push: yes
source: build
- name: Archive image - name: Archive image
docker_image: docker_image:
name: registry.ansible.com/chouseknecht/sinatra name: registry.ansible.com/chouseknecht/sinatra
tag: v1 tag: v1
archive_path: my_sinatra.tar archive_path: my_sinatra.tar
source: local
- name: Load image from archive and push to a private registry - name: Load image from archive and push to a private registry
docker_image: docker_image:
@ -240,23 +371,28 @@ EXAMPLES = '''
tag: v1 tag: v1
push: yes push: yes
load_path: my_sinatra.tar load_path: my_sinatra.tar
source: load
- name: Build image and with buildargs - name: Build image and with build args
docker_image: docker_image:
path: /path/to/build/dir name: myimage
name: myimage build:
buildargs: path: /path/to/build/dir
log_volume: /var/log/myapp args:
listen_port: 8080 log_volume: /var/log/myapp
listen_port: 8080
source: build
- name: Build image using cache source - name: Build image using cache source
docker_image: docker_image:
name: myimage:latest name: myimage:latest
path: /path/to/build/dir build:
# Use as cache source for building myimage path: /path/to/build/dir
cache_from: # Use as cache source for building myimage
- nginx:latest cache_from:
- alpine:3.8 - nginx:latest
- alpine:3.8
source: build
''' '''
RETURN = ''' RETURN = '''
@ -296,24 +432,28 @@ class ImageManager(DockerBaseClass):
parameters = self.client.module.params parameters = self.client.module.params
self.check_mode = self.client.check_mode self.check_mode = self.client.check_mode
self.source = parameters['source']
build = parameters['build'] or dict()
self.archive_path = parameters.get('archive_path') self.archive_path = parameters.get('archive_path')
self.cache_from = parameters.get('cache_from') self.cache_from = build.get('cache_from')
self.container_limits = parameters.get('container_limits') self.container_limits = build.get('container_limits')
self.dockerfile = parameters.get('dockerfile') self.dockerfile = build.get('dockerfile')
self.force = parameters.get('force') self.force_source = parameters.get('force_source')
self.force_absent = parameters.get('force_absent')
self.force_tag = parameters.get('force_tag')
self.load_path = parameters.get('load_path') self.load_path = parameters.get('load_path')
self.name = parameters.get('name') self.name = parameters.get('name')
self.network = parameters.get('network') self.network = build.get('network')
self.nocache = parameters.get('nocache') self.nocache = build.get('nocache')
self.path = parameters.get('path') self.build_path = build.get('path')
self.pull = parameters.get('pull') self.pull = build.get('pull')
self.repository = parameters.get('repository') self.repository = parameters.get('repository')
self.rm = parameters.get('rm') self.rm = build.get('rm')
self.state = parameters.get('state') self.state = parameters.get('state')
self.tag = parameters.get('tag') self.tag = parameters.get('tag')
self.http_timeout = parameters.get('http_timeout') self.http_timeout = build.get('http_timeout')
self.push = parameters.get('push') self.push = parameters.get('push')
self.buildargs = parameters.get('buildargs') self.buildargs = build.get('args')
# If name contains a tag, it takes precedence over tag parameter. # If name contains a tag, it takes precedence over tag parameter.
if not is_image_name_id(self.name): if not is_image_name_id(self.name):
@ -322,7 +462,7 @@ class ImageManager(DockerBaseClass):
self.name = repo self.name = repo
self.tag = repo_tag self.tag = repo_tag
if self.state in ['present', 'build']: if self.state == 'present':
self.present() self.present()
elif self.state == 'absent': elif self.state == 'absent':
self.absent() self.absent()
@ -339,20 +479,20 @@ class ImageManager(DockerBaseClass):
''' '''
image = self.client.find_image(name=self.name, tag=self.tag) image = self.client.find_image(name=self.name, tag=self.tag)
if not image or self.force: if not image or self.force_source:
if self.path: if self.source == 'build':
# Build the image # Build the image
if not os.path.isdir(self.path): if not os.path.isdir(self.build_path):
self.fail("Requested build path %s could not be found or you do not have access." % self.path) self.fail("Requested build path %s could not be found or you do not have access." % self.build_path)
image_name = self.name image_name = self.name
if self.tag: if self.tag:
image_name = "%s:%s" % (self.name, self.tag) image_name = "%s:%s" % (self.name, self.tag)
self.log("Building image %s" % image_name) self.log("Building image %s" % image_name)
self.results['actions'].append("Built image %s from %s" % (image_name, self.path)) self.results['actions'].append("Built image %s from %s" % (image_name, self.build_path))
self.results['changed'] = True self.results['changed'] = True
if not self.check_mode: if not self.check_mode:
self.results['image'] = self.build_image() self.results['image'] = self.build_image()
elif self.load_path: elif self.source == 'load':
# Load the image from an archive # Load the image from an archive
if not os.path.isfile(self.load_path): if not os.path.isfile(self.load_path):
self.fail("Error loading image %s. Specified path %s does not exist." % (self.name, self.fail("Error loading image %s. Specified path %s does not exist." % (self.name,
@ -364,12 +504,18 @@ class ImageManager(DockerBaseClass):
self.results['changed'] = True self.results['changed'] = True
if not self.check_mode: if not self.check_mode:
self.results['image'] = self.load_image() self.results['image'] = self.load_image()
else: elif self.source == 'pull':
# pull the image # pull the image
self.results['actions'].append('Pulled image %s:%s' % (self.name, self.tag)) self.results['actions'].append('Pulled image %s:%s' % (self.name, self.tag))
self.results['changed'] = True self.results['changed'] = True
if not self.check_mode: if not self.check_mode:
self.results['image'], dummy = self.client.pull_image(self.name, tag=self.tag) self.results['image'], dummy = self.client.pull_image(self.name, tag=self.tag)
elif self.source == 'local':
if image is None:
name = self.name
if self.tag:
name = "%s:%s" % (self.name, self.tag)
self.client.fail('Cannot find the image %s locally.' % name)
if not self.check_mode and image and image['Id'] == self.results['image']['Id']: if not self.check_mode and image and image['Id'] == self.results['image']['Id']:
self.results['changed'] = False self.results['changed'] = False
@ -379,7 +525,7 @@ class ImageManager(DockerBaseClass):
if self.push and not self.repository: if self.push and not self.repository:
self.push_image(self.name, self.tag) self.push_image(self.name, self.tag)
elif self.repository: elif self.repository:
self.tag_image(self.name, self.tag, self.repository, force=self.force, push=self.push) self.tag_image(self.name, self.tag, self.repository, push=self.push)
def absent(self): def absent(self):
''' '''
@ -397,7 +543,7 @@ class ImageManager(DockerBaseClass):
if image: if image:
if not self.check_mode: if not self.check_mode:
try: try:
self.client.remove_image(name, force=self.force) self.client.remove_image(name, force=self.force_absent)
except Exception as exc: except Exception as exc:
self.fail("Error removing image %s - %s" % (name, str(exc))) self.fail("Error removing image %s - %s" % (name, str(exc)))
@ -491,14 +637,13 @@ class ImageManager(DockerBaseClass):
self.results['image'] = dict() self.results['image'] = dict()
self.results['image']['push_status'] = status self.results['image']['push_status'] = status
def tag_image(self, name, tag, repository, force=False, push=False): def tag_image(self, name, tag, repository, push=False):
''' '''
Tag an image into a repository. Tag an image into a repository.
:param name: name of the image. required. :param name: name of the image. required.
:param tag: image tag. :param tag: image tag.
:param repository: path to the repository. required. :param repository: path to the repository. required.
:param force: bool. force tagging, even it image already exists with the repository path.
:param push: bool. push the image once it's tagged. :param push: bool. push the image once it's tagged.
:return: None :return: None
''' '''
@ -511,7 +656,7 @@ class ImageManager(DockerBaseClass):
found = 'found' if image else 'not found' found = 'found' if image else 'not found'
self.log("image %s was %s" % (repo, found)) self.log("image %s was %s" % (repo, found))
if not image or force: if not image or self.force_tag:
self.log("tagging %s:%s to %s:%s" % (name, tag, repo, repo_tag)) self.log("tagging %s:%s to %s:%s" % (name, tag, repo, repo_tag))
self.results['changed'] = True self.results['changed'] = True
self.results['actions'].append("Tagged image %s:%s to %s:%s" % (name, tag, repo, repo_tag)) self.results['actions'].append("Tagged image %s:%s to %s:%s" % (name, tag, repo, repo_tag))
@ -541,7 +686,7 @@ class ImageManager(DockerBaseClass):
:return: image dict :return: image dict
''' '''
params = dict( params = dict(
path=self.path, path=self.build_path,
tag=self.name, tag=self.name,
rm=self.rm, rm=self.rm,
nocache=self.nocache, nocache=self.nocache,
@ -614,39 +759,70 @@ class ImageManager(DockerBaseClass):
def main(): def main():
argument_spec = dict( argument_spec = dict(
source=dict(type='str', choices=['build', 'load', 'pull', 'local']),
build=dict(type='dict', suboptions=dict(
cache_from=dict(type='list', elements='str'),
container_limits=dict(type='dict', options=dict(
memory=dict(type='int'),
memswap=dict(type='int'),
cpushares=dict(type='int'),
cpusetcpus=dict(type='str'),
)),
dockerfile=dict(type='str'),
http_timeout=dict(type='int'),
network=dict(type='str'),
nocache=dict(type='bool', default=False),
path=dict(type='path', required=True),
pull=dict(type='bool', default=True),
rm=dict(type='bool', default=True),
args=dict(type='dict'),
)),
archive_path=dict(type='path'), archive_path=dict(type='path'),
cache_from=dict(type='list', elements='str'),
container_limits=dict(type='dict', options=dict( container_limits=dict(type='dict', options=dict(
memory=dict(type='int'), memory=dict(type='int'),
memswap=dict(type='int'), memswap=dict(type='int'),
cpushares=dict(type='int'), cpushares=dict(type='int'),
cpusetcpus=dict(type='str'), cpusetcpus=dict(type='str'),
)), ), removedin_version='2.12'),
dockerfile=dict(type='str'), dockerfile=dict(type='str', removedin_version='2.12'),
force=dict(type='bool', default=False), force=dict(type='bool', removed_in_version='2.12'),
http_timeout=dict(type='int'), force_source=dict(type='bool', default=False),
force_absent=dict(type='bool', default=False),
force_tag=dict(type='bool', default=False),
http_timeout=dict(type='int', removedin_version='2.12'),
load_path=dict(type='path'), load_path=dict(type='path'),
name=dict(type='str', required=True), name=dict(type='str', required=True),
network=dict(type='str'), nocache=dict(type='bool', default=False, removedin_version='2.12'),
nocache=dict(type='bool', default=False), path=dict(type='path', aliases=['build_path'], removedin_version='2.12'),
path=dict(type='path', aliases=['build_path']), pull=dict(type='bool', default=True, removedin_version='2.12'),
pull=dict(type='bool', default=True),
push=dict(type='bool', default=False), push=dict(type='bool', default=False),
repository=dict(type='str'), repository=dict(type='str'),
rm=dict(type='bool', default=True), rm=dict(type='bool', default=True, removedin_version='2.12'),
state=dict(type='str', default='present', choices=['absent', 'present', 'build']), state=dict(type='str', default='present', choices=['absent', 'present', 'build']),
tag=dict(type='str', default='latest'), tag=dict(type='str', default='latest'),
use_tls=dict(type='str', choices=['no', 'encrypt', 'verify'], removed_in_version='2.11'), use_tls=dict(type='str', choices=['no', 'encrypt', 'verify'], removed_in_version='2.11'),
buildargs=dict(type='dict'), buildargs=dict(type='dict', removedin_version='2.12'),
) )
option_minimal_versions = dict( required_if = [
cache_from=dict(docker_py_version='2.1.0', docker_api_version='1.25'), # ('state', 'present', ['source']), -- enable in Ansible 2.12.
network=dict(docker_py_version='2.4.0', docker_api_version='1.25'), # ('source', 'build', ['build']), -- enable in Ansible 2.12.
) ('source', 'load', ['load_path']),
]
def detect_build_cache_from(client):
return bool(client.params['build'] and client.params['build']['cache_from'] is not None)
def detect_build_network(client):
return bool(client.params['build'] and client.params['build']['network'] is not None)
option_minimal_versions = dict()
option_minimal_versions["build.cache_from"] = dict(docker_py_version='2.1.0', docker_api_version='1.25', detect_usage=detect_build_cache_from)
option_minimal_versions["build.network"] = dict(docker_py_version='2.4.0', docker_api_version='1.25', detect_usage=detect_build_network)
client = AnsibleDockerClient( client = AnsibleDockerClient(
argument_spec=argument_spec, argument_spec=argument_spec,
required_if=required_if,
supports_check_mode=True, supports_check_mode=True,
min_docker_version='1.8.0', min_docker_version='1.8.0',
min_docker_api_version='1.20', min_docker_api_version='1.20',
@ -657,11 +833,60 @@ def main():
client.module.warn('The "build" state has been deprecated for a long time ' client.module.warn('The "build" state has been deprecated for a long time '
'and will be removed in Ansible 2.11. Please use ' 'and will be removed in Ansible 2.11. Please use '
'"present", which has the same meaning as "build".') '"present", which has the same meaning as "build".')
client.module.params['state'] = 'present'
if client.module.params['use_tls']: if client.module.params['use_tls']:
client.module.warn('The "use_tls" option has been deprecated for a long time ' client.module.warn('The "use_tls" option has been deprecated for a long time '
'and will be removed in Ansible 2.11. Please use the' 'and will be removed in Ansible 2.11. Please use the'
'"tls" and "tls_verify" options instead.') '"tls" and "tls_verify" options instead.')
build_options = dict(
container_limits='container_limits',
dockerfile='dockerfile',
http_timeout='http_timeout',
nocache='nocache',
path='path',
pull='pull',
rm='rm',
buildargs='args',
)
for option, build_option in build_options.items():
default_value = None
if option in ('pull', 'rm'):
default_value = True
elif option in ('nocache', ):
default_value = False
if client.module.params[option] != default_value:
if client.module.params['build'] is None:
client.module.params['build'] = dict()
if client.module.params['build'].get(build_option) != default_value:
client.fail('Cannot specify both %s and build.%s!' % (option, build_option))
client.module.params['build'][build_option] = client.module.params[option]
client.module.warn('Please specify build.%s instead of %s. The %s option '
'has been renamed and will be removed in Ansible 2.12.' % (build_option, option, option))
if client.module.params['source'] == 'build' and \
(not client.module.params['build'] or not client.module.params['build'].get('path')):
client.module.fail('If "source" is set to "build", the "build.path" option must be specified.')
if client.module.params['state'] == 'present' and client.module.params['source'] is None:
# Autodetection. To be removed in Ansible 2.12.
if (client.module.params['build'] or dict()).get('path'):
client.module.params['source'] = 'build'
elif client.module.params['load_path']:
client.module.params['source'] = 'load'
else:
client.module.params['source'] = 'pull'
client.module.warn('The value of the "source" option was determined to be "%s". '
'Please set the "source" option explicitly. Autodetection will '
'be removed in Ansible 2.12.' % client.module.params['source'])
if client.module.params['force']:
client.module.params['force_source'] = True
client.module.params['force_absent'] = True
client.module.params['force_tag'] = True
client.module.warn('The "force" option will be removed in Ansible 2.12. Please '
'use the "force_source", "force_absent" or "force_tag" option '
'instead, depending on what you want to force.')
results = dict( results = dict(
changed=False, changed=False,
actions=[], actions=[],

View file

@ -7,6 +7,7 @@
docker_image: docker_image:
name: "hello-world:latest" name: "hello-world:latest"
state: absent state: absent
force_absent: yes
register: absent_1 register: absent_1
- name: Make sure image is not there (idempotency) - name: Make sure image is not there (idempotency)
@ -23,14 +24,14 @@
docker_image: docker_image:
name: "hello-world:latest" name: "hello-world:latest"
state: present state: present
pull: no source: pull
register: present_1 register: present_1
- name: Make sure image is there (idempotent) - name: Make sure image is there (idempotent)
docker_image: docker_image:
name: "hello-world:latest" name: "hello-world:latest"
state: present state: present
pull: yes source: pull
register: present_2 register: present_2
- assert: - assert:
@ -81,12 +82,14 @@
docker_image: docker_image:
name: "{{ registry_address }}/test/hello-world:latest" name: "{{ registry_address }}/test/hello-world:latest"
state: absent state: absent
force_absent: yes
- name: Push image to test registry - name: Push image to test registry
docker_image: docker_image:
name: "hello-world:latest" name: "hello-world:latest"
repository: "{{ registry_address }}/test/hello-world" repository: "{{ registry_address }}/test/hello-world"
push: yes push: yes
source: local
register: push_1 register: push_1
- name: Push image to test registry (idempotent) - name: Push image to test registry (idempotent)
@ -94,6 +97,7 @@
name: "hello-world:latest" name: "hello-world:latest"
repository: "{{ registry_address }}/test/hello-world" repository: "{{ registry_address }}/test/hello-world"
push: yes push: yes
source: local
register: push_2 register: push_2
- name: Push image to test registry (force, still idempotent) - name: Push image to test registry (force, still idempotent)
@ -119,6 +123,7 @@
docker_image: docker_image:
name: "{{ registry_address }}/test/hello-world:latest" name: "{{ registry_address }}/test/hello-world:latest"
state: absent state: absent
force_absent: yes
- name: Get facts of local image (absent) - name: Get facts of local image (absent)
docker_image_facts: docker_image_facts:
@ -129,12 +134,14 @@
docker_image: docker_image:
name: "{{ registry_address }}/test/hello-world:latest" name: "{{ registry_address }}/test/hello-world:latest"
state: present state: present
source: pull
register: pull_1 register: pull_1
- name: Pull image from test registry (idempotency) - name: Pull image from test registry (idempotency)
docker_image: docker_image:
name: "{{ registry_address }}/test/hello-world:latest" name: "{{ registry_address }}/test/hello-world:latest"
state: present state: present
source: pull
register: pull_2 register: pull_2
- name: Get facts of local image (present) - name: Get facts of local image (present)

View file

@ -9,33 +9,38 @@
inames: "{{ inames }} + [iname, iname_1]" inames: "{{ inames }} + [iname, iname_1]"
#################################################################### ####################################################################
## buildargs ####################################################### ## build.args ######################################################
#################################################################### ####################################################################
- name: buildargs - name: buildargs
docker_image: docker_image:
path: "{{ role_path }}/files"
name: "{{ iname }}" name: "{{ iname }}"
buildargs: build:
TEST1: val1 path: "{{ role_path }}/files"
TEST2: val2 args:
TEST3: "True" TEST1: val1
TEST2: val2
TEST3: "True"
source: build
register: buildargs_1 register: buildargs_1
- name: buildargs (idempotency) - name: buildargs (idempotency)
docker_image: docker_image:
path: "{{ role_path }}/files"
name: "{{ iname }}" name: "{{ iname }}"
buildargs: build:
TEST1: val1 path: "{{ role_path }}/files"
TEST2: val2 args:
TEST3: "True" TEST1: val1
TEST2: val2
TEST3: "True"
source: build
register: buildargs_2 register: buildargs_2
- name: cleanup - name: cleanup
docker_image: docker_image:
name: "{{ iname }}" name: "{{ iname }}"
state: absent state: absent
force_absent: yes
- assert: - assert:
that: that:
@ -55,26 +60,31 @@
- name: container_limits (Failed due to min memory limit) - name: container_limits (Failed due to min memory limit)
docker_image: docker_image:
path: "{{ role_path }}/files"
name: "{{ iname }}" name: "{{ iname }}"
container_limits: build:
memory: 4000 path: "{{ role_path }}/files"
container_limits:
memory: 4000
source: build
ignore_errors: yes ignore_errors: yes
register: container_limits_1 register: container_limits_1
- name: container_limits - name: container_limits
docker_image: docker_image:
path: "{{ role_path }}/files"
name: "{{ iname }}" name: "{{ iname }}"
container_limits: build:
memory: 5000000 path: "{{ role_path }}/files"
memswap: 7000000 container_limits:
memory: 5000000
memswap: 7000000
source: build
register: container_limits_2 register: container_limits_2
- name: cleanup - name: cleanup
docker_image: docker_image:
name: "{{ iname }}" name: "{{ iname }}"
state: absent state: absent
force_absent: yes
- assert: - assert:
that: that:
@ -93,15 +103,18 @@
- name: dockerfile - name: dockerfile
docker_image: docker_image:
path: "{{ role_path }}/files"
name: "{{ iname }}" name: "{{ iname }}"
dockerfile: "MyDockerfile" build:
path: "{{ role_path }}/files"
dockerfile: "MyDockerfile"
source: build
register: dockerfile_1 register: dockerfile_1
- name: cleanup - name: cleanup
docker_image: docker_image:
name: "{{ iname }}" name: "{{ iname }}"
state: absent state: absent
force_absent: yes
- assert: - assert:
that: that:
@ -116,19 +129,24 @@
docker_image: docker_image:
name: "{{ registry_address }}/test/{{ iname }}:latest" name: "{{ registry_address }}/test/{{ iname }}:latest"
state: absent state: absent
force_absent: yes
- name: repository - name: repository
docker_image: docker_image:
name: "{{ iname }}" name: "{{ iname }}"
path: "{{ role_path }}/files" build:
path: "{{ role_path }}/files"
repository: "{{ registry_address }}/test/{{ iname }}" repository: "{{ registry_address }}/test/{{ iname }}"
source: build
register: repository_1 register: repository_1
- name: repository (idempotent) - name: repository (idempotent)
docker_image: docker_image:
name: "{{ iname }}" name: "{{ iname }}"
path: "{{ role_path }}/files" build:
path: "{{ role_path }}/files"
repository: "{{ registry_address }}/test/{{ iname }}" repository: "{{ registry_address }}/test/{{ iname }}"
source: build
register: repository_2 register: repository_2
- assert: - assert:
@ -145,7 +163,7 @@
docker_image: docker_image:
name: "{{ registry_address }}/test/{{ iname }}:latest" name: "{{ registry_address }}/test/{{ iname }}:latest"
state: absent state: absent
force: yes force_absent: yes
- assert: - assert:
that: that:
@ -157,29 +175,36 @@
- name: Build an image - name: Build an image
docker_image: docker_image:
path: "{{ role_path }}/files"
name: "{{ iname }}" name: "{{ iname }}"
build:
path: "{{ role_path }}/files"
source: build
- name: force (changed) - name: force (changed)
docker_image: docker_image:
path: "{{ role_path }}/files"
name: "{{ iname }}" name: "{{ iname }}"
dockerfile: "MyDockerfile" build:
force: yes path: "{{ role_path }}/files"
dockerfile: "MyDockerfile"
source: build
force_source: yes
register: force_1 register: force_1
- name: force (unchanged) - name: force (unchanged)
docker_image: docker_image:
path: "{{ role_path }}/files"
name: "{{ iname }}" name: "{{ iname }}"
dockerfile: "MyDockerfile" build:
force: yes path: "{{ role_path }}/files"
dockerfile: "MyDockerfile"
source: build
force_source: yes
register: force_2 register: force_2
- name: cleanup - name: cleanup
docker_image: docker_image:
name: "{{ iname }}" name: "{{ iname }}"
state: absent state: absent
force_absent: yes
- assert: - assert:
that: that:
@ -194,23 +219,27 @@
docker_image: docker_image:
name: "hello-world:latest" name: "hello-world:latest"
archive_path: image.tar archive_path: image.tar
source: pull
register: archive_image register: archive_image
- name: remove image - name: remove image
docker_image: docker_image:
name: "hello-world:latest" name: "hello-world:latest"
state: absent state: absent
force_absent: yes
- name: load image (changed) - name: load image (changed)
docker_image: docker_image:
name: "hello-world:latest" name: "hello-world:latest"
load_path: image.tar load_path: image.tar
source: load
register: load_image register: load_image
- name: load image (idempotency) - name: load image (idempotency)
docker_image: docker_image:
name: "hello-world:latest" name: "hello-world:latest"
load_path: image.tar load_path: image.tar
source: load
register: load_image_1 register: load_image_1
- assert: - assert:
@ -226,19 +255,24 @@
- name: Build image - name: Build image
docker_image: docker_image:
name: "{{ iname }}" name: "{{ iname }}"
path: "{{ role_path }}/files" build:
path: "{{ role_path }}/files"
source: build
register: path_1 register: path_1
- name: Build image(idempotency) - name: Build image (idempotency)
docker_image: docker_image:
name: "{{ iname }}" name: "{{ iname }}"
path: "{{ role_path }}/files" build:
path: "{{ role_path }}/files"
source: build
register: path_2 register: path_2
- name: cleanup - name: cleanup
docker_image: docker_image:
name: "{{ iname }}" name: "{{ iname }}"
state: absent state: absent
force_absent: yes
- assert: - assert:
that: that: