def has_different_config(self): """ Return the list of differences between the current parameters and the existing volume. :return: list of options that differ """ differences = DifferenceTracker() if self.parameters.driver and self.parameters.driver != self.existing_volume['Driver']: differences.add('driver', parameter=self.parameters.driver, active=self.existing_volume['Driver']) if self.parameters.driver_options: if not self.existing_volume.get('Options'): differences.add('driver_options', parameter=self.parameters.driver_options, active=self.existing_volume.get('Options')) else: for key, value in iteritems(self.parameters.driver_options): if (not self.existing_volume['Options'].get(key) or value != self.existing_volume['Options'][key]): differences.add('driver_options.%s' % key, parameter=value, active=self.existing_volume['Options'].get(key)) if self.parameters.labels: existing_labels = self.existing_volume.get('Labels', {}) for label in self.parameters.labels: if existing_labels.get(label) != self.parameters.labels.get(label): differences.add('labels.%s' % label, parameter=self.parameters.labels.get(label), active=existing_labels.get(label)) return differences
def has_different_config(self, net): ''' Evaluates an existing network and returns a tuple containing a boolean indicating if the configuration is different and a list of differences. :param net: the inspection output for an existing network :return: (bool, list) ''' differences = DifferenceTracker() if self.parameters.driver and self.parameters.driver != net['Driver']: differences.add('driver', parameter=self.parameters.driver, active=net['Driver']) if self.parameters.driver_options: if not net.get('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]: 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: 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']: 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() try: ip_version = get_ip_version(ipam_config['subnet']) for net_ipam_config in net['IPAM']['Config']: if ip_version == get_ip_version( net_ipam_config['Subnet']): net_config = net_ipam_config except ValueError as e: self.client.fail(str(e)) for key, value in ipam_config.items(): if value is None: # due to recursive argument_spec, all keys are always present # (but have default value None if not specified) continue camelkey = None for net_key in net_config: if key == net_key.lower(): camelkey = net_key break if not camelkey or net_config.get(camelkey) != value: 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): differences.add('enable_ipv6', parameter=self.parameters.enable_ipv6, active=net.get('EnableIPv6', False)) if self.parameters.internal is not None and self.parameters.internal != net.get( 'Internal', False): differences.add('internal', parameter=self.parameters.internal, active=net.get('Internal')) if self.parameters.scope is not None and self.parameters.scope != net.get( 'Scope'): differences.add('scope', parameter=self.parameters.scope, active=net.get('Scope')) if self.parameters.attachable is not None and self.parameters.attachable != net.get( 'Attachable', False): differences.add('attachable', parameter=self.parameters.attachable, active=net.get('Attachable')) return not differences.empty, differences
class DockerNetworkManager(object): def _get_minimal_versions(self): # TODO: Move this and the same from docker_container.py to docker_common.py self.option_minimal_versions = dict() for option, data in self.client.module.argument_spec.items(): self.option_minimal_versions[option] = dict() self.option_minimal_versions.update( dict( scope=dict(docker_py_version='2.6.0', docker_api_version='1.30'), attachable=dict(docker_py_version='2.0.0', docker_api_version='1.26'), )) for option, data in self.option_minimal_versions.items(): # Test whether option is supported, and store result support_docker_py = True support_docker_api = True if 'docker_py_version' in data: support_docker_py = self.client.docker_py_version >= LooseVersion( data['docker_py_version']) if 'docker_api_version' in data: support_docker_api = self.client.docker_api_version >= LooseVersion( data['docker_api_version']) data['supported'] = support_docker_py and support_docker_api # Fail if option is not supported but used if not data['supported']: # Test whether option is specified if 'detect_usage' in data: used = data['detect_usage']() else: used = self.client.module.params.get(option) is not None if used and 'default' in self.client.module.argument_spec[ option]: used = self.client.module.params[ option] != self.client.module.argument_spec[ option]['default'] if used: # If the option is used, compose error message. if 'usage_msg' in data: usg = data['usage_msg'] else: usg = 'set %s option' % (option, ) if not support_docker_api: msg = 'docker API version is %s. Minimum version required is %s to %s.' msg = msg % (self.client.docker_api_version_str, data['docker_api_version'], usg) elif not support_docker_py: if LooseVersion(data['docker_py_version'] ) < LooseVersion('2.0.0'): msg = ( "docker-py version is %s. Minimum version required is %s to %s. " "Consider switching to the 'docker' package if you do not require Python 2.6 support." ) elif self.client.docker_py_version < LooseVersion( '2.0.0'): msg = ( "docker-py version is %s. Minimum version required is %s to %s. " "You have to switch to the Python 'docker' package. First uninstall 'docker-py' before " "installing 'docker' to avoid a broken installation." ) else: msg = "docker version is %s. Minimum version required is %s to %s." msg = msg % (docker_version, data['docker_py_version'], usg) else: # should not happen msg = 'Cannot %s with your configuration.' % (usg, ) self.client.fail(msg) def __init__(self, client): self.client = client self.parameters = TaskParameters(client) self.check_mode = self.client.check_mode self.results = {u'changed': False, u'actions': []} self.diff = self.client.module._diff self.diff_tracker = DifferenceTracker() self.diff_result = dict() self._get_minimal_versions() self.existing_network = self.get_existing_network() if not self.parameters.connected and self.existing_network: self.parameters.connected = container_names_in_network( self.existing_network) 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']): self.parameters.ipam_config = [self.parameters.ipam_options] if self.parameters.driver_options: self.parameters.driver_options = get_driver_options( self.parameters.driver_options) state = self.parameters.state if state == 'present': self.present() 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) except NotFound: return None def has_different_config(self, net): ''' Evaluates an existing network and returns a tuple containing a boolean indicating if the configuration is different and a list of differences. :param net: the inspection output for an existing network :return: (bool, list) ''' differences = DifferenceTracker() if self.parameters.driver and self.parameters.driver != net['Driver']: differences.add('driver', parameter=self.parameters.driver, active=net['Driver']) if self.parameters.driver_options: if not net.get('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]: 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: 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']: 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() try: ip_version = get_ip_version(ipam_config['subnet']) for net_ipam_config in net['IPAM']['Config']: if ip_version == get_ip_version( net_ipam_config['Subnet']): net_config = net_ipam_config except ValueError as e: self.client.fail(str(e)) for key, value in ipam_config.items(): if value is None: # due to recursive argument_spec, all keys are always present # (but have default value None if not specified) continue camelkey = None for net_key in net_config: if key == net_key.lower(): camelkey = net_key break if not camelkey or net_config.get(camelkey) != value: 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): differences.add('enable_ipv6', parameter=self.parameters.enable_ipv6, active=net.get('EnableIPv6', False)) if self.parameters.internal is not None and self.parameters.internal != net.get( 'Internal', False): differences.add('internal', parameter=self.parameters.internal, active=net.get('Internal')) if self.parameters.scope is not None and self.parameters.scope != net.get( 'Scope'): differences.add('scope', parameter=self.parameters.scope, active=net.get('Scope')) if self.parameters.attachable is not None and self.parameters.attachable != net.get( 'Attachable', False): differences.add('attachable', parameter=self.parameters.attachable, active=net.get('Attachable')) return not differences.empty, differences def create_network(self): if not self.existing_network: params = dict( driver=self.parameters.driver, options=self.parameters.driver_options, ) ipam_pools = [] if self.parameters.ipam_config: for ipam_pool in self.parameters.ipam_config: if LooseVersion(docker_version) >= LooseVersion('2.0.0'): ipam_pools.append(IPAMPool(**ipam_pool)) else: ipam_pools.append(utils.create_ipam_pool(**ipam_pool)) if self.parameters.ipam_driver or ipam_pools: # Only add ipam parameter if a driver was specified or if IPAM parameters # 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 LooseVersion(docker_version) >= LooseVersion('2.0.0'): params['ipam'] = IPAMConfig( driver=self.parameters.ipam_driver, pool_configs=ipam_pools) else: params['ipam'] = utils.create_ipam_config( driver=self.parameters.ipam_driver, pool_configs=ipam_pools) if self.parameters.enable_ipv6 is not None: params['enable_ipv6'] = self.parameters.enable_ipv6 if self.parameters.internal is not None: params['internal'] = self.parameters.internal if self.parameters.scope is not None: params['scope'] = self.parameters.scope if self.parameters.attachable is not None: params['attachable'] = self.parameters.attachable if not self.check_mode: resp = self.client.create_network(self.parameters.network_name, **params) self.existing_network = self.client.inspect_network(resp['Id']) self.results['actions'].append( "Created network %s with driver %s" % (self.parameters.network_name, self.parameters.driver)) self.results['changed'] = True def remove_network(self): if self.existing_network: self.disconnect_all_containers() if not self.check_mode: self.client.remove_network(self.parameters.network_name) self.results['actions'].append("Removed network %s" % (self.parameters.network_name, )) self.results['changed'] = True def is_container_connected(self, container_name): return container_name in container_names_in_network( self.existing_network) def connect_containers(self): for name in self.parameters.connected: if not self.is_container_connected(name): if not self.check_mode: 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: return containers = self.existing_network['Containers'] if not containers: return for c in containers.values(): name = c['Name'] if name not in self.parameters.connected: self.disconnect_container(name) def disconnect_all_containers(self): containers = self.client.inspect_network( self.parameters.network_name)['Containers'] if not containers: return for cont in containers.values(): self.disconnect_container(cont['Name']) def disconnect_container(self, container_name): if not self.check_mode: 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 = 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 self.create_network() self.connect_containers() if not self.parameters.appends: self.disconnect_missing() if self.diff or self.check_mode or self.parameters.debug: 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') 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()
class DockerVolumeManager(object): def __init__(self, client): self.client = client self.parameters = TaskParameters(client) self.check_mode = self.client.check_mode self.results = { u'changed': False, u'actions': [] } self.diff = self.client.module._diff self.diff_tracker = DifferenceTracker() self.diff_result = dict() self.existing_volume = self.get_existing_volume() state = self.parameters.state if state == 'present': self.present() 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_volume(self): try: volumes = self.client.volumes() except APIError as e: self.client.fail(text_type(e)) if volumes[u'Volumes'] is None: return None for volume in volumes[u'Volumes']: if volume['Name'] == self.parameters.volume_name: return volume return None def has_different_config(self): """ Return the list of differences between the current parameters and the existing volume. :return: list of options that differ """ differences = DifferenceTracker() if self.parameters.driver and self.parameters.driver != self.existing_volume['Driver']: differences.add('driver', parameter=self.parameters.driver, active=self.existing_volume['Driver']) if self.parameters.driver_options: if not self.existing_volume.get('Options'): differences.add('driver_options', parameter=self.parameters.driver_options, active=self.existing_volume.get('Options')) else: for key, value in iteritems(self.parameters.driver_options): if (not self.existing_volume['Options'].get(key) or value != self.existing_volume['Options'][key]): differences.add('driver_options.%s' % key, parameter=value, active=self.existing_volume['Options'].get(key)) if self.parameters.labels: existing_labels = self.existing_volume.get('Labels', {}) for label in self.parameters.labels: if existing_labels.get(label) != self.parameters.labels.get(label): differences.add('labels.%s' % label, parameter=self.parameters.labels.get(label), active=existing_labels.get(label)) return differences def create_volume(self): if not self.existing_volume: if not self.check_mode: try: params = dict( driver=self.parameters.driver, driver_opts=self.parameters.driver_options, ) if self.parameters.labels is not None: params['labels'] = self.parameters.labels resp = self.client.create_volume(self.parameters.volume_name, **params) self.existing_volume = self.client.inspect_volume(resp['Name']) except APIError as e: self.client.fail(text_type(e)) self.results['actions'].append("Created volume %s with driver %s" % (self.parameters.volume_name, self.parameters.driver)) self.results['changed'] = True def remove_volume(self): if self.existing_volume: if not self.check_mode: try: self.client.remove_volume(self.parameters.volume_name) except APIError as e: self.client.fail(text_type(e)) self.results['actions'].append("Removed volume %s" % self.parameters.volume_name) self.results['changed'] = True def present(self): differences = DifferenceTracker() if self.existing_volume: differences = self.has_different_config() self.diff_tracker.add('exists', parameter=True, active=self.existing_volume is not None) if (not differences.empty and self.parameters.recreate == 'options-changed') or self.parameters.recreate == 'always': self.remove_volume() self.existing_volume = None self.create_volume() if self.diff or self.check_mode or self.parameters.debug: 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') self.results['ansible_facts'] = {u'docker_volume': self.get_existing_volume()} def absent(self): self.diff_tracker.add('exists', parameter=False, active=self.existing_volume is not None) self.remove_volume()
def compare(self, os): differences = DifferenceTracker() needs_rebuild = False force_update = False if self.endpoint_mode != os.endpoint_mode: differences.add('endpoint_mode', parameter=self.endpoint_mode, active=os.endpoint_mode) if self.env != os.env: differences.add('env', parameter=self.env, active=os.env) if self.log_driver != os.log_driver: differences.add('log_driver', parameter=self.log_driver, active=os.log_driver) if self.log_driver_options != os.log_driver_options: differences.add('log_opt', parameter=self.log_driver_options, active=os.log_driver_options) if self.mode != os.mode: needs_rebuild = True differences.add('mode', parameter=self.mode, active=os.mode) if self.mounts != os.mounts: differences.add('mounts', parameter=self.mounts, active=os.mounts) if self.configs != os.configs: differences.add('configs', parameter=self.configs, active=os.configs) if self.secrets != os.secrets: differences.add('secrets', parameter=self.secrets, active=os.secrets) if self.networks != os.networks: differences.add('networks', parameter=self.networks, active=os.networks) needs_rebuild = True if self.replicas != os.replicas: differences.add('replicas', parameter=self.replicas, active=os.replicas) if self.args != os.args: differences.add('args', parameter=self.args, active=os.args) if self.constraints != os.constraints: differences.add('constraints', parameter=self.constraints, active=os.constraints) if self.labels != os.labels: differences.add('labels', parameter=self.labels, active=os.labels) if self.limit_cpu != os.limit_cpu: differences.add('limit_cpu', parameter=self.limit_cpu, active=os.limit_cpu) if self.limit_memory != os.limit_memory: differences.add('limit_memory', parameter=self.limit_memory, active=os.limit_memory) if self.reserve_cpu != os.reserve_cpu: differences.add('reserve_cpu', parameter=self.reserve_cpu, active=os.reserve_cpu) if self.reserve_memory != os.reserve_memory: differences.add('reserve_memory', parameter=self.reserve_memory, active=os.reserve_memory) if self.container_labels != os.container_labels: differences.add('container_labels', parameter=self.container_labels, active=os.container_labels) if self.publish != os.publish: differences.add('publish', parameter=self.publish, active=os.publish) if self.restart_policy != os.restart_policy: differences.add('restart_policy', parameter=self.restart_policy, active=os.restart_policy) if self.restart_policy_attempts != os.restart_policy_attempts: differences.add('restart_policy_attempts', parameter=self.restart_policy_attempts, active=os.restart_policy_attempts) if self.restart_policy_delay != os.restart_policy_delay: differences.add('restart_policy_delay', parameter=self.restart_policy_delay, active=os.restart_policy_delay) if self.restart_policy_window != os.restart_policy_window: differences.add('restart_policy_window', parameter=self.restart_policy_window, active=os.restart_policy_window) if self.update_delay != os.update_delay: differences.add('update_delay', parameter=self.update_delay, active=os.update_delay) if self.update_parallelism != os.update_parallelism: differences.add('update_parallelism', parameter=self.update_parallelism, active=os.update_parallelism) if self.update_failure_action != os.update_failure_action: differences.add('update_failure_action', parameter=self.update_failure_action, active=os.update_failure_action) if self.update_monitor != os.update_monitor: differences.add('update_monitor', parameter=self.update_monitor, active=os.update_monitor) if self.update_max_failure_ratio != os.update_max_failure_ratio: differences.add('update_max_failure_ratio', parameter=self.update_max_failure_ratio, active=os.update_max_failure_ratio) if self.update_order != os.update_order: differences.add('update_order', parameter=self.update_order, active=os.update_order) if self.image != os.image.split('@')[0]: differences.add('image', parameter=self.image, active=os.image.split('@')[0]) if self.user and self.user != os.user: differences.add('user', parameter=self.user, active=os.user) if self.dns != os.dns: differences.add('dns', parameter=self.dns, active=os.dns) if self.dns_search != os.dns_search: differences.add('dns_search', parameter=self.dns_search, active=os.dns_search) if self.dns_options != os.dns_options: differences.add('dns_options', parameter=self.dns_options, active=os.dns_options) if self.hostname != os.hostname: differences.add('hostname', parameter=self.hostname, active=os.hostname) if self.tty != os.tty: differences.add('tty', parameter=self.tty, active=os.tty) if self.force_update: force_update = True return not differences.empty or force_update, differences, needs_rebuild, force_update
class DockerNetworkManager(object): def __init__(self, client): self.client = client self.parameters = TaskParameters(client) self.check_mode = self.client.check_mode self.results = {u'changed': False, u'actions': []} self.diff = self.client.module._diff self.diff_tracker = DifferenceTracker() self.diff_result = dict() self.existing_network = self.get_existing_network() if not self.parameters.connected and self.existing_network: self.parameters.connected = container_names_in_network( self.existing_network) 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']): self.parameters.ipam_config = [self.parameters.ipam_options] if self.parameters.driver_options: self.parameters.driver_options = get_driver_options( self.parameters.driver_options) state = self.parameters.state if state == 'present': self.present() 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) except NotFound: return None def has_different_config(self, net): ''' Evaluates an existing network and returns a tuple containing a boolean indicating if the configuration is different and a list of differences. :param net: the inspection output for an existing network :return: (bool, list) ''' differences = DifferenceTracker() if self.parameters.driver and self.parameters.driver != net['Driver']: differences.add('driver', parameter=self.parameters.driver, active=net['Driver']) if self.parameters.driver_options: if not net.get('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]: 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: 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']: 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() try: ip_version = get_ip_version(ipam_config['subnet']) for net_ipam_config in net['IPAM']['Config']: if ip_version == get_ip_version( net_ipam_config['Subnet']): net_config = net_ipam_config except ValueError as e: self.client.fail(str(e)) for key, value in ipam_config.items(): if value is None: # due to recursive argument_spec, all keys are always present # (but have default value None if not specified) continue camelkey = None for net_key in net_config: if key == net_key.lower(): camelkey = net_key break if not camelkey or net_config.get(camelkey) != value: 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): 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'): differences.add('internal', parameter=self.parameters.internal, active=net.get('Internal')) else: if net.get('Internal'): 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: params = dict( driver=self.parameters.driver, options=self.parameters.driver_options, ) ipam_pools = [] if self.parameters.ipam_config: for ipam_pool in self.parameters.ipam_config: if LooseVersion(docker_version) >= LooseVersion('2.0.0'): ipam_pools.append(IPAMPool(**ipam_pool)) else: ipam_pools.append(utils.create_ipam_pool(**ipam_pool)) if self.parameters.ipam_driver or ipam_pools: # Only add ipam parameter if a driver was specified or if IPAM parameters # 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 LooseVersion(docker_version) >= LooseVersion('2.0.0'): params['ipam'] = IPAMConfig( driver=self.parameters.ipam_driver, pool_configs=ipam_pools) else: params['ipam'] = utils.create_ipam_config( driver=self.parameters.ipam_driver, pool_configs=ipam_pools) if self.parameters.enable_ipv6 is not None: params['enable_ipv6'] = self.parameters.enable_ipv6 if self.parameters.internal is not None: params['internal'] = self.parameters.internal if not self.check_mode: resp = self.client.create_network(self.parameters.network_name, **params) self.existing_network = self.client.inspect_network(resp['Id']) self.results['actions'].append( "Created network %s with driver %s" % (self.parameters.network_name, self.parameters.driver)) self.results['changed'] = True def remove_network(self): if self.existing_network: self.disconnect_all_containers() if not self.check_mode: self.client.remove_network(self.parameters.network_name) self.results['actions'].append("Removed network %s" % (self.parameters.network_name, )) self.results['changed'] = True def is_container_connected(self, container_name): return container_name in container_names_in_network( self.existing_network) def connect_containers(self): for name in self.parameters.connected: if not self.is_container_connected(name): if not self.check_mode: 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: return containers = self.existing_network['Containers'] if not containers: return for c in containers.values(): name = c['Name'] if name not in self.parameters.connected: self.disconnect_container(name) def disconnect_all_containers(self): containers = self.client.inspect_network( self.parameters.network_name)['Containers'] if not containers: return for cont in containers.values(): self.disconnect_container(cont['Name']) def disconnect_container(self, container_name): if not self.check_mode: 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 = 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 self.create_network() self.connect_containers() if not self.parameters.appends: self.disconnect_missing() if self.diff or self.check_mode or self.parameters.debug: 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') 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()