diff --git a/lib/ansible/modules/cloud/docker/docker_container.py b/lib/ansible/modules/cloud/docker/docker_container.py index d8d3b82295b..b0506f62c49 100644 --- a/lib/ansible/modules/cloud/docker/docker_container.py +++ b/lib/ansible/modules/cloud/docker/docker_container.py @@ -229,15 +229,36 @@ options: networks: description: - List of networks the container belongs to. - - Each network is a dict with keys C(name), C(ipv4_address), C(ipv6_address), C(links), C(aliases). - - For each network C(name) is required, all other keys are optional. - - If included, C(links) or C(aliases) are lists. - For examples of the data structure and usage see EXAMPLES below. - To remove a container from one or more networks, use the C(purge_networks) option. - Note that as opposed to C(docker run ...), M(docker_container) does not remove the default network if C(networks) is specified. You need to explicity use C(purge_networks) to enforce the removal of the default network (and all other networks not explicitly mentioned in C(networks)). version_added: "2.2" + type: list + suboptions: + name: + type: str + required: true + description: + - The network's name. + ipv4_address: + type: str + description: + - The container's IPv4 address in this network. + ipv6_address: + type: str + description: + - The container's IPv6 address in this network. + links: + type: list + description: + - A list of containers to link to. + aliases: + type: list + description: + - List of aliases for this container in this network. These names + can be used in the network to reach this container. oom_killer: description: - Whether or not to disable OOM Killer for the container. @@ -801,8 +822,6 @@ class TaskParameters(DockerBaseClass): if self.networks: for network in self.networks: - if not network.get('name'): - self.fail("Parameter error: network must have a name attribute.") network['id'] = self._get_network_id(network['name']) if not network['id']: self.fail("Parameter error: network named %s could not be found. Does it exist?" % network['name']) @@ -1505,21 +1524,15 @@ class Container(DockerBaseClass): diff = True if network.get('ipv6_address') and network['ipv6_address'] != connected_networks[network['name']].get('GlobalIPv6Address'): diff = True - if network.get('aliases') and not connected_networks[network['name']].get('Aliases'): - diff = True - if network.get('aliases') and connected_networks[network['name']].get('Aliases'): - for alias in network.get('aliases'): - if alias not in connected_networks[network['name']].get('Aliases', []): - diff = True - if network.get('links') and not connected_networks[network['name']].get('Links'): - diff = True - if network.get('links') and connected_networks[network['name']].get('Links'): + if network.get('aliases'): + if not compare_generic(network['aliases'], connected_networks[network['name']].get('Aliases'), 'allow_more_present', 'set'): + diff = True + if network.get('links'): expected_links = [] for link, alias in network['links']: expected_links.append("%s:%s" % (link, alias)) - for link in expected_links: - if link not in connected_networks[network['name']].get('Links', []): - diff = True + if not compare_generic(expected_links, connected_networks[network['name']].get('Links'), 'allow_more_present', 'set'): + diff = True if diff: different = True differences.append(dict( @@ -2301,8 +2314,8 @@ def main(): argument_spec = dict( auto_remove=dict(type='bool', default=False), blkio_weight=dict(type='int'), - capabilities=dict(type='list'), - cap_drop=dict(type='list'), + capabilities=dict(type='list', elements='str'), + cap_drop=dict(type='list', elements='str'), cleanup=dict(type='bool', default=False), command=dict(type='raw'), cpu_period=dict(type='int'), @@ -2311,18 +2324,18 @@ def main(): cpuset_mems=dict(type='str'), cpu_shares=dict(type='int'), detach=dict(type='bool', default=True), - devices=dict(type='list'), - dns_servers=dict(type='list'), - dns_opts=dict(type='list'), - dns_search_domains=dict(type='list'), + devices=dict(type='list', elements='str'), + dns_servers=dict(type='list', elements='str'), + dns_opts=dict(type='list', elements='str'), + dns_search_domains=dict(type='list', elements='str'), domainname=dict(type='str'), - entrypoint=dict(type='list'), + entrypoint=dict(type='list', elements='str'), env=dict(type='dict'), env_file=dict(type='path'), etc_hosts=dict(type='dict'), - exposed_ports=dict(type='list', aliases=['exposed', 'expose']), + exposed_ports=dict(type='list', aliases=['exposed', 'expose'], elements='str'), force_kill=dict(type='bool', default=False, aliases=['forcekill']), - groups=dict(type='list'), + groups=dict(type='list', elements='str'), hostname=dict(type='str'), ignore_image=dict(type='bool', default=False), image=dict(type='str'), @@ -2333,7 +2346,7 @@ def main(): kernel_memory=dict(type='str'), kill_signal=dict(type='str'), labels=dict(type='dict'), - links=dict(type='list'), + links=dict(type='list', elements='str'), log_driver=dict(type='str'), log_options=dict(type='dict', aliases=['log_opt']), mac_address=dict(type='str'), @@ -2343,14 +2356,20 @@ def main(): memory_swappiness=dict(type='int'), name=dict(type='str', required=True), network_mode=dict(type='str'), - networks=dict(type='list'), + networks=dict(type='list', elements='dict', options=dict( + name=dict(required=True, type='str'), + ipv4_address=dict(type='str'), + ipv6_address=dict(type='str'), + aliases=dict(type='list', elements='str'), + links=dict(type='list', elements='str'), + )), oom_killer=dict(type='bool'), oom_score_adj=dict(type='int'), output_logs=dict(type='bool', default=False), paused=dict(type='bool', default=False), pid_mode=dict(type='str'), privileged=dict(type='bool', default=False), - published_ports=dict(type='list', aliases=['ports']), + published_ports=dict(type='list', aliases=['ports'], elements='str'), pull=dict(type='bool', default=False), purge_networks=dict(type='bool', default=False), read_only=dict(type='bool', default=False), @@ -2358,22 +2377,22 @@ def main(): restart=dict(type='bool', default=False), restart_policy=dict(type='str', choices=['no', 'on-failure', 'always', 'unless-stopped']), restart_retries=dict(type='int', default=None), - security_opts=dict(type='list'), + security_opts=dict(type='list', elements='str'), shm_size=dict(type='str'), state=dict(type='str', choices=['absent', 'present', 'started', 'stopped'], default='started'), stop_signal=dict(type='str'), stop_timeout=dict(type='int'), sysctls=dict(type='dict'), - tmpfs=dict(type='list'), + tmpfs=dict(type='list', elements='str'), trust_image_content=dict(type='bool', default=False), tty=dict(type='bool', default=False), - ulimits=dict(type='list'), + ulimits=dict(type='list', elements='str'), user=dict(type='str'), userns_mode=dict(type='str'), uts=dict(type='str'), volume_driver=dict(type='str'), - volumes=dict(type='list'), - volumes_from=dict(type='list'), + volumes=dict(type='list', elements='str'), + volumes_from=dict(type='list', elements='str'), working_dir=dict(type='str'), ) diff --git a/lib/ansible/modules/cloud/docker/docker_image.py b/lib/ansible/modules/cloud/docker/docker_image.py index d48f4fa0886..d25a02c5f15 100644 --- a/lib/ansible/modules/cloud/docker/docker_image.py +++ b/lib/ansible/modules/cloud/docker/docker_image.py @@ -576,7 +576,12 @@ class ImageManager(DockerBaseClass): def main(): argument_spec = dict( archive_path=dict(type='path'), - container_limits=dict(type='dict'), + 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'), diff --git a/lib/ansible/modules/cloud/docker/docker_image_facts.py b/lib/ansible/modules/cloud/docker/docker_image_facts.py index 913c1cfc5a9..ec1fbc951ef 100644 --- a/lib/ansible/modules/cloud/docker/docker_image_facts.py +++ b/lib/ansible/modules/cloud/docker/docker_image_facts.py @@ -222,7 +222,7 @@ class ImageManager(DockerBaseClass): def main(): argument_spec = dict( - name=dict(type='list'), + name=dict(type='list', elements='str'), ) client = AnsibleDockerClient( diff --git a/lib/ansible/modules/cloud/docker/docker_network.py b/lib/ansible/modules/cloud/docker/docker_network.py index 018c890f920..e48da0bfe08 100644 --- a/lib/ansible/modules/cloud/docker/docker_network.py +++ b/lib/ansible/modules/cloud/docker/docker_network.py @@ -272,6 +272,10 @@ class DockerNetworkManager(object): else: for key, value in self.parameters.ipam_options.items(): camelkey = None + if value is None: + # due to recursive argument_spec, all keys are always present + # (but have default value None if not specified) + continue for net_key in net['IPAM']['Config'][0]: if key == net_key.lower(): camelkey = net_key @@ -289,7 +293,8 @@ class DockerNetworkManager(object): def create_network(self): if not self.existing_network: ipam_pools = [] - if self.parameters.ipam_options: + if (self.parameters.ipam_options['subnet'] or self.parameters.ipam_options['iprange'] or + self.parameters.ipam_options['gateway'] or self.parameters.ipam_options['aux_addresses']): if HAS_DOCKER_PY_2 or HAS_DOCKER_PY_3: ipam_pools.append(IPAMPool(**self.parameters.ipam_options)) else: @@ -385,14 +390,19 @@ class DockerNetworkManager(object): def main(): argument_spec = dict( network_name=dict(type='str', required=True, aliases=['name']), - connected=dict(type='list', default=[], aliases=['containers']), + connected=dict(type='list', default=[], aliases=['containers'], elements='str'), state=dict(type='str', default='present', choices=['present', 'absent']), driver=dict(type='str', default='bridge'), driver_options=dict(type='dict', default={}), force=dict(type='bool', default=False), appends=dict(type='bool', default=False, aliases=['incremental']), - ipam_driver=dict(type='str', default=None), - ipam_options=dict(type='dict', default={}), + ipam_driver=dict(type='str'), + ipam_options=dict(type='dict', default={}, options=dict( + subnet=dict(type='str'), + iprange=dict(type='str'), + gateway=dict(type='str'), + aux_addresses=dict(type='dict'), + )), debug=dict(type='bool', default=False) ) diff --git a/lib/ansible/modules/cloud/docker/docker_service.py b/lib/ansible/modules/cloud/docker/docker_service.py index 902d72da365..79f8003558b 100644 --- a/lib/ansible/modules/cloud/docker/docker_service.py +++ b/lib/ansible/modules/cloud/docker/docker_service.py @@ -1033,7 +1033,7 @@ def main(): argument_spec = dict( project_src=dict(type='path'), project_name=dict(type='str',), - files=dict(type='list'), + files=dict(type='list', elements='path'), state=dict(type='str', choices=['absent', 'present'], default='present'), definition=dict(type='dict'), hostname_check=dict(type='bool', default=False), @@ -1045,7 +1045,7 @@ def main(): stopped=dict(type='bool', default=False), restarted=dict(type='bool', default=False), scale=dict(type='dict'), - services=dict(type='list'), + services=dict(type='list', elements='str'), dependencies=dict(type='bool', default=True), pull=dict(type='bool', default=False), nocache=dict(type='bool', default=False), diff --git a/lib/ansible/modules/cloud/docker/docker_swarm.py b/lib/ansible/modules/cloud/docker/docker_swarm.py index d3de6142c4b..a94aa880baa 100644 --- a/lib/ansible/modules/cloud/docker/docker_swarm.py +++ b/lib/ansible/modules/cloud/docker/docker_swarm.py @@ -475,7 +475,7 @@ def main(): state=dict(type='str', choices=['present', 'join', 'absent', 'remove', 'inspect'], default='present'), force=dict(type='bool', default=False), listen_addr=dict(type='str', default='0.0.0.0:2377'), - remote_addrs=dict(type='list'), + remote_addrs=dict(type='list', elements='str'), join_token=dict(type='str'), snapshot_interval=dict(type='int'), task_history_retention_limit=dict(type='int'),