mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-04-19 10:21:30 +00:00
Reformat everything.
This commit is contained in:
parent
3f2213791a
commit
340ff8586d
1008 changed files with 61301 additions and 58309 deletions
|
|
@ -15,9 +15,8 @@ display = Display()
|
|||
|
||||
|
||||
class ActionModule(ActionBase):
|
||||
|
||||
# Keep internal params away from user interactions
|
||||
_VALID_ARGS = frozenset(('path', 'state', 'table', 'noflush', 'counters', 'modprobe', 'ip_version', 'wait'))
|
||||
_VALID_ARGS = frozenset(("path", "state", "table", "noflush", "counters", "modprobe", "ip_version", "wait"))
|
||||
DEFAULT_SUDOABLE = True
|
||||
|
||||
@staticmethod
|
||||
|
|
@ -27,7 +26,8 @@ class ActionModule(ActionBase):
|
|||
"is set to 'restored'. To enable its rollback feature (that needs the "
|
||||
"module to run asynchronously on the remote), please set task attribute "
|
||||
f"'poll' (={task_poll}) to 0, and 'async' (={task_async}) to a value >2 and not greater than "
|
||||
f"'ansible_timeout' (={max_timeout}) (recommended).")
|
||||
f"'ansible_timeout' (={max_timeout}) (recommended)."
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def msg_warning__no_async_is_no_rollback(task_poll, task_async, max_timeout):
|
||||
|
|
@ -37,7 +37,8 @@ class ActionModule(ActionBase):
|
|||
"regain it before fixing firewall rules through a serial console, or any "
|
||||
f"other way except SSH. Please set task attribute 'poll' (={task_poll}) to 0, and "
|
||||
f"'async' (={task_async}) to a value >2 and not greater than 'ansible_timeout' (={max_timeout}) "
|
||||
"(recommended).")
|
||||
"(recommended)."
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def msg_warning__async_greater_than_timeout(task_poll, task_async, max_timeout):
|
||||
|
|
@ -46,44 +47,48 @@ class ActionModule(ActionBase):
|
|||
"but with settings that will lead this rollback to happen AFTER that the "
|
||||
"controller will reach its own timeout. Please set task attribute 'poll' "
|
||||
f"(={task_poll}) to 0, and 'async' (={task_async}) to a value >2 and not greater than "
|
||||
f"'ansible_timeout' (={max_timeout}) (recommended).")
|
||||
f"'ansible_timeout' (={max_timeout}) (recommended)."
|
||||
)
|
||||
|
||||
def _async_result(self, async_status_args, task_vars, timeout):
|
||||
'''
|
||||
"""
|
||||
Retrieve results of the asynchronous task, and display them in place of
|
||||
the async wrapper results (those with the ansible_job_id key).
|
||||
'''
|
||||
"""
|
||||
async_status = self._task.copy()
|
||||
async_status.args = async_status_args
|
||||
async_status.action = 'ansible.builtin.async_status'
|
||||
async_status.action = "ansible.builtin.async_status"
|
||||
async_status.async_val = 0
|
||||
async_action = self._shared_loader_obj.action_loader.get(
|
||||
async_status.action, task=async_status, connection=self._connection,
|
||||
play_context=self._play_context, loader=self._loader, templar=self._templar,
|
||||
shared_loader_obj=self._shared_loader_obj)
|
||||
async_status.action,
|
||||
task=async_status,
|
||||
connection=self._connection,
|
||||
play_context=self._play_context,
|
||||
loader=self._loader,
|
||||
templar=self._templar,
|
||||
shared_loader_obj=self._shared_loader_obj,
|
||||
)
|
||||
|
||||
if async_status.args['mode'] == 'cleanup':
|
||||
if async_status.args["mode"] == "cleanup":
|
||||
return async_action.run(task_vars=task_vars)
|
||||
|
||||
# At least one iteration is required, even if timeout is 0.
|
||||
for dummy in range(max(1, timeout)):
|
||||
async_result = async_action.run(task_vars=task_vars)
|
||||
if async_result.get('finished', 0) == 1:
|
||||
if async_result.get("finished", 0) == 1:
|
||||
break
|
||||
time.sleep(min(1, timeout))
|
||||
|
||||
return async_result
|
||||
|
||||
def run(self, tmp=None, task_vars=None):
|
||||
|
||||
self._supports_check_mode = True
|
||||
self._supports_async = True
|
||||
|
||||
result = super().run(tmp, task_vars)
|
||||
del tmp # tmp no longer has any effect
|
||||
|
||||
if not result.get('skipped'):
|
||||
|
||||
if not result.get("skipped"):
|
||||
# FUTURE: better to let _execute_module calculate this internally?
|
||||
wrap_async = self._task.async_val and not self._connection.has_native_async
|
||||
|
||||
|
|
@ -98,41 +103,38 @@ class ActionModule(ActionBase):
|
|||
starter_cmd = None
|
||||
confirm_cmd = None
|
||||
|
||||
if module_args.get('state', None) == 'restored':
|
||||
if module_args.get("state", None) == "restored":
|
||||
if not wrap_async:
|
||||
if not check_mode:
|
||||
display.warning(self.msg_error__async_and_poll_not_zero(
|
||||
task_poll,
|
||||
task_async,
|
||||
max_timeout))
|
||||
display.warning(self.msg_error__async_and_poll_not_zero(task_poll, task_async, max_timeout))
|
||||
elif task_poll:
|
||||
raise AnsibleActionFail(self.msg_warning__no_async_is_no_rollback(
|
||||
task_poll,
|
||||
task_async,
|
||||
max_timeout))
|
||||
raise AnsibleActionFail(
|
||||
self.msg_warning__no_async_is_no_rollback(task_poll, task_async, max_timeout)
|
||||
)
|
||||
else:
|
||||
if task_async > max_timeout and not check_mode:
|
||||
display.warning(self.msg_warning__async_greater_than_timeout(
|
||||
task_poll,
|
||||
task_async,
|
||||
max_timeout))
|
||||
display.warning(
|
||||
self.msg_warning__async_greater_than_timeout(task_poll, task_async, max_timeout)
|
||||
)
|
||||
|
||||
# inject the async directory based on the shell option into the
|
||||
# module args
|
||||
async_dir = self.get_shell_option('async_dir', default="~/.ansible_async")
|
||||
async_dir = self.get_shell_option("async_dir", default="~/.ansible_async")
|
||||
|
||||
# Bind the loop max duration to consistent values on both
|
||||
# remote and local sides (if not the same, make the loop
|
||||
# longer on the controller); and set a backup file path.
|
||||
module_args['_timeout'] = task_async
|
||||
module_args['_back'] = f'{async_dir}/iptables.state'
|
||||
async_status_args = dict(mode='status')
|
||||
module_args["_timeout"] = task_async
|
||||
module_args["_back"] = f"{async_dir}/iptables.state"
|
||||
async_status_args = dict(mode="status")
|
||||
confirm_cmd = f"rm -f {module_args['_back']}"
|
||||
starter_cmd = f"touch {module_args['_back']}.starter"
|
||||
remaining_time = max(task_async, max_timeout)
|
||||
|
||||
# do work!
|
||||
result = merge_hash(result, self._execute_module(module_args=module_args, task_vars=task_vars, wrap_async=wrap_async))
|
||||
result = merge_hash(
|
||||
result, self._execute_module(module_args=module_args, task_vars=task_vars, wrap_async=wrap_async)
|
||||
)
|
||||
|
||||
# Then the 3-steps "go ahead or rollback":
|
||||
# 1. Catch early errors of the module (in asynchronous task) if any.
|
||||
|
|
@ -140,9 +142,9 @@ class ActionModule(ActionBase):
|
|||
# 2. Reset connection to ensure a persistent one will not be reused.
|
||||
# 3. Confirm the restored state by removing the backup on the remote.
|
||||
# Retrieve the results of the asynchronous task to return them.
|
||||
if '_back' in module_args:
|
||||
async_status_args['jid'] = result.get('ansible_job_id', None)
|
||||
if async_status_args['jid'] is None:
|
||||
if "_back" in module_args:
|
||||
async_status_args["jid"] = result.get("ansible_job_id", None)
|
||||
if async_status_args["jid"] is None:
|
||||
raise AnsibleActionFail("Unable to get 'ansible_job_id'.")
|
||||
|
||||
# Catch early errors due to missing mandatory option, bad
|
||||
|
|
@ -156,7 +158,7 @@ class ActionModule(ActionBase):
|
|||
|
||||
# As the main command is not yet executed on the target, here
|
||||
# 'finished' means 'failed before main command be executed'.
|
||||
if not result['finished']:
|
||||
if not result["finished"]:
|
||||
try:
|
||||
self._connection.reset()
|
||||
except AttributeError:
|
||||
|
|
@ -178,16 +180,16 @@ class ActionModule(ActionBase):
|
|||
result = merge_hash(result, self._async_result(async_status_args, task_vars, remaining_time))
|
||||
|
||||
# Cleanup async related stuff and internal params
|
||||
for key in ('ansible_job_id', 'results_file', 'started', 'finished'):
|
||||
for key in ("ansible_job_id", "results_file", "started", "finished"):
|
||||
if result.get(key):
|
||||
del result[key]
|
||||
|
||||
if result.get('invocation', {}).get('module_args'):
|
||||
for key in ('_back', '_timeout', '_async_dir', 'jid'):
|
||||
if result['invocation']['module_args'].get(key):
|
||||
del result['invocation']['module_args'][key]
|
||||
if result.get("invocation", {}).get("module_args"):
|
||||
for key in ("_back", "_timeout", "_async_dir", "jid"):
|
||||
if result["invocation"]["module_args"].get(key):
|
||||
del result["invocation"]["module_args"][key]
|
||||
|
||||
async_status_args['mode'] = 'cleanup'
|
||||
async_status_args["mode"] = "cleanup"
|
||||
dummy = self._async_result(async_status_args, task_vars, 0)
|
||||
|
||||
if not wrap_async:
|
||||
|
|
|
|||
|
|
@ -26,35 +26,31 @@ class TimedOutException(Exception):
|
|||
|
||||
class ActionModule(ActionBase):
|
||||
TRANSFERS_FILES = False
|
||||
_VALID_ARGS = frozenset((
|
||||
'msg',
|
||||
'delay',
|
||||
'search_paths'
|
||||
))
|
||||
_VALID_ARGS = frozenset(("msg", "delay", "search_paths"))
|
||||
|
||||
DEFAULT_CONNECT_TIMEOUT = None
|
||||
DEFAULT_PRE_SHUTDOWN_DELAY = 0
|
||||
DEFAULT_SHUTDOWN_MESSAGE = 'Shut down initiated by Ansible'
|
||||
DEFAULT_SHUTDOWN_COMMAND = 'shutdown'
|
||||
DEFAULT_SHUTDOWN_MESSAGE = "Shut down initiated by Ansible"
|
||||
DEFAULT_SHUTDOWN_COMMAND = "shutdown"
|
||||
DEFAULT_SHUTDOWN_COMMAND_ARGS = '-h {delay_min} "{message}"'
|
||||
DEFAULT_SUDOABLE = True
|
||||
|
||||
SHUTDOWN_COMMANDS = {
|
||||
'alpine': 'poweroff',
|
||||
'vmkernel': 'halt',
|
||||
"alpine": "poweroff",
|
||||
"vmkernel": "halt",
|
||||
}
|
||||
|
||||
SHUTDOWN_COMMAND_ARGS = {
|
||||
'alpine': '',
|
||||
'void': '-h +{delay_min} "{message}"',
|
||||
'freebsd': '-p +{delay_sec}s "{message}"',
|
||||
'linux': DEFAULT_SHUTDOWN_COMMAND_ARGS,
|
||||
'macosx': '-h +{delay_min} "{message}"',
|
||||
'openbsd': '-h +{delay_min} "{message}"',
|
||||
'solaris': '-y -g {delay_sec} -i 5 "{message}"',
|
||||
'sunos': '-y -g {delay_sec} -i 5 "{message}"',
|
||||
'vmkernel': '-d {delay_sec}',
|
||||
'aix': '-Fh',
|
||||
"alpine": "",
|
||||
"void": '-h +{delay_min} "{message}"',
|
||||
"freebsd": '-p +{delay_sec}s "{message}"',
|
||||
"linux": DEFAULT_SHUTDOWN_COMMAND_ARGS,
|
||||
"macosx": '-h +{delay_min} "{message}"',
|
||||
"openbsd": '-h +{delay_min} "{message}"',
|
||||
"solaris": '-y -g {delay_sec} -i 5 "{message}"',
|
||||
"sunos": '-y -g {delay_sec} -i 5 "{message}"',
|
||||
"vmkernel": "-d {delay_sec}",
|
||||
"aix": "-Fh",
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
|
@ -62,7 +58,7 @@ class ActionModule(ActionBase):
|
|||
|
||||
@property
|
||||
def delay(self):
|
||||
return self._check_delay('delay', self.DEFAULT_PRE_SHUTDOWN_DELAY)
|
||||
return self._check_delay("delay", self.DEFAULT_PRE_SHUTDOWN_DELAY)
|
||||
|
||||
def _check_delay(self, key, default):
|
||||
"""Ensure that the value is positive or zero"""
|
||||
|
|
@ -75,29 +71,28 @@ class ActionModule(ActionBase):
|
|||
"""Get dist+version specific args first, then distribution, then family, lastly use default"""
|
||||
attr = getattr(self, variable_name)
|
||||
value = attr.get(
|
||||
distribution['name'] + distribution['version'],
|
||||
attr.get(
|
||||
distribution['name'],
|
||||
attr.get(
|
||||
distribution['family'],
|
||||
getattr(self, default_value))))
|
||||
distribution["name"] + distribution["version"],
|
||||
attr.get(distribution["name"], attr.get(distribution["family"], getattr(self, default_value))),
|
||||
)
|
||||
return value
|
||||
|
||||
def get_distribution(self, task_vars):
|
||||
# FIXME: only execute the module if we don't already have the facts we need
|
||||
distribution = {}
|
||||
display.debug(f'{self._task.action}: running setup module to get distribution')
|
||||
display.debug(f"{self._task.action}: running setup module to get distribution")
|
||||
module_output = self._execute_module(
|
||||
task_vars=task_vars,
|
||||
module_name='ansible.legacy.setup',
|
||||
module_args={'gather_subset': 'min'})
|
||||
task_vars=task_vars, module_name="ansible.legacy.setup", module_args={"gather_subset": "min"}
|
||||
)
|
||||
try:
|
||||
if module_output.get('failed', False):
|
||||
raise AnsibleError(f"Failed to determine system distribution. {fmt(module_output, 'module_stdout')}, {fmt(module_output, 'module_stderr')}")
|
||||
distribution['name'] = module_output['ansible_facts']['ansible_distribution'].lower()
|
||||
distribution['version'] = to_text(
|
||||
module_output['ansible_facts']['ansible_distribution_version'].split('.')[0])
|
||||
distribution['family'] = to_text(module_output['ansible_facts']['ansible_os_family'].lower())
|
||||
if module_output.get("failed", False):
|
||||
raise AnsibleError(
|
||||
f"Failed to determine system distribution. {fmt(module_output, 'module_stdout')}, {fmt(module_output, 'module_stderr')}"
|
||||
)
|
||||
distribution["name"] = module_output["ansible_facts"]["ansible_distribution"].lower()
|
||||
distribution["version"] = to_text(
|
||||
module_output["ansible_facts"]["ansible_distribution_version"].split(".")[0]
|
||||
)
|
||||
distribution["family"] = to_text(module_output["ansible_facts"]["ansible_os_family"].lower())
|
||||
display.debug(f"{self._task.action}: distribution: {distribution}")
|
||||
return distribution
|
||||
except KeyError as ke:
|
||||
|
|
@ -105,22 +100,20 @@ class ActionModule(ActionBase):
|
|||
|
||||
def get_shutdown_command(self, task_vars, distribution):
|
||||
def find_command(command, find_search_paths):
|
||||
display.debug(f'{self._task.action}: running find module looking in {find_search_paths} to get path for "{command}"')
|
||||
display.debug(
|
||||
f'{self._task.action}: running find module looking in {find_search_paths} to get path for "{command}"'
|
||||
)
|
||||
find_result = self._execute_module(
|
||||
task_vars=task_vars,
|
||||
# prevent collection search by calling with ansible.legacy (still allows library/ override of find)
|
||||
module_name='ansible.legacy.find',
|
||||
module_args={
|
||||
'paths': find_search_paths,
|
||||
'patterns': [command],
|
||||
'file_type': 'any'
|
||||
}
|
||||
module_name="ansible.legacy.find",
|
||||
module_args={"paths": find_search_paths, "patterns": [command], "file_type": "any"},
|
||||
)
|
||||
return [x['path'] for x in find_result['files']]
|
||||
return [x["path"] for x in find_result["files"]]
|
||||
|
||||
shutdown_bin = self._get_value_from_facts('SHUTDOWN_COMMANDS', distribution, 'DEFAULT_SHUTDOWN_COMMAND')
|
||||
default_search_paths = ['/sbin', '/usr/sbin', '/usr/local/sbin']
|
||||
search_paths = self._task.args.get('search_paths', default_search_paths)
|
||||
shutdown_bin = self._get_value_from_facts("SHUTDOWN_COMMANDS", distribution, "DEFAULT_SHUTDOWN_COMMAND")
|
||||
default_search_paths = ["/sbin", "/usr/sbin", "/usr/local/sbin"]
|
||||
search_paths = self._task.args.get("search_paths", default_search_paths)
|
||||
|
||||
# FIXME: switch all this to user arg spec validation methods when they are available
|
||||
# Convert bare strings to a list
|
||||
|
|
@ -138,26 +131,28 @@ class ActionModule(ActionBase):
|
|||
|
||||
full_path = find_command(shutdown_bin, search_paths) # find the path to the shutdown command
|
||||
if not full_path: # if we could not find the shutdown command
|
||||
|
||||
# tell the user we will try with systemd
|
||||
display.vvv(f'Unable to find command "{shutdown_bin}" in search paths: {search_paths}, will attempt a shutdown using systemd directly.')
|
||||
systemctl_search_paths = ['/bin', '/usr/bin']
|
||||
full_path = find_command('systemctl', systemctl_search_paths) # find the path to the systemctl command
|
||||
display.vvv(
|
||||
f'Unable to find command "{shutdown_bin}" in search paths: {search_paths}, will attempt a shutdown using systemd directly.'
|
||||
)
|
||||
systemctl_search_paths = ["/bin", "/usr/bin"]
|
||||
full_path = find_command("systemctl", systemctl_search_paths) # find the path to the systemctl command
|
||||
if not full_path: # if we couldn't find systemctl
|
||||
raise AnsibleError(
|
||||
f'Could not find command "{shutdown_bin}" in search paths: {search_paths} or systemctl'
|
||||
f' command in search paths: {systemctl_search_paths}, unable to shutdown.') # we give up here
|
||||
f" command in search paths: {systemctl_search_paths}, unable to shutdown."
|
||||
) # we give up here
|
||||
else:
|
||||
return f"{full_path[0]} poweroff" # done, since we cannot use args with systemd shutdown
|
||||
|
||||
# systemd case taken care of, here we add args to the command
|
||||
args = self._get_value_from_facts('SHUTDOWN_COMMAND_ARGS', distribution, 'DEFAULT_SHUTDOWN_COMMAND_ARGS')
|
||||
args = self._get_value_from_facts("SHUTDOWN_COMMAND_ARGS", distribution, "DEFAULT_SHUTDOWN_COMMAND_ARGS")
|
||||
# Convert seconds to minutes. If less that 60, set it to 0.
|
||||
delay_sec = self.delay
|
||||
shutdown_message = self._task.args.get('msg', self.DEFAULT_SHUTDOWN_MESSAGE)
|
||||
shutdown_message = self._task.args.get("msg", self.DEFAULT_SHUTDOWN_MESSAGE)
|
||||
|
||||
af = args.format(delay_sec=delay_sec, delay_min=delay_sec // 60, message=shutdown_message)
|
||||
return f'{full_path[0]} {af}'
|
||||
return f"{full_path[0]} {af}"
|
||||
|
||||
def perform_shutdown(self, task_vars, distribution):
|
||||
result = {}
|
||||
|
|
@ -169,23 +164,24 @@ class ActionModule(ActionBase):
|
|||
display.vvv(f"{self._task.action}: shutting down server...")
|
||||
display.debug(f"{self._task.action}: shutting down server with command '{shutdown_command_exec}'")
|
||||
if self._play_context.check_mode:
|
||||
shutdown_result['rc'] = 0
|
||||
shutdown_result["rc"] = 0
|
||||
else:
|
||||
shutdown_result = self._low_level_execute_command(shutdown_command_exec, sudoable=self.DEFAULT_SUDOABLE)
|
||||
except AnsibleConnectionFailure as e:
|
||||
# If the connection is closed too quickly due to the system being shutdown, carry on
|
||||
display.debug(
|
||||
f'{self._task.action}: AnsibleConnectionFailure caught and handled: {e}')
|
||||
shutdown_result['rc'] = 0
|
||||
display.debug(f"{self._task.action}: AnsibleConnectionFailure caught and handled: {e}")
|
||||
shutdown_result["rc"] = 0
|
||||
|
||||
if shutdown_result['rc'] != 0:
|
||||
result['failed'] = True
|
||||
result['shutdown'] = False
|
||||
result['msg'] = f"Shutdown command failed. Error was {fmt(shutdown_result, 'stdout')}, {fmt(shutdown_result, 'stderr')}"
|
||||
if shutdown_result["rc"] != 0:
|
||||
result["failed"] = True
|
||||
result["shutdown"] = False
|
||||
result["msg"] = (
|
||||
f"Shutdown command failed. Error was {fmt(shutdown_result, 'stdout')}, {fmt(shutdown_result, 'stderr')}"
|
||||
)
|
||||
return result
|
||||
|
||||
result['failed'] = False
|
||||
result['shutdown_command'] = shutdown_command_exec
|
||||
result["failed"] = False
|
||||
result["shutdown_command"] = shutdown_command_exec
|
||||
return result
|
||||
|
||||
def run(self, tmp=None, task_vars=None):
|
||||
|
|
@ -193,16 +189,16 @@ class ActionModule(ActionBase):
|
|||
self._supports_async = True
|
||||
|
||||
# If running with local connection, fail so we don't shutdown ourself
|
||||
if self._connection.transport == 'local' and (not self._play_context.check_mode):
|
||||
msg = f'Running {self._task.action} with local connection would shutdown the control node.'
|
||||
return {'changed': False, 'elapsed': 0, 'shutdown': False, 'failed': True, 'msg': msg}
|
||||
if self._connection.transport == "local" and (not self._play_context.check_mode):
|
||||
msg = f"Running {self._task.action} with local connection would shutdown the control node."
|
||||
return {"changed": False, "elapsed": 0, "shutdown": False, "failed": True, "msg": msg}
|
||||
|
||||
if task_vars is None:
|
||||
task_vars = {}
|
||||
|
||||
result = super().run(tmp, task_vars)
|
||||
|
||||
if result.get('skipped', False) or result.get('failed', False):
|
||||
if result.get("skipped", False) or result.get("failed", False):
|
||||
return result
|
||||
|
||||
distribution = self.get_distribution(task_vars)
|
||||
|
|
@ -210,12 +206,12 @@ class ActionModule(ActionBase):
|
|||
# Initiate shutdown
|
||||
shutdown_result = self.perform_shutdown(task_vars, distribution)
|
||||
|
||||
if shutdown_result['failed']:
|
||||
if shutdown_result["failed"]:
|
||||
result = shutdown_result
|
||||
return result
|
||||
|
||||
result['shutdown'] = True
|
||||
result['changed'] = True
|
||||
result['shutdown_command'] = shutdown_result['shutdown_command']
|
||||
result["shutdown"] = True
|
||||
result["changed"] = True
|
||||
result["shutdown_command"] = shutdown_result["shutdown_command"]
|
||||
|
||||
return result
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue