docker_swarm: Return UnlockKey (#54490)

* Return UnlockKey

* Add changelog fragment

* Add method to check if a parameter exists in diffs

* Add method to get swarm unlock key

* Add option unlock_key

* Only return unlock key when created or changed

* Rename difference check

* Extend unlock key example

* Assert that unlock_key is a string

* Fix docker_swarm_info authors

* Don’t silence APIErrors

* Test unlock_key on unlocked swarm

* Catch APIError when retrieving unlock key

* Better return value description

* Lint

* Fix UnlockKey return value documentation

Co-Authored-By: hannseman <hannes@5monkeys.se>

* Get unlock key safely

Co-Authored-By: hannseman <hannes@5monkeys.se>

* Return None on empty UnlockKey

* Assert swarm_unlock_key is undefined if unqueried

* Add documentation about swarm_info unlock_key

* Add change log fragment for unlock_key option

* Revert "Add change log fragment for unlock_key option"

This reverts commit e3cb2325b552e5d14cc3f42b33a86bf3ee84d3b9.

* Use generator expression instead

* Restart docker more decisively

* Use systemctl kill

Co-Authored-By: hannseman <hannes@5monkeys.se>

* Try to restart docker daemon
This commit is contained in:
Hannes Ljungberg 2019-04-01 13:19:18 +02:00 committed by John R Barker
parent 21c8650180
commit e58f23b73e
8 changed files with 146 additions and 4 deletions

View file

@ -171,6 +171,7 @@ options:
description:
- If set, generate a key and use it to lock data stored on the managers.
- Docker default value is C(no).
- M(docker_swarm_info) can be used to retrieve the unlock key.
type: bool
rotate_worker_token:
description: Rotate the worker join token.
@ -250,6 +251,13 @@ swarm_facts:
returned: success
type: str
example: SWMTKN-1--xxxxx
UnlockKey:
description: The swarm unlock-key if I(autolock_managers) is C(true).
returned: on success if I(autolock_managers) is C(true)
and swarm is initialised, or if I(autolock_managers) has changed.
type: str
example: SWMKEY-1-xxx
actions:
description: Provides the actions done on the swarm.
returned: when action failed.
@ -269,6 +277,7 @@ except ImportError:
from ansible.module_utils.docker.common import (
DockerBaseClass,
DifferenceTracker,
LooseVersion,
)
from ansible.module_utils.docker.swarm import AnsibleDockerSwarmClient
@ -424,6 +433,8 @@ class SwarmManager(DockerBaseClass):
self.differences = DifferenceTracker()
self.parameters = TaskParameters.from_ansible_params(client)
self.created = False
def __call__(self):
choice_map = {
"present": self.init_swarm,
@ -450,11 +461,29 @@ class SwarmManager(DockerBaseClass):
data = self.client.inspect_swarm()
json_str = json.dumps(data, ensure_ascii=False)
self.swarm_info = json.loads(json_str)
self.results['changed'] = False
self.results['swarm_facts'] = self.swarm_info
unlock_key = self.get_unlock_key()
self.swarm_info.update(unlock_key)
except APIError:
return
def get_unlock_key(self):
default = {'UnlockKey': None}
if not self.has_swarm_lock_changed():
return default
try:
return self.client.get_unlock_key() or default
except APIError:
return default
def has_swarm_lock_changed(self):
return self.parameters.autolock_managers and (
self.created or self.differences.has_difference_for('autolock_managers')
)
def init_swarm(self):
if not self.force and self.client.check_if_swarm_manager():
self.__update_swarm()
@ -479,11 +508,16 @@ class SwarmManager(DockerBaseClass):
if not self.client.check_if_swarm_manager():
if not self.check_mode:
self.client.fail("Swarm not created or other error!")
self.created = True
self.inspect_swarm()
self.results['actions'].append("New Swarm cluster created: %s" % (self.swarm_info.get('ID')))
self.differences.add('state', parameter='present', active='absent')
self.results['changed'] = True
self.results['swarm_facts'] = {u'JoinTokens': self.swarm_info.get('JoinTokens')}
self.results['swarm_facts'] = {
'JoinTokens': self.swarm_info.get('JoinTokens'),
'UnlockKey': self.swarm_info.get('UnlockKey')
}
def __update_swarm(self):
try:

View file

@ -29,7 +29,7 @@ description:
version_added: "2.8"
author:
- Piotr Wojciechowski (@wojciechowskipiotr)
- Piotr Wojciechowski (@WojciechowskiPiotr)
options:
nodes:
@ -68,6 +68,11 @@ options:
- See L(the docker documentation,https://docs.docker.com/engine/reference/commandline/service_ps/#filtering)
for more information on possible filters.
type: dict
unlock_key:
description:
- Whether to retrieve the swarm unlock key.
type: bool
default: no
verbose_output:
description:
- When set to C(yes) and I(nodes), I(services) or I(tasks) is set to C(yes)
@ -121,6 +126,15 @@ EXAMPLES = '''
- debug:
var: result.swarm_facts
- name: Get the swarm unlock key
docker_swarm_info:
unlock_key: yes
register: result
- debug:
var: result.swarm_unlock_key
'''
RETURN = '''
@ -143,13 +157,17 @@ docker_swarm_manager:
- Only if this one is C(true), the module will not fail.
returned: both on success and on error
type: bool
swarm_facts:
description:
- Facts representing the basic state of the docker Swarm cluster.
- Contains tokens to connect to the Swarm
returned: always
type: dict
swarm_unlock_key:
description:
- Contains the key needed to unlock the swarm.
returned: When I(unlock_key) is C(true).
type: str
nodes:
description:
- List of dict objects containing the basic information about each volume.
@ -208,6 +226,8 @@ class DockerSwarmManager(DockerBaseClass):
filter_name = docker_object + "_filters"
filters = clean_dict_booleans_for_docker_api(client.module.params.get(filter_name))
self.results[returned_name] = self.get_docker_items_list(docker_object, filters)
if self.client.module.params['unlock_key']:
self.results['swarm_unlock_key'] = self.get_docker_swarm_unlock_key()
def get_docker_swarm_facts(self):
try:
@ -305,6 +325,10 @@ class DockerSwarmManager(DockerBaseClass):
return object_essentials
def get_docker_swarm_unlock_key(self):
unlock_key = self.client.get_unlock_key() or {}
return unlock_key.get('UnlockKey') or None
def main():
argument_spec = dict(
@ -314,14 +338,19 @@ def main():
tasks_filters=dict(type='dict'),
services=dict(type='bool', default=False),
services_filters=dict(type='dict'),
unlock_key=dict(type='bool', default=False),
verbose_output=dict(type='bool', default=False),
)
option_minimal_versions = dict(
unlock_key=dict(docker_py_version='2.7.0', docker_api_version='1.25'),
)
client = AnsibleDockerSwarmClient(
argument_spec=argument_spec,
supports_check_mode=True,
min_docker_version='1.10.0',
min_docker_api_version='1.24',
option_minimal_versions=option_minimal_versions,
fail_results=dict(
can_talk_to_docker=False,
docker_swarm_active=False,