docker_swarm update to use shared Swarm library (#52886)
* docker_swarm: Update code to use AnsibleDockerSwarmClient instead of AnsibleDockerClient * docker_swarm: Update check_if_swarm_node_is_down() with repetitive attempts to check node status to reflect original method implementation * docker_swarm: Add information that `state: inspect` will be removed in future release * docker_swarm: Fix sanity error * docker_swarm: Check_mode conditional for failing during the swarm init * docker_swarm: Small cleanup of a code * docker_swarm: Moving the warning message before dispatching * Commit to solve problems with Shippable
This commit is contained in:
parent
c6ae23062b
commit
72bdcdfff2
2 changed files with 35 additions and 53 deletions
|
@ -3,6 +3,7 @@
|
|||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
import json
|
||||
from time import sleep
|
||||
|
||||
try:
|
||||
from docker.errors import APIError
|
||||
|
@ -108,23 +109,29 @@ class AnsibleDockerSwarmClient(AnsibleDockerClient):
|
|||
return True
|
||||
return False
|
||||
|
||||
def check_if_swarm_node_is_down(self, node_id=None):
|
||||
def check_if_swarm_node_is_down(self, node_id=None, repeat_check=1):
|
||||
"""
|
||||
Checks if node status on Swarm manager is 'down'. If node_id is provided it query manager about
|
||||
node specified in parameter, otherwise it query manager itself. If run on Swarm Worker node or
|
||||
host that is not part of Swarm it will fail the playbook
|
||||
|
||||
:param repeat_check: number of check attempts with 5 seconds delay between them, by default check only once
|
||||
:param node_id: node ID or name, if None then method will try to get node_id of host module run on
|
||||
:return:
|
||||
True if node is part of swarm but its state is down, False otherwise
|
||||
"""
|
||||
|
||||
if repeat_check < 1:
|
||||
repeat_check = 1
|
||||
|
||||
if node_id is None:
|
||||
node_id = self.get_swarm_node_id()
|
||||
|
||||
node_info = self.get_node_inspect(node_id=node_id)
|
||||
if node_info['Status']['State'] == 'down':
|
||||
return True
|
||||
for retry in range(0, repeat_check):
|
||||
node_info = self.get_node_inspect(node_id=node_id)
|
||||
if node_info['Status']['State'] == 'down':
|
||||
return True
|
||||
sleep(5)
|
||||
return False
|
||||
|
||||
def get_node_inspect(self, node_id=None, skip_missing=False):
|
||||
|
|
|
@ -159,6 +159,7 @@ requirements:
|
|||
- Docker API >= 1.25
|
||||
author:
|
||||
- Thierry Bouvet (@tbouvet)
|
||||
- Piotr Wojciechowski (@WojciechowskiPiotr)
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
|
@ -229,7 +230,7 @@ actions:
|
|||
'''
|
||||
|
||||
import json
|
||||
from time import sleep
|
||||
|
||||
try:
|
||||
from docker.errors import APIError
|
||||
except ImportError:
|
||||
|
@ -237,10 +238,12 @@ except ImportError:
|
|||
pass
|
||||
|
||||
from ansible.module_utils.docker.common import (
|
||||
AnsibleDockerClient,
|
||||
DockerBaseClass,
|
||||
DifferenceTracker,
|
||||
)
|
||||
|
||||
from ansible.module_utils.docker.swarm import AnsibleDockerSwarmClient
|
||||
|
||||
from ansible.module_utils._text import to_native
|
||||
|
||||
|
||||
|
@ -253,6 +256,7 @@ class TaskParameters(DockerBaseClass):
|
|||
self.force_new_cluster = None
|
||||
self.remote_addrs = None
|
||||
self.join_token = None
|
||||
self.force = None
|
||||
|
||||
# Spec
|
||||
self.snapshot_interval = None
|
||||
|
@ -389,6 +393,11 @@ class SwarmManager(DockerBaseClass):
|
|||
"inspect": self.inspect_swarm
|
||||
}
|
||||
|
||||
if self.state == 'inspect':
|
||||
self.client.module.deprecate(
|
||||
"The 'inspect' state is deprecated, please use 'docker_swarm_facts' to inspect swarm cluster",
|
||||
version='2.12')
|
||||
|
||||
choice_map.get(self.state)()
|
||||
|
||||
if self.client.module._diff or self.parameters.debug:
|
||||
|
@ -396,15 +405,6 @@ class SwarmManager(DockerBaseClass):
|
|||
diff['before'], diff['after'] = self.differences.get_before_after()
|
||||
self.results['diff'] = diff
|
||||
|
||||
def __isSwarmManager(self):
|
||||
try:
|
||||
data = self.client.inspect_swarm()
|
||||
json_str = json.dumps(data, ensure_ascii=False)
|
||||
self.swarm_info = json.loads(json_str)
|
||||
return True
|
||||
except APIError:
|
||||
return False
|
||||
|
||||
def inspect_swarm(self):
|
||||
try:
|
||||
data = self.client.inspect_swarm()
|
||||
|
@ -416,7 +416,7 @@ class SwarmManager(DockerBaseClass):
|
|||
return
|
||||
|
||||
def init_swarm(self):
|
||||
if self.__isSwarmManager():
|
||||
if self.client.check_if_swarm_manager():
|
||||
self.__update_swarm()
|
||||
return
|
||||
|
||||
|
@ -428,7 +428,10 @@ class SwarmManager(DockerBaseClass):
|
|||
except APIError as exc:
|
||||
self.client.fail("Can not create a new Swarm Cluster: %s" % to_native(exc))
|
||||
|
||||
self.__isSwarmManager()
|
||||
if not self.client.check_if_swarm_manager():
|
||||
if not self.check_mode:
|
||||
self.client.fail("Swarm not created or other error!")
|
||||
self.inspect_swarm()
|
||||
self.results['actions'].append("New Swarm cluster created: %s" % (self.swarm_info.get('ID')))
|
||||
self.differences.add('state', parameter='absent', active='present')
|
||||
self.results['changed'] = True
|
||||
|
@ -460,26 +463,15 @@ class SwarmManager(DockerBaseClass):
|
|||
self.results['actions'].append("Swarm cluster updated")
|
||||
self.results['changed'] = True
|
||||
|
||||
def __isSwarmNode(self):
|
||||
info = self.client.info()
|
||||
if info:
|
||||
json_str = json.dumps(info, ensure_ascii=False)
|
||||
self.swarm_info = json.loads(json_str)
|
||||
if self.swarm_info['Swarm']['NodeID']:
|
||||
return True
|
||||
if self.swarm_info['Swarm']['LocalNodeState'] in ('active', 'pending', 'locked'):
|
||||
return True
|
||||
return False
|
||||
|
||||
def join(self):
|
||||
if self.__isSwarmNode():
|
||||
if self.client.check_if_swarm_node():
|
||||
self.results['actions'].append("This node is already part of a swarm.")
|
||||
return
|
||||
if not self.check_mode:
|
||||
try:
|
||||
self.client.join_swarm(
|
||||
remote_addrs=self.parameters.remote_addrs, join_token=self.parameters.join_token, listen_addr=self.parameters.listen_addr,
|
||||
advertise_addr=self.parameters.advertise_addr)
|
||||
remote_addrs=self.parameters.remote_addrs, join_token=self.parameters.join_token,
|
||||
listen_addr=self.parameters.listen_addr, advertise_addr=self.parameters.advertise_addr)
|
||||
except APIError as exc:
|
||||
self.client.fail("Can not join the Swarm Cluster: %s" % to_native(exc))
|
||||
self.results['actions'].append("New node is added to swarm cluster")
|
||||
|
@ -487,7 +479,7 @@ class SwarmManager(DockerBaseClass):
|
|||
self.results['changed'] = True
|
||||
|
||||
def leave(self):
|
||||
if not(self.__isSwarmNode()):
|
||||
if not(self.client.check_if_swarm_node()):
|
||||
self.results['actions'].append("This node is not part of a swarm.")
|
||||
return
|
||||
if not self.check_mode:
|
||||
|
@ -499,33 +491,16 @@ class SwarmManager(DockerBaseClass):
|
|||
self.differences.add('joined', parameter='absent', active='present')
|
||||
self.results['changed'] = True
|
||||
|
||||
def __get_node_info(self):
|
||||
try:
|
||||
node_info = self.client.inspect_node(node_id=self.parameters.node_id)
|
||||
except APIError as exc:
|
||||
raise exc
|
||||
json_str = json.dumps(node_info, ensure_ascii=False)
|
||||
node_info = json.loads(json_str)
|
||||
return node_info
|
||||
|
||||
def __check_node_is_down(self):
|
||||
for _x in range(0, 5):
|
||||
node_info = self.__get_node_info()
|
||||
if node_info['Status']['State'] == 'down':
|
||||
return True
|
||||
sleep(5)
|
||||
return False
|
||||
|
||||
def remove(self):
|
||||
if not(self.__isSwarmManager()):
|
||||
if not(self.client.check_if_swarm_manager()):
|
||||
self.client.fail("This node is not a manager.")
|
||||
|
||||
try:
|
||||
status_down = self.__check_node_is_down()
|
||||
status_down = self.client.check_if_swarm_node_is_down(repeat_check=5)
|
||||
except APIError:
|
||||
return
|
||||
|
||||
if not(status_down):
|
||||
if not status_down:
|
||||
self.client.fail("Can not remove the node. The status node is ready and not down.")
|
||||
|
||||
if not self.check_mode:
|
||||
|
@ -577,7 +552,7 @@ def main():
|
|||
ca_force_rotate=dict(docker_api_version='1.30'),
|
||||
)
|
||||
|
||||
client = AnsibleDockerClient(
|
||||
client = AnsibleDockerSwarmClient(
|
||||
argument_spec=argument_spec,
|
||||
supports_check_mode=True,
|
||||
required_if=required_if,
|
||||
|
|
Loading…
Reference in a new issue