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:
parent
259b2e06a4
commit
955da2a095
1 changed files with 54 additions and 12 deletions
|
@ -56,6 +56,16 @@ DOCUMENTATION = '''
|
|||
tls_hostname:
|
||||
description: When verifying the authenticity of the Docker Host server, provide the expected name of the server.
|
||||
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 = '''
|
||||
|
@ -125,7 +135,8 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
|
|||
def _get_tls_connect_params(self):
|
||||
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_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)
|
||||
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'):
|
||||
# TLS with certs and host verification
|
||||
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'),
|
||||
verify=True,
|
||||
assert_hostname=self.get_option('tls_hostname'))
|
||||
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,
|
||||
assert_hostname=self.get_option('tls_hostname'))
|
||||
|
||||
|
@ -165,37 +178,65 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
|
|||
return None
|
||||
|
||||
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('manager')
|
||||
self.inventory.add_group('worker')
|
||||
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:
|
||||
self.nodes = self.client.nodes.list()
|
||||
for self.node in self.nodes:
|
||||
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'], 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):
|
||||
self.inventory.set_variable(self.node_attrs['ID'], 'docker_swarm_node_attributes', self.node_attrs)
|
||||
if 'ManagerStatus' in self.node_attrs:
|
||||
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
|
||||
# Check moby/moby#35437 for details
|
||||
self.inventory.set_variable(self.node_attrs['ID'], 'ansible_host',
|
||||
parse_address(self.node_attrs['ManagerStatus']['Addr'])[0])
|
||||
swarm_leader_ip = parse_address(self.node_attrs['ManagerStatus']['Addr'])[0] or \
|
||||
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')
|
||||
# Use constructed if applicable
|
||||
strict = self.get_option('strict')
|
||||
# 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
|
||||
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
|
||||
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:
|
||||
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):
|
||||
"""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):
|
||||
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)
|
||||
self._read_config_data(path)
|
||||
self._populate()
|
||||
|
|
Loading…
Reference in a new issue