mirror of
https://github.com/ansible-collections/ansible.posix.git
synced 2026-03-09 19:15:19 +01:00
Compare commits
11 commits
d8a1c0e3c7
...
d4e1efab0d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4e1efab0d | ||
|
|
9bfed58f7f | ||
|
|
a18d180246 | ||
|
|
51b94f536c | ||
|
|
0a07bdb358 | ||
|
|
8cdf51b3b3 | ||
|
|
0b6eb4506b | ||
|
|
dea22dcf4e | ||
|
|
dd3b97069b | ||
|
|
fa4dd35d66 | ||
|
|
211e6c74b5 |
9 changed files with 117 additions and 43 deletions
4
changelogs/fragments/333_doc_absent_precision.yml
Normal file
4
changelogs/fragments/333_doc_absent_precision.yml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
trivial:
|
||||
- mount - fix description in the documentation of the state ``absent`` to match its actual behavior
|
||||
and point out that ``src`` is ignored with state ``absent`` and ``unmounted`` (https://github.com/ansible-collections/ansible.posix/issues/322)
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
minor_changes:
|
||||
- synchronize - user-defined ``--out-format`` in ``rsync_opts`` is now honored in the returned output. (https://github.com/ansible-collections/ansible.posix/pull/428)
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
bugfixes:
|
||||
- seboolean - make it work with disabled SELinux
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
minor_changes:
|
||||
- "Add summary_only parameter to profile_roles and profile_tasks callbacks."
|
||||
|
|
@ -14,6 +14,19 @@ DOCUMENTATION = '''
|
|||
- This callback module provides profiling for ansible roles.
|
||||
requirements:
|
||||
- whitelisting in configuration
|
||||
options:
|
||||
summary_only:
|
||||
description:
|
||||
- Only show summary, not individual task profiles.
|
||||
Especially usefull in combination with C(DISPLAY_SKIPPED_HOSTS=false) and/or C(ANSIBLE_DISPLAY_OK_HOSTS=false).
|
||||
type: bool
|
||||
default: False
|
||||
env:
|
||||
- name: PROFILE_ROLES_SUMMARY_ONLY
|
||||
ini:
|
||||
- section: callback_profile_roles
|
||||
key: summary_only
|
||||
version_added: 1.5.0
|
||||
'''
|
||||
|
||||
import collections
|
||||
|
|
@ -76,13 +89,26 @@ class CallbackModule(CallbackBase):
|
|||
self.stats = collections.Counter()
|
||||
self.totals = collections.Counter()
|
||||
self.current = None
|
||||
|
||||
self.summary_only = None
|
||||
|
||||
super(CallbackModule, self).__init__()
|
||||
|
||||
def set_options(self, task_keys=None, var_options=None, direct=None):
|
||||
|
||||
super(CallbackModule, self).set_options(task_keys=task_keys, var_options=var_options, direct=direct)
|
||||
|
||||
self.summary_only = self.get_option('summary_only')
|
||||
|
||||
def _display_tasktime(self):
|
||||
if not self.summary_only:
|
||||
self._display.display(tasktime())
|
||||
|
||||
def _record_task(self, task):
|
||||
"""
|
||||
Logs the start of each task
|
||||
"""
|
||||
self._display.display(tasktime())
|
||||
self._display_tasktime()
|
||||
timestamp(self)
|
||||
|
||||
if task._role:
|
||||
|
|
@ -99,10 +125,10 @@ class CallbackModule(CallbackBase):
|
|||
self._record_task(task)
|
||||
|
||||
def playbook_on_setup(self):
|
||||
self._display.display(tasktime())
|
||||
self._display_tasktime()
|
||||
|
||||
def playbook_on_stats(self, stats):
|
||||
self._display.display(tasktime())
|
||||
self._display_tasktime()
|
||||
self._display.display(filled("", fchar="="))
|
||||
|
||||
timestamp(self)
|
||||
|
|
|
|||
|
|
@ -40,6 +40,18 @@ DOCUMENTATION = '''
|
|||
ini:
|
||||
- section: callback_profile_tasks
|
||||
key: sort_order
|
||||
summary_only:
|
||||
description:
|
||||
- Only show summary, not individual task profiles.
|
||||
Especially usefull in combination with C(DISPLAY_SKIPPED_HOSTS=false) and/or C(ANSIBLE_DISPLAY_OK_HOSTS=false).
|
||||
type: bool
|
||||
default: False
|
||||
env:
|
||||
- name: PROFILE_TASKS_SUMMARY_ONLY
|
||||
ini:
|
||||
- section: callback_profile_tasks
|
||||
key: summary_only
|
||||
version_added: 1.5.0
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
|
|
@ -120,6 +132,7 @@ class CallbackModule(CallbackBase):
|
|||
self.current = None
|
||||
|
||||
self.sort_order = None
|
||||
self.summary_only = None
|
||||
self.task_output_limit = None
|
||||
|
||||
super(CallbackModule, self).__init__()
|
||||
|
|
@ -137,6 +150,8 @@ class CallbackModule(CallbackBase):
|
|||
elif self.sort_order == 'none':
|
||||
self.sort_order = None
|
||||
|
||||
self.summary_only = self.get_option('summary_only')
|
||||
|
||||
self.task_output_limit = self.get_option('output_limit')
|
||||
if self.task_output_limit is not None:
|
||||
if self.task_output_limit == 'all':
|
||||
|
|
@ -144,11 +159,15 @@ class CallbackModule(CallbackBase):
|
|||
else:
|
||||
self.task_output_limit = int(self.task_output_limit)
|
||||
|
||||
def _display_tasktime(self):
|
||||
if not self.summary_only:
|
||||
self._display.display(tasktime())
|
||||
|
||||
def _record_task(self, task):
|
||||
"""
|
||||
Logs the start of each task
|
||||
"""
|
||||
self._display.display(tasktime())
|
||||
self._display_tasktime()
|
||||
timestamp(self)
|
||||
|
||||
# Record the start time of the current task
|
||||
|
|
@ -171,10 +190,10 @@ class CallbackModule(CallbackBase):
|
|||
self._record_task(task)
|
||||
|
||||
def playbook_on_setup(self):
|
||||
self._display.display(tasktime())
|
||||
self._display_tasktime()
|
||||
|
||||
def playbook_on_stats(self, stats):
|
||||
self._display.display(tasktime())
|
||||
self._display_tasktime()
|
||||
self._display.display(filled("", fchar="="))
|
||||
|
||||
timestamp(self)
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ options:
|
|||
description:
|
||||
- Device (or NFS volume, or something else) to be mounted on I(path).
|
||||
- Required when I(state) set to C(present), C(mounted) or C(ephemeral).
|
||||
- Ignored when I(state) set to C(absent) or C(unmounted).
|
||||
type: path
|
||||
fstype:
|
||||
description:
|
||||
|
|
@ -75,9 +76,13 @@ options:
|
|||
the module will fail to avoid unexpected unmount or mount point override.
|
||||
If the mount point is not present, the mount point will be created.
|
||||
The I(fstab) is completely ignored. This option is added in version 1.5.0.
|
||||
- C(absent) specifies that the device mount's entry will be removed from
|
||||
I(fstab) and will also unmount the device and remove the mount
|
||||
point.
|
||||
- C(absent) specifies that the mount point entry I(path) will be removed
|
||||
from I(fstab) and will also unmount the mounted device and remove the
|
||||
mount point. A mounted device will be unmounted regardless of I(src) or its
|
||||
real source. C(absent) does not unmount recursively, and the module will
|
||||
fail if multiple devices are mounted on the same mount point. Using
|
||||
C(absent) with a mount point that is not registered in the I(fstab) has
|
||||
no effect. Use C(unmounted) instead..
|
||||
- C(remounted) specifies that the device will be remounted for when you
|
||||
want to force a refresh on the mount itself (added in 2.9). This will
|
||||
always return changed=true. If I(opts) is set, the options will be
|
||||
|
|
|
|||
|
|
@ -73,8 +73,7 @@ except ImportError:
|
|||
HAVE_SEMANAGE = False
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
from ansible.module_utils.six import binary_type
|
||||
from ansible.module_utils._text import to_bytes, to_text
|
||||
from ansible.module_utils._text import to_text
|
||||
from ansible_collections.ansible.posix.plugins.module_utils._respawn import respawn_module, HAS_RESPAWN_UTIL
|
||||
|
||||
|
||||
|
|
@ -82,23 +81,6 @@ def get_runtime_status(ignore_selinux_state=False):
|
|||
return True if ignore_selinux_state is True else selinux.is_selinux_enabled()
|
||||
|
||||
|
||||
def has_boolean_value(module, name):
|
||||
bools = []
|
||||
try:
|
||||
rc, bools = selinux.security_get_boolean_names()
|
||||
except OSError:
|
||||
module.fail_json(msg="Failed to get list of boolean names")
|
||||
# work around for selinux who changed its API, see
|
||||
# https://github.com/ansible/ansible/issues/25651
|
||||
if len(bools) > 0:
|
||||
if isinstance(bools[0], binary_type):
|
||||
name = to_bytes(name)
|
||||
if name in bools:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def get_boolean_value(module, name):
|
||||
state = 0
|
||||
try:
|
||||
|
|
@ -174,7 +156,10 @@ def semanage_set_boolean_value(module, handle, name, value):
|
|||
semanage.semanage_handle_destroy(handle)
|
||||
module.fail_json(msg="Failed to modify boolean key with semanage")
|
||||
|
||||
if semanage.semanage_bool_set_active(handle, boolkey, sebool) < 0:
|
||||
if (
|
||||
selinux.is_selinux_enabled()
|
||||
and semanage.semanage_bool_set_active(handle, boolkey, sebool) < 0
|
||||
):
|
||||
semanage.semanage_handle_destroy(handle)
|
||||
module.fail_json(msg="Failed to set boolean key active with semanage")
|
||||
|
||||
|
|
@ -315,12 +300,9 @@ def main():
|
|||
# Feature only available in selinux library since 2012.
|
||||
name = selinux.selinux_boolean_sub(name)
|
||||
|
||||
if not has_boolean_value(module, name):
|
||||
module.fail_json(msg="SELinux boolean %s does not exist." % name)
|
||||
|
||||
if persistent:
|
||||
changed = semanage_boolean_value(module, name, state)
|
||||
else:
|
||||
elif selinux.is_selinux_enabled():
|
||||
cur_value = get_boolean_value(module, name)
|
||||
if cur_value != state:
|
||||
changed = True
|
||||
|
|
|
|||
|
|
@ -365,6 +365,7 @@ EXAMPLES = r'''
|
|||
|
||||
import os
|
||||
import errno
|
||||
import re
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils._text import to_bytes, to_native
|
||||
|
|
@ -596,8 +597,19 @@ def main():
|
|||
module.fail_json(msg='Hardlinking into a subdirectory of the source would cause recursion. %s and %s' % (destination_path, dest))
|
||||
cmd.append('--link-dest=%s' % link_path)
|
||||
|
||||
changed_marker = '<<CHANGED>>'
|
||||
cmd.append('--out-format=%s' % shlex_quote(changed_marker + '%i %n%L'))
|
||||
# find the last specified out-format
|
||||
out_format = ''
|
||||
for rsync_opt in rsync_opts:
|
||||
if rsync_opt.startswith('--out-format='):
|
||||
out_format = rsync_opt.replace('--out-format=', '', 1)
|
||||
|
||||
# force a known out-format so we can test for changes and return a known format of diff
|
||||
diff_marker = 'DIFF'
|
||||
if out_format == '' or module._diff:
|
||||
diff_detail = '%n%L'
|
||||
else:
|
||||
diff_detail = ''
|
||||
cmd.append('--out-format=%s' % shlex_quote('%s//%s//%%i//%s' % (out_format, diff_marker, diff_detail)))
|
||||
|
||||
cmd.append(shlex_quote(source))
|
||||
cmd.append(shlex_quote(dest))
|
||||
|
|
@ -623,18 +635,36 @@ def main():
|
|||
if rc:
|
||||
return module.fail_json(msg=err, rc=rc, cmd=cmdstr)
|
||||
|
||||
if link_dest:
|
||||
# a leading period indicates no change
|
||||
changed = (changed_marker + '.') not in out
|
||||
else:
|
||||
changed = changed_marker in out
|
||||
changed = False
|
||||
diff = []
|
||||
out_lines = []
|
||||
# remove forced out-format suffix, check for file changes
|
||||
for line in out.split('\n'):
|
||||
match = re.match('(.*)//%s//(...*?)//(.*)$' % diff_marker, line)
|
||||
if match:
|
||||
default_diff = '%s %s' % (match.group(2), match.group(3))
|
||||
|
||||
out_clean = out.replace(changed_marker, '')
|
||||
out_lines = out_clean.split('\n')
|
||||
if module._diff:
|
||||
diff.append(default_diff)
|
||||
|
||||
if out_format == '':
|
||||
out_lines.append(default_diff)
|
||||
else:
|
||||
out_lines.append(match.group(1))
|
||||
|
||||
# a period in the first position indicates no changes to the file's contents
|
||||
# a period in every other position from the third onward indicates no attribute changes
|
||||
if not re.match(r'\..\.*$', match.group(2)):
|
||||
changed = True
|
||||
else:
|
||||
out_lines.append(line)
|
||||
|
||||
out_clean = '\n'.join(out_lines)
|
||||
while '' in out_lines:
|
||||
out_lines.remove('')
|
||||
|
||||
if module._diff:
|
||||
diff = {'prepared': out_clean}
|
||||
diff = {'prepared': '\n'.join(diff)}
|
||||
return module.exit_json(changed=changed, msg=out_clean,
|
||||
rc=rc, cmd=cmdstr, stdout_lines=out_lines,
|
||||
diff=diff)
|
||||
|
|
|
|||
Loading…
Reference in a new issue