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

docker_swarm inventory plugin - new attribute with parsed node URI (#53894)

* * Adding new attribute that contains an URI which may be used in other docker swarm modules

* Change host_uri to include_host_uri parameter name

* Adding port detection/override

* Small fixes

* Some general PEP8 adjustments for better code readability

* Changing the parameter type description for clearance
This commit is contained in:
Piotr Wojciechowski 2019-03-17 10:42:33 +01:00 committed by ansibot
parent 259b2e06a4
commit 955da2a095

View file

@ -56,6 +56,16 @@ DOCUMENTATION = '''
tls_hostname: tls_hostname:
description: When verifying the authenticity of the Docker Host server, provide the expected name of the server. description: When verifying the authenticity of the Docker Host server, provide the expected name of the server.
type: str type: str
include_host_uri:
description: Toggle to return the additional attribute I(ansible_host_uri) which contains the URI of the
swarm leader in format of M(tcp://172.16.0.1:2376). This value may be used without additional
modification as value of option I(docker_host) in Docker Swarm modules when connecting via API.
The port always defaults to M(2376).
type: bool
default: no
include_host_uri_port:
description: Override the detected port number included in I(ansible_host_uri)
type: int
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -125,7 +135,8 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
def _get_tls_connect_params(self): def _get_tls_connect_params(self):
if self.get_option('tls') and self.get_option('cert_path') and self.get_option('key_path'): if self.get_option('tls') and self.get_option('cert_path') and self.get_option('key_path'):
# TLS with certs and no host verification # TLS with certs and no host verification
tls_config = self._get_tls_config(client_cert=(self.get_option('cert_path'), self.get_option('key_path')), tls_config = self._get_tls_config(client_cert=(self.get_option('cert_path'),
self.get_option('key_path')),
verify=False) verify=False)
return tls_config return tls_config
@ -137,12 +148,14 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
if self.get_option('tls_verify') and self.get_option('cert_path') and self.get_option('key_path'): if self.get_option('tls_verify') and self.get_option('cert_path') and self.get_option('key_path'):
# TLS with certs and host verification # TLS with certs and host verification
if self.get_option('cacert_path'): if self.get_option('cacert_path'):
tls_config = self._get_tls_config(client_cert=(self.get_option('cert_path'), self.get_option('key_path')), tls_config = self._get_tls_config(client_cert=(self.get_option('cert_path'),
self.get_option('key_path')),
ca_cert=self.get_option('cacert_path'), ca_cert=self.get_option('cacert_path'),
verify=True, verify=True,
assert_hostname=self.get_option('tls_hostname')) assert_hostname=self.get_option('tls_hostname'))
else: else:
tls_config = self._get_tls_config(client_cert=(self.get_option('cert_path'), self.get_option('key_path')), tls_config = self._get_tls_config(client_cert=(self.get_option('cert_path'),
self.get_option('key_path')),
verify=True, verify=True,
assert_hostname=self.get_option('tls_hostname')) assert_hostname=self.get_option('tls_hostname'))
@ -165,37 +178,65 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
return None return None
def _populate(self): def _populate(self):
self.client = docker.DockerClient(base_url=self.get_option('host'), tls=self._get_tls_connect_params()) self.client = docker.DockerClient(base_url=self.get_option('host'),
tls=self._get_tls_connect_params())
self.inventory.add_group('all') self.inventory.add_group('all')
self.inventory.add_group('manager') self.inventory.add_group('manager')
self.inventory.add_group('worker') self.inventory.add_group('worker')
self.inventory.add_group('leader') self.inventory.add_group('leader')
if self.get_option('include_host_uri', True):
if self.get_option('include_host_uri_port'):
host_uri_port = self.get_option('include_host_uri_port')
elif self.get_option('tls') or self.get_option('tls_verify'):
host_uri_port = "2376"
else:
host_uri_port = "2375"
try: try:
self.nodes = self.client.nodes.list() self.nodes = self.client.nodes.list()
for self.node in self.nodes: for self.node in self.nodes:
self.node_attrs = self.client.nodes.get(self.node.id).attrs self.node_attrs = self.client.nodes.get(self.node.id).attrs
self.inventory.add_host(self.node_attrs['ID']) self.inventory.add_host(self.node_attrs['ID'])
self.inventory.add_host(self.node_attrs['ID'], group=self.node_attrs['Spec']['Role']) self.inventory.add_host(self.node_attrs['ID'], group=self.node_attrs['Spec']['Role'])
self.inventory.set_variable(self.node_attrs['ID'], 'ansible_host', self.node_attrs['Status']['Addr']) self.inventory.set_variable(self.node_attrs['ID'], 'ansible_host',
self.node_attrs['Status']['Addr'])
if self.get_option('include_host_uri', True):
self.inventory.set_variable(self.node_attrs['ID'], 'ansible_host_uri',
"tcp://" + self.node_attrs['Status']['Addr'] + ":" + host_uri_port)
if self.get_option('verbose_output', True): if self.get_option('verbose_output', True):
self.inventory.set_variable(self.node_attrs['ID'], 'docker_swarm_node_attributes', self.node_attrs) self.inventory.set_variable(self.node_attrs['ID'], 'docker_swarm_node_attributes', self.node_attrs)
if 'ManagerStatus' in self.node_attrs: if 'ManagerStatus' in self.node_attrs:
if self.node_attrs['ManagerStatus'].get('Leader'): if self.node_attrs['ManagerStatus'].get('Leader'):
# This is workaround of bug in Docker when in some cases the Leader IP is 0.0.0.0 # This is workaround of bug in Docker when in some cases the Leader IP is 0.0.0.0
# Check moby/moby#35437 for details # Check moby/moby#35437 for details
self.inventory.set_variable(self.node_attrs['ID'], 'ansible_host', swarm_leader_ip = parse_address(self.node_attrs['ManagerStatus']['Addr'])[0] or \
parse_address(self.node_attrs['ManagerStatus']['Addr'])[0]) self.node_attrs['Status']['Addr']
if self.get_option('include_host_uri', True):
self.inventory.set_variable(self.node_attrs['ID'], 'ansible_host_uri', "tcp://" +
swarm_leader_ip + ":" + host_uri_port)
self.inventory.set_variable(self.node_attrs['ID'], 'ansible_host', swarm_leader_ip)
self.inventory.add_host(self.node_attrs['ID'], group='leader') self.inventory.add_host(self.node_attrs['ID'], group='leader')
# Use constructed if applicable # Use constructed if applicable
strict = self.get_option('strict') strict = self.get_option('strict')
# Composed variables # Composed variables
self._set_composite_vars(self.get_option('compose'), self.node_attrs, self.node_attrs['ID'], strict=strict) self._set_composite_vars(self.get_option('compose'),
self.node_attrs,
self.node_attrs['ID'],
strict=strict)
# Complex groups based on jinja2 conditionals, hosts that meet the conditional are added to group # Complex groups based on jinja2 conditionals, hosts that meet the conditional are added to group
self._add_host_to_composed_groups(self.get_option('groups'), self.node_attrs, self.node_attrs['ID'], strict=strict) self._add_host_to_composed_groups(self.get_option('groups'),
self.node_attrs,
self.node_attrs['ID'],
strict=strict)
# Create groups based on variable values and add the corresponding hosts to it # Create groups based on variable values and add the corresponding hosts to it
self._add_host_to_keyed_groups(self.get_option('keyed_groups'), self.node_attrs, self.node_attrs['ID'], strict=strict) self._add_host_to_keyed_groups(self.get_option('keyed_groups'),
self.node_attrs,
self.node_attrs['ID'],
strict=strict)
except Exception as e: except Exception as e:
raise AnsibleError('Unable to fetch hosts from Docker swarm API, this was the original exception: %s' % to_native(e)) raise AnsibleError('Unable to fetch hosts from Docker swarm API, this was the original exception: %s' %
to_native(e))
def verify_file(self, path): def verify_file(self, path):
"""Return the possibly of a file being consumable by this plugin.""" """Return the possibly of a file being consumable by this plugin."""
@ -205,7 +246,8 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
def parse(self, inventory, loader, path, cache=True): def parse(self, inventory, loader, path, cache=True):
if not HAS_DOCKER: if not HAS_DOCKER:
raise AnsibleError('The Docker swarm dynamic inventory plugin requires the Docker SDK for Python: https://github.com/docker/docker-py.') raise AnsibleError('The Docker swarm dynamic inventory plugin requires the Docker SDK for Python: '
'https://github.com/docker/docker-py.')
super(InventoryModule, self).parse(inventory, loader, path, cache) super(InventoryModule, self).parse(inventory, loader, path, cache)
self._read_config_data(path) self._read_config_data(path)
self._populate() self._populate()