From 35e7fb776a9047158db3afdc9b169003f309763f Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 14 Mar 2019 10:46:38 +0100 Subject: [PATCH] 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. --- .../49787-docker_image-cache_from.yaml | 2 +- changelogs/fragments/52894-docker_image.yaml | 4 + .../modules/cloud/docker/docker_image.py | 369 ++++++++++++++---- .../docker_image/tasks/tests/basic.yml | 11 +- .../docker_image/tasks/tests/options.yml | 100 +++-- 5 files changed, 378 insertions(+), 108 deletions(-) create mode 100644 changelogs/fragments/52894-docker_image.yaml diff --git a/changelogs/fragments/49787-docker_image-cache_from.yaml b/changelogs/fragments/49787-docker_image-cache_from.yaml index 2ad67ef3656..cc056c4d0e7 100644 --- a/changelogs/fragments/49787-docker_image-cache_from.yaml +++ b/changelogs/fragments/49787-docker_image-cache_from.yaml @@ -1,2 +1,2 @@ minor_changes: -- "docker_image - Add ``cache_from`` option." +- "docker_image - Add ``build.cache_from`` option." diff --git a/changelogs/fragments/52894-docker_image.yaml b/changelogs/fragments/52894-docker_image.yaml new file mode 100644 index 00000000000..8c0eff722ef --- /dev/null +++ b/changelogs/fragments/52894-docker_image.yaml @@ -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." diff --git a/lib/ansible/modules/cloud/docker/docker_image.py b/lib/ansible/modules/cloud/docker/docker_image.py index f51f0923508..d1d1776abbb 100644 --- a/lib/ansible/modules/cloud/docker/docker_image.py +++ b/lib/ansible/modules/cloud/docker/docker_image.py @@ -21,41 +21,161 @@ short_description: Manage docker images. version_added: "1.5" description: - - 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. + - 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. + - 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: + 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: description: - Use with state C(present) to archive an image to a .tar file. type: path version_added: "2.1" - cache_from: - description: - - List of image names to consider as cache source. - type: list - version_added: "2.8" load_path: description: - 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 version_added: "2.2" dockerfile: description: - 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 version_added: "2.0" force: description: - 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 - default: no 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: description: - Timeout for HTTP requests during the image build operation. Provide a positive integer value for the number of seconds. + - Please use I(build.http_timeout) instead. This option will be removed in Ansible 2.12. type: int version_added: "2.1" name: @@ -69,12 +189,17 @@ options: 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. + - 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 aliases: - build_path pull: description: - 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 default: yes version_added: "2.1" @@ -87,17 +212,14 @@ options: rm: description: - Remove intermediate containers after build. + - Please use I(build.rm) instead. This option will be removed in Ansible 2.12. type: bool default: yes version_added: "2.1" - network: - description: - - The network to use for C(RUN) build instructions. - type: str - version_added: "2.8" nocache: description: - 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 default: no repository: @@ -136,11 +258,13 @@ options: - 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. + - Please use I(build.args) instead. This option will be removed in Ansible 2.12. type: dict version_added: "2.2" container_limits: description: - 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 suboptions: memory: @@ -194,26 +318,30 @@ EXAMPLES = ''' - name: pull an image docker_image: name: pacur/centos-7 + source: pull - name: Tag and push to docker hub docker_image: name: pacur/centos-7:56 repository: dcoppenhagan/myimage:7.56 push: yes + source: local - name: Tag and push to local registry docker_image: - # Image will be centos:7 - name: centos - # Will be pushed to localhost:5000/centos:7 - repository: localhost:5000/centos - tag: 7 - push: yes + # Image will be centos:7 + name: centos + # Will be pushed to localhost:5000/centos:7 + repository: localhost:5000/centos + tag: 7 + push: yes + source: local - name: Add tag latest to image docker_image: name: myimage:7.1.2 repository: myimage:latest + source: local - name: Remove image docker_image: @@ -223,16 +351,19 @@ EXAMPLES = ''' - name: Build an image and push it to a private repo docker_image: - path: ./sinatra + build: + path: ./sinatra name: registry.ansible.com/chouseknecht/sinatra tag: v1 push: yes + source: build - name: Archive image docker_image: name: registry.ansible.com/chouseknecht/sinatra tag: v1 archive_path: my_sinatra.tar + source: local - name: Load image from archive and push to a private registry docker_image: @@ -240,23 +371,28 @@ EXAMPLES = ''' tag: v1 push: yes load_path: my_sinatra.tar + source: load -- name: Build image and with buildargs +- name: Build image and with build args docker_image: - path: /path/to/build/dir - name: myimage - buildargs: - log_volume: /var/log/myapp - listen_port: 8080 + name: myimage + build: + path: /path/to/build/dir + args: + log_volume: /var/log/myapp + listen_port: 8080 + source: build - name: Build image using cache source docker_image: name: myimage:latest - path: /path/to/build/dir - # Use as cache source for building myimage - cache_from: - - nginx:latest - - alpine:3.8 + build: + path: /path/to/build/dir + # Use as cache source for building myimage + cache_from: + - nginx:latest + - alpine:3.8 + source: build ''' RETURN = ''' @@ -296,24 +432,28 @@ class ImageManager(DockerBaseClass): parameters = self.client.module.params self.check_mode = self.client.check_mode + self.source = parameters['source'] + build = parameters['build'] or dict() self.archive_path = parameters.get('archive_path') - self.cache_from = parameters.get('cache_from') - self.container_limits = parameters.get('container_limits') - self.dockerfile = parameters.get('dockerfile') - self.force = parameters.get('force') + self.cache_from = build.get('cache_from') + self.container_limits = build.get('container_limits') + self.dockerfile = build.get('dockerfile') + 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.name = parameters.get('name') - self.network = parameters.get('network') - self.nocache = parameters.get('nocache') - self.path = parameters.get('path') - self.pull = parameters.get('pull') + self.network = build.get('network') + self.nocache = build.get('nocache') + self.build_path = build.get('path') + self.pull = build.get('pull') self.repository = parameters.get('repository') - self.rm = parameters.get('rm') + self.rm = build.get('rm') self.state = parameters.get('state') 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.buildargs = parameters.get('buildargs') + self.buildargs = build.get('args') # If name contains a tag, it takes precedence over tag parameter. if not is_image_name_id(self.name): @@ -322,7 +462,7 @@ class ImageManager(DockerBaseClass): self.name = repo self.tag = repo_tag - if self.state in ['present', 'build']: + if self.state == 'present': self.present() elif self.state == 'absent': self.absent() @@ -339,20 +479,20 @@ class ImageManager(DockerBaseClass): ''' image = self.client.find_image(name=self.name, tag=self.tag) - if not image or self.force: - if self.path: + if not image or self.force_source: + if self.source == 'build': # Build the image - if not os.path.isdir(self.path): - self.fail("Requested build path %s could not be found or you do not have access." % 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.build_path) image_name = self.name if self.tag: image_name = "%s:%s" % (self.name, self.tag) 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 if not self.check_mode: self.results['image'] = self.build_image() - elif self.load_path: + elif self.source == 'load': # Load the image from an archive if not os.path.isfile(self.load_path): 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 if not self.check_mode: self.results['image'] = self.load_image() - else: + elif self.source == 'pull': # pull the image self.results['actions'].append('Pulled image %s:%s' % (self.name, self.tag)) self.results['changed'] = True if not self.check_mode: 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']: self.results['changed'] = False @@ -379,7 +525,7 @@ class ImageManager(DockerBaseClass): if self.push and not self.repository: self.push_image(self.name, self.tag) 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): ''' @@ -397,7 +543,7 @@ class ImageManager(DockerBaseClass): if image: if not self.check_mode: try: - self.client.remove_image(name, force=self.force) + self.client.remove_image(name, force=self.force_absent) except Exception as 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']['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. :param name: name of the image. required. :param tag: image tag. :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. :return: None ''' @@ -511,7 +656,7 @@ class ImageManager(DockerBaseClass): found = 'found' if image else 'not 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.results['changed'] = True 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 ''' params = dict( - path=self.path, + path=self.build_path, tag=self.name, rm=self.rm, nocache=self.nocache, @@ -614,39 +759,70 @@ class ImageManager(DockerBaseClass): def main(): 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'), - 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'), - force=dict(type='bool', default=False), - http_timeout=dict(type='int'), + ), removedin_version='2.12'), + dockerfile=dict(type='str', removedin_version='2.12'), + force=dict(type='bool', removed_in_version='2.12'), + 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'), name=dict(type='str', required=True), - network=dict(type='str'), - nocache=dict(type='bool', default=False), - path=dict(type='path', aliases=['build_path']), - pull=dict(type='bool', default=True), + nocache=dict(type='bool', default=False, removedin_version='2.12'), + path=dict(type='path', aliases=['build_path'], removedin_version='2.12'), + pull=dict(type='bool', default=True, removedin_version='2.12'), push=dict(type='bool', default=False), 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']), tag=dict(type='str', default='latest'), 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( - cache_from=dict(docker_py_version='2.1.0', docker_api_version='1.25'), - network=dict(docker_py_version='2.4.0', docker_api_version='1.25'), - ) + required_if = [ + # ('state', 'present', ['source']), -- enable in Ansible 2.12. + # ('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( argument_spec=argument_spec, + required_if=required_if, supports_check_mode=True, min_docker_version='1.8.0', 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 ' 'and will be removed in Ansible 2.11. Please use ' '"present", which has the same meaning as "build".') + client.module.params['state'] = 'present' if client.module.params['use_tls']: 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' '"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( changed=False, actions=[], diff --git a/test/integration/targets/docker_image/tasks/tests/basic.yml b/test/integration/targets/docker_image/tasks/tests/basic.yml index 43c0cc85887..c503b13cb0c 100644 --- a/test/integration/targets/docker_image/tasks/tests/basic.yml +++ b/test/integration/targets/docker_image/tasks/tests/basic.yml @@ -7,6 +7,7 @@ docker_image: name: "hello-world:latest" state: absent + force_absent: yes register: absent_1 - name: Make sure image is not there (idempotency) @@ -23,14 +24,14 @@ docker_image: name: "hello-world:latest" state: present - pull: no + source: pull register: present_1 - name: Make sure image is there (idempotent) docker_image: name: "hello-world:latest" state: present - pull: yes + source: pull register: present_2 - assert: @@ -81,12 +82,14 @@ docker_image: name: "{{ registry_address }}/test/hello-world:latest" state: absent + force_absent: yes - name: Push image to test registry docker_image: name: "hello-world:latest" repository: "{{ registry_address }}/test/hello-world" push: yes + source: local register: push_1 - name: Push image to test registry (idempotent) @@ -94,6 +97,7 @@ name: "hello-world:latest" repository: "{{ registry_address }}/test/hello-world" push: yes + source: local register: push_2 - name: Push image to test registry (force, still idempotent) @@ -119,6 +123,7 @@ docker_image: name: "{{ registry_address }}/test/hello-world:latest" state: absent + force_absent: yes - name: Get facts of local image (absent) docker_image_facts: @@ -129,12 +134,14 @@ docker_image: name: "{{ registry_address }}/test/hello-world:latest" state: present + source: pull register: pull_1 - name: Pull image from test registry (idempotency) docker_image: name: "{{ registry_address }}/test/hello-world:latest" state: present + source: pull register: pull_2 - name: Get facts of local image (present) diff --git a/test/integration/targets/docker_image/tasks/tests/options.yml b/test/integration/targets/docker_image/tasks/tests/options.yml index 0e8f8f78e7a..741b748fc46 100644 --- a/test/integration/targets/docker_image/tasks/tests/options.yml +++ b/test/integration/targets/docker_image/tasks/tests/options.yml @@ -9,33 +9,38 @@ inames: "{{ inames }} + [iname, iname_1]" #################################################################### -## buildargs ####################################################### +## build.args ###################################################### #################################################################### - name: buildargs docker_image: - path: "{{ role_path }}/files" name: "{{ iname }}" - buildargs: - TEST1: val1 - TEST2: val2 - TEST3: "True" + build: + path: "{{ role_path }}/files" + args: + TEST1: val1 + TEST2: val2 + TEST3: "True" + source: build register: buildargs_1 - name: buildargs (idempotency) docker_image: - path: "{{ role_path }}/files" name: "{{ iname }}" - buildargs: - TEST1: val1 - TEST2: val2 - TEST3: "True" + build: + path: "{{ role_path }}/files" + args: + TEST1: val1 + TEST2: val2 + TEST3: "True" + source: build register: buildargs_2 - name: cleanup docker_image: name: "{{ iname }}" state: absent + force_absent: yes - assert: that: @@ -55,26 +60,31 @@ - name: container_limits (Failed due to min memory limit) docker_image: - path: "{{ role_path }}/files" name: "{{ iname }}" - container_limits: - memory: 4000 + build: + path: "{{ role_path }}/files" + container_limits: + memory: 4000 + source: build ignore_errors: yes register: container_limits_1 - name: container_limits docker_image: - path: "{{ role_path }}/files" name: "{{ iname }}" - container_limits: - memory: 5000000 - memswap: 7000000 + build: + path: "{{ role_path }}/files" + container_limits: + memory: 5000000 + memswap: 7000000 + source: build register: container_limits_2 - name: cleanup docker_image: name: "{{ iname }}" state: absent + force_absent: yes - assert: that: @@ -93,15 +103,18 @@ - name: dockerfile docker_image: - path: "{{ role_path }}/files" name: "{{ iname }}" - dockerfile: "MyDockerfile" + build: + path: "{{ role_path }}/files" + dockerfile: "MyDockerfile" + source: build register: dockerfile_1 - name: cleanup docker_image: name: "{{ iname }}" state: absent + force_absent: yes - assert: that: @@ -116,19 +129,24 @@ docker_image: name: "{{ registry_address }}/test/{{ iname }}:latest" state: absent + force_absent: yes - name: repository docker_image: name: "{{ iname }}" - path: "{{ role_path }}/files" + build: + path: "{{ role_path }}/files" repository: "{{ registry_address }}/test/{{ iname }}" + source: build register: repository_1 - name: repository (idempotent) docker_image: name: "{{ iname }}" - path: "{{ role_path }}/files" + build: + path: "{{ role_path }}/files" repository: "{{ registry_address }}/test/{{ iname }}" + source: build register: repository_2 - assert: @@ -145,7 +163,7 @@ docker_image: name: "{{ registry_address }}/test/{{ iname }}:latest" state: absent - force: yes + force_absent: yes - assert: that: @@ -157,29 +175,36 @@ - name: Build an image docker_image: - path: "{{ role_path }}/files" name: "{{ iname }}" + build: + path: "{{ role_path }}/files" + source: build - name: force (changed) docker_image: - path: "{{ role_path }}/files" name: "{{ iname }}" - dockerfile: "MyDockerfile" - force: yes + build: + path: "{{ role_path }}/files" + dockerfile: "MyDockerfile" + source: build + force_source: yes register: force_1 - name: force (unchanged) docker_image: - path: "{{ role_path }}/files" name: "{{ iname }}" - dockerfile: "MyDockerfile" - force: yes + build: + path: "{{ role_path }}/files" + dockerfile: "MyDockerfile" + source: build + force_source: yes register: force_2 - name: cleanup docker_image: name: "{{ iname }}" state: absent + force_absent: yes - assert: that: @@ -194,23 +219,27 @@ docker_image: name: "hello-world:latest" archive_path: image.tar + source: pull register: archive_image - name: remove image docker_image: name: "hello-world:latest" state: absent + force_absent: yes - name: load image (changed) docker_image: name: "hello-world:latest" load_path: image.tar + source: load register: load_image - name: load image (idempotency) docker_image: name: "hello-world:latest" load_path: image.tar + source: load register: load_image_1 - assert: @@ -226,19 +255,24 @@ - name: Build image docker_image: name: "{{ iname }}" - path: "{{ role_path }}/files" + build: + path: "{{ role_path }}/files" + source: build register: path_1 -- name: Build image(idempotency) +- name: Build image (idempotency) docker_image: name: "{{ iname }}" - path: "{{ role_path }}/files" + build: + path: "{{ role_path }}/files" + source: build register: path_2 - name: cleanup docker_image: name: "{{ iname }}" state: absent + force_absent: yes - assert: that: