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:
|
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()
|
||||||
|
|
Loading…
Reference in a new issue