mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-05-28 03:49:09 -07:00
docker_* modules: improve diff (#48546)
* Add difference tracking tool * Improve --diff mode for docker_container. * Improve diffs of sets by ordering the sets. * Rewrite imports, get rid of HAS_DOCKER_PY_x variables and use docker_version instead. * Rename container -> active (more generic). * Add --diff for docker_volume. Change old diff output. * Add --diff for docker_network. Change old diff output. * Add --diff for docker_swarm_service. * Add changelog. * Add entry for porting guide on docker_network and docker_volume.
This commit is contained in:
parent
a67e9f89e7
commit
891687284f
13 changed files with 356 additions and 114 deletions
|
@ -228,12 +228,19 @@ facts:
|
|||
|
||||
import re
|
||||
|
||||
from ansible.module_utils.docker_common import AnsibleDockerClient, DockerBaseClass, HAS_DOCKER_PY_2, HAS_DOCKER_PY_3
|
||||
from distutils.version import LooseVersion
|
||||
|
||||
from ansible.module_utils.docker_common import (
|
||||
AnsibleDockerClient,
|
||||
DockerBaseClass,
|
||||
docker_version,
|
||||
DifferenceTracker,
|
||||
)
|
||||
|
||||
try:
|
||||
from docker import utils
|
||||
from docker.errors import NotFound
|
||||
if HAS_DOCKER_PY_2 or HAS_DOCKER_PY_3:
|
||||
if LooseVersion(docker_version) >= LooseVersion('2.0.0'):
|
||||
from docker.types import IPAMPool, IPAMConfig
|
||||
except Exception as dummy:
|
||||
# missing docker-py handled in ansible.module_utils.docker_common
|
||||
|
@ -312,6 +319,8 @@ class DockerNetworkManager(object):
|
|||
u'actions': []
|
||||
}
|
||||
self.diff = self.client.module._diff
|
||||
self.diff_tracker = DifferenceTracker()
|
||||
self.diff_result = dict()
|
||||
|
||||
self.existing_network = self.get_existing_network()
|
||||
|
||||
|
@ -331,6 +340,11 @@ class DockerNetworkManager(object):
|
|||
elif state == 'absent':
|
||||
self.absent()
|
||||
|
||||
if self.diff or self.check_mode or self.parameters.debug:
|
||||
if self.diff:
|
||||
self.diff_result['before'], self.diff_result['after'] = self.diff_tracker.get_before_after()
|
||||
self.results['diff'] = self.diff_result
|
||||
|
||||
def get_existing_network(self):
|
||||
try:
|
||||
return self.client.inspect_network(self.parameters.network_name)
|
||||
|
@ -345,30 +359,34 @@ class DockerNetworkManager(object):
|
|||
:param net: the inspection output for an existing network
|
||||
:return: (bool, list)
|
||||
'''
|
||||
different = False
|
||||
differences = []
|
||||
differences = DifferenceTracker()
|
||||
if self.parameters.driver and self.parameters.driver != net['Driver']:
|
||||
different = True
|
||||
differences.append('driver')
|
||||
differences.add('driver',
|
||||
parameter=self.parameters.driver,
|
||||
active=net['Driver'])
|
||||
if self.parameters.driver_options:
|
||||
if not net.get('Options'):
|
||||
different = True
|
||||
differences.append('driver_options')
|
||||
differences.add('driver_options',
|
||||
parameter=self.parameters.driver_options,
|
||||
active=net.get('Options'))
|
||||
else:
|
||||
for key, value in self.parameters.driver_options.items():
|
||||
if not (key in net['Options']) or value != net['Options'][key]:
|
||||
different = True
|
||||
differences.append('driver_options.%s' % key)
|
||||
differences.add('driver_options.%s' % key,
|
||||
parameter=value,
|
||||
active=net['Options'].get(key))
|
||||
|
||||
if self.parameters.ipam_driver:
|
||||
if not net.get('IPAM') or net['IPAM']['Driver'] != self.parameters.ipam_driver:
|
||||
different = True
|
||||
differences.append('ipam_driver')
|
||||
differences.add('ipam_driver',
|
||||
parameter=self.parameters.ipam_driver,
|
||||
active=net.get('IPAM'))
|
||||
|
||||
if self.parameters.ipam_config is not None and self.parameters.ipam_config:
|
||||
if not net.get('IPAM') or not net['IPAM']['Config']:
|
||||
different = True
|
||||
differences.append('ipam_config')
|
||||
differences.add('ipam_config',
|
||||
parameter=self.parameters.ipam_config,
|
||||
active=net.get('IPAM', {}).get('Config'))
|
||||
else:
|
||||
for idx, ipam_config in enumerate(self.parameters.ipam_config):
|
||||
net_config = dict()
|
||||
|
@ -391,23 +409,27 @@ class DockerNetworkManager(object):
|
|||
camelkey = net_key
|
||||
break
|
||||
if not camelkey or net_config.get(camelkey) != value:
|
||||
different = True
|
||||
differences.append('ipam_config[%s].%s' % (idx, key))
|
||||
differences.add('ipam_config[%s].%s' % (idx, key),
|
||||
parameter=value,
|
||||
active=net_config.get(camelkey) if camelkey else None)
|
||||
|
||||
if self.parameters.enable_ipv6 is not None and self.parameters.enable_ipv6 != net.get('EnableIPv6', False):
|
||||
different = True
|
||||
differences.append('enable_ipv6')
|
||||
differences.add('enable_ipv6',
|
||||
parameter=self.parameters.enable_ipv6,
|
||||
active=net.get('EnableIPv6', False))
|
||||
|
||||
if self.parameters.internal is not None:
|
||||
if self.parameters.internal:
|
||||
if not net.get('Internal'):
|
||||
different = True
|
||||
differences.append('internal')
|
||||
differences.add('internal',
|
||||
parameter=self.parameters.internal,
|
||||
active=net.get('Internal'))
|
||||
else:
|
||||
if net.get('Internal'):
|
||||
different = True
|
||||
differences.append('internal')
|
||||
return different, differences
|
||||
differences.add('internal',
|
||||
parameter=self.parameters.internal,
|
||||
active=net.get('Internal'))
|
||||
return not differences.empty, differences
|
||||
|
||||
def create_network(self):
|
||||
if not self.existing_network:
|
||||
|
@ -419,7 +441,7 @@ class DockerNetworkManager(object):
|
|||
ipam_pools = []
|
||||
if self.parameters.ipam_config:
|
||||
for ipam_pool in self.parameters.ipam_config:
|
||||
if HAS_DOCKER_PY_2 or HAS_DOCKER_PY_3:
|
||||
if LooseVersion(docker_version) >= LooseVersion('2.0.0'):
|
||||
ipam_pools.append(IPAMPool(**ipam_pool))
|
||||
else:
|
||||
ipam_pools.append(utils.create_ipam_pool(**ipam_pool))
|
||||
|
@ -429,7 +451,7 @@ class DockerNetworkManager(object):
|
|||
# were specified. Leaving this parameter away can significantly speed up
|
||||
# creation; on my machine creation with this option needs ~15 seconds,
|
||||
# and without just a few seconds.
|
||||
if HAS_DOCKER_PY_2 or HAS_DOCKER_PY_3:
|
||||
if LooseVersion(docker_version) >= LooseVersion('2.0.0'):
|
||||
params['ipam'] = IPAMConfig(driver=self.parameters.ipam_driver,
|
||||
pool_configs=ipam_pools)
|
||||
else:
|
||||
|
@ -466,6 +488,9 @@ class DockerNetworkManager(object):
|
|||
self.client.connect_container_to_network(name, self.parameters.network_name)
|
||||
self.results['actions'].append("Connected container %s" % (name,))
|
||||
self.results['changed'] = True
|
||||
self.diff_tracker.add('connected.{0}'.format(name),
|
||||
parameter=True,
|
||||
active=False)
|
||||
|
||||
def disconnect_missing(self):
|
||||
if not self.existing_network:
|
||||
|
@ -490,13 +515,17 @@ class DockerNetworkManager(object):
|
|||
self.client.disconnect_container_from_network(container_name, self.parameters.network_name)
|
||||
self.results['actions'].append("Disconnected container %s" % (container_name,))
|
||||
self.results['changed'] = True
|
||||
self.diff_tracker.add('connected.{0}'.format(container_name),
|
||||
parameter=False,
|
||||
active=True)
|
||||
|
||||
def present(self):
|
||||
different = False
|
||||
differences = []
|
||||
differences = DifferenceTracker()
|
||||
if self.existing_network:
|
||||
different, differences = self.has_different_config(self.existing_network)
|
||||
|
||||
self.diff_tracker.add('exists', parameter=True, active=self.existing_network is not None)
|
||||
if self.parameters.force or different:
|
||||
self.remove_network()
|
||||
self.existing_network = None
|
||||
|
@ -507,7 +536,8 @@ class DockerNetworkManager(object):
|
|||
self.disconnect_missing()
|
||||
|
||||
if self.diff or self.check_mode or self.parameters.debug:
|
||||
self.results['diff'] = differences
|
||||
self.diff_result['differences'] = differences.get_legacy_docker_diffs()
|
||||
self.diff_tracker.merge(differences)
|
||||
|
||||
if not self.check_mode and not self.parameters.debug:
|
||||
self.results.pop('actions')
|
||||
|
@ -515,6 +545,7 @@ class DockerNetworkManager(object):
|
|||
self.results['ansible_facts'] = {u'docker_network': self.get_existing_network()}
|
||||
|
||||
def absent(self):
|
||||
self.diff_tracker.add('exists', parameter=False, active=self.existing_network is not None)
|
||||
self.remove_network()
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue