mirror of
https://github.com/ansible-collections/ansible.posix.git
synced 2026-01-12 23:55:19 +01:00
Compare commits
17 commits
ea52fdd54b
...
79590e2c16
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
79590e2c16 | ||
|
|
1994b2cf1c | ||
|
|
2f224e6a6a | ||
|
|
c401a5d331 | ||
|
|
94059765b6 | ||
|
|
48c2e9310e | ||
|
|
0a58f59906 | ||
|
|
892c045679 | ||
|
|
793518be3c | ||
|
|
b4fe18e6ff | ||
|
|
e72424ae50 | ||
|
|
6afd4cdcf1 | ||
|
|
ee7748732c | ||
|
|
1e0654f8b6 | ||
|
|
fe7dd71bda | ||
|
|
1a4c2051e8 | ||
|
|
8bb61047f8 |
6 changed files with 99 additions and 22 deletions
|
|
@ -0,0 +1,2 @@
|
||||||
|
minor_changes:
|
||||||
|
- synchronize - add the ``quiet`` option to suppress non-error messages (https://github.com/ansible-collections/ansible.posix/issues/171).
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
minor_changes:
|
||||||
|
- profile_tasks - Add option to provide a different date/time format (https://github.com/ansible-collections/ansible.posix/issues/279).
|
||||||
|
|
@ -52,6 +52,17 @@ DOCUMENTATION = '''
|
||||||
- section: callback_profile_tasks
|
- section: callback_profile_tasks
|
||||||
key: summary_only
|
key: summary_only
|
||||||
version_added: 1.5.0
|
version_added: 1.5.0
|
||||||
|
datetime_format:
|
||||||
|
description:
|
||||||
|
- Datetime format, as expected by the C(strftime) and C(strptime) methods.
|
||||||
|
An C(iso8601) alias will be translated to C('%Y-%m-%dT%H:%M:%S.%f') if that datetime standard wants to be used.
|
||||||
|
default: '%A %d %B %Y %H:%M:%S %z'
|
||||||
|
env:
|
||||||
|
- name: PROFILE_TASKS_DATETIME_FORMAT
|
||||||
|
ini:
|
||||||
|
- section: callback_profile_tasks
|
||||||
|
key: datetime_format
|
||||||
|
version_added: 3.0.0
|
||||||
'''
|
'''
|
||||||
|
|
||||||
EXAMPLES = '''
|
EXAMPLES = '''
|
||||||
|
|
@ -72,14 +83,15 @@ sample output: >
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
import time
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
from ansible.module_utils.six.moves import reduce
|
from ansible.module_utils.six.moves import reduce
|
||||||
from ansible.plugins.callback import CallbackBase
|
from ansible.plugins.callback import CallbackBase
|
||||||
|
|
||||||
|
|
||||||
# define start time
|
# define start time
|
||||||
t0 = tn = time.time()
|
dt0 = dtn = datetime.now().astimezone()
|
||||||
|
|
||||||
|
|
||||||
def secondsToStr(t):
|
def secondsToStr(t):
|
||||||
|
|
@ -104,17 +116,18 @@ def filled(msg, fchar="*"):
|
||||||
|
|
||||||
def timestamp(self):
|
def timestamp(self):
|
||||||
if self.current is not None:
|
if self.current is not None:
|
||||||
elapsed = time.time() - self.stats[self.current]['started']
|
elapsed = (datetime.now().astimezone() - self.stats[self.current]['started']).total_seconds()
|
||||||
self.stats[self.current]['elapsed'] += elapsed
|
self.stats[self.current]['elapsed'] += elapsed
|
||||||
|
|
||||||
|
|
||||||
def tasktime():
|
def tasktime(self):
|
||||||
global tn
|
global dtn
|
||||||
time_current = time.strftime('%A %d %B %Y %H:%M:%S %z')
|
cdtn = datetime.now().astimezone()
|
||||||
time_elapsed = secondsToStr(time.time() - tn)
|
datetime_current = cdtn.strftime(self.datetime_format)
|
||||||
time_total_elapsed = secondsToStr(time.time() - t0)
|
time_elapsed = secondsToStr((cdtn - dtn).total_seconds())
|
||||||
tn = time.time()
|
time_total_elapsed = secondsToStr((cdtn - dt0).total_seconds())
|
||||||
return filled('%s (%s)%s%s' % (time_current, time_elapsed, ' ' * 7, time_total_elapsed))
|
dtn = cdtn
|
||||||
|
return filled('%s (%s)%s%s' % (datetime_current, time_elapsed, ' ' * 7, time_total_elapsed))
|
||||||
|
|
||||||
|
|
||||||
class CallbackModule(CallbackBase):
|
class CallbackModule(CallbackBase):
|
||||||
|
|
@ -134,6 +147,7 @@ class CallbackModule(CallbackBase):
|
||||||
self.sort_order = None
|
self.sort_order = None
|
||||||
self.summary_only = None
|
self.summary_only = None
|
||||||
self.task_output_limit = None
|
self.task_output_limit = None
|
||||||
|
self.datetime_format = None
|
||||||
|
|
||||||
super(CallbackModule, self).__init__()
|
super(CallbackModule, self).__init__()
|
||||||
|
|
||||||
|
|
@ -159,9 +173,14 @@ class CallbackModule(CallbackBase):
|
||||||
else:
|
else:
|
||||||
self.task_output_limit = int(self.task_output_limit)
|
self.task_output_limit = int(self.task_output_limit)
|
||||||
|
|
||||||
|
self.datetime_format = self.get_option('datetime_format')
|
||||||
|
if self.datetime_format is not None:
|
||||||
|
if self.datetime_format == 'iso8601':
|
||||||
|
self.datetime_format = '%Y-%m-%dT%H:%M:%S.%f'
|
||||||
|
|
||||||
def _display_tasktime(self):
|
def _display_tasktime(self):
|
||||||
if not self.summary_only:
|
if not self.summary_only:
|
||||||
self._display.display(tasktime())
|
self._display.display(tasktime(self))
|
||||||
|
|
||||||
def _record_task(self, task):
|
def _record_task(self, task):
|
||||||
"""
|
"""
|
||||||
|
|
@ -176,10 +195,11 @@ class CallbackModule(CallbackBase):
|
||||||
# with the same UUID is executed when `serial` is specified in a playbook.
|
# with the same UUID is executed when `serial` is specified in a playbook.
|
||||||
# elapsed: Elapsed time since the first serialized task was started
|
# elapsed: Elapsed time since the first serialized task was started
|
||||||
self.current = task._uuid
|
self.current = task._uuid
|
||||||
|
dtn = datetime.now().astimezone()
|
||||||
if self.current not in self.stats:
|
if self.current not in self.stats:
|
||||||
self.stats[self.current] = {'started': time.time(), 'elapsed': 0.0, 'name': task.get_name()}
|
self.stats[self.current] = {'started': dtn, 'elapsed': 0.0, 'name': task.get_name()}
|
||||||
else:
|
else:
|
||||||
self.stats[self.current]['started'] = time.time()
|
self.stats[self.current]['started'] = dtn
|
||||||
if self._display.verbosity >= 2:
|
if self._display.verbosity >= 2:
|
||||||
self.stats[self.current]['path'] = task.get_path()
|
self.stats[self.current]['path'] = task.get_path()
|
||||||
|
|
||||||
|
|
@ -196,7 +216,7 @@ class CallbackModule(CallbackBase):
|
||||||
# Align summary report header with other callback plugin summary
|
# Align summary report header with other callback plugin summary
|
||||||
self._display.banner("TASKS RECAP")
|
self._display.banner("TASKS RECAP")
|
||||||
|
|
||||||
self._display.display(tasktime())
|
self._display.display(tasktime(self))
|
||||||
self._display.display(filled("", fchar="="))
|
self._display.display(filled("", fchar="="))
|
||||||
|
|
||||||
timestamp(self)
|
timestamp(self)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
DOCUMENTATION = r'''
|
DOCUMENTATION = r'''
|
||||||
---
|
---
|
||||||
module: synchronize
|
module: synchronize
|
||||||
|
|
@ -204,6 +203,12 @@ options:
|
||||||
description: Internal use only. See O(use_ssh_args) for ssh arg settings.
|
description: Internal use only. See O(use_ssh_args) for ssh arg settings.
|
||||||
type: str
|
type: str
|
||||||
required: false
|
required: false
|
||||||
|
quiet:
|
||||||
|
description:
|
||||||
|
- This option specifies quiet option which on true suppresses the output.
|
||||||
|
type: bool
|
||||||
|
default: false
|
||||||
|
version_added: 1.6.0
|
||||||
|
|
||||||
notes:
|
notes:
|
||||||
- C(rsync) must be installed on both the local and remote host.
|
- C(rsync) must be installed on both the local and remote host.
|
||||||
|
|
@ -361,6 +366,12 @@ EXAMPLES = r'''
|
||||||
src: /tmp/localpath/
|
src: /tmp/localpath/
|
||||||
dest: /tmp/remotepath
|
dest: /tmp/remotepath
|
||||||
rsync_path: /usr/gnu/bin/rsync
|
rsync_path: /usr/gnu/bin/rsync
|
||||||
|
|
||||||
|
- name: Synchronization with quiet option enabled
|
||||||
|
ansible.posix.synchronize:
|
||||||
|
src: some/relative/path
|
||||||
|
dest: /some/absolute/path
|
||||||
|
quiet: true
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -438,6 +449,7 @@ def main():
|
||||||
delay_updates=dict(type='bool', default=True),
|
delay_updates=dict(type='bool', default=True),
|
||||||
mode=dict(type='str', default='push', choices=['pull', 'push']),
|
mode=dict(type='str', default='push', choices=['pull', 'push']),
|
||||||
link_dest=dict(type='list', elements='path'),
|
link_dest=dict(type='list', elements='path'),
|
||||||
|
quiet=dict(type='bool', default=False)
|
||||||
),
|
),
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
)
|
)
|
||||||
|
|
@ -478,6 +490,7 @@ def main():
|
||||||
verify_host = module.params['verify_host']
|
verify_host = module.params['verify_host']
|
||||||
link_dest = module.params['link_dest']
|
link_dest = module.params['link_dest']
|
||||||
delay_updates = module.params['delay_updates']
|
delay_updates = module.params['delay_updates']
|
||||||
|
quiet = module.params['quiet']
|
||||||
|
|
||||||
if '/' not in rsync:
|
if '/' not in rsync:
|
||||||
rsync = module.get_bin_path(rsync, required=True)
|
rsync = module.get_bin_path(rsync, required=True)
|
||||||
|
|
@ -602,6 +615,9 @@ def main():
|
||||||
|
|
||||||
cmd.append(shlex_quote(source))
|
cmd.append(shlex_quote(source))
|
||||||
cmd.append(shlex_quote(dest))
|
cmd.append(shlex_quote(dest))
|
||||||
|
if quiet:
|
||||||
|
cmd.append('--quiet')
|
||||||
|
|
||||||
cmdstr = ' '.join(cmd)
|
cmdstr = ' '.join(cmd)
|
||||||
|
|
||||||
# If we are using password authentication, write the password into the pipe
|
# If we are using password authentication, write the password into the pipe
|
||||||
|
|
@ -634,14 +650,17 @@ def main():
|
||||||
out_lines = out_clean.split('\n')
|
out_lines = out_clean.split('\n')
|
||||||
while '' in out_lines:
|
while '' in out_lines:
|
||||||
out_lines.remove('')
|
out_lines.remove('')
|
||||||
if module._diff:
|
|
||||||
diff = {'prepared': out_clean}
|
|
||||||
return module.exit_json(changed=changed, msg=out_clean,
|
|
||||||
rc=rc, cmd=cmdstr, stdout_lines=out_lines,
|
|
||||||
diff=diff)
|
|
||||||
|
|
||||||
return module.exit_json(changed=changed, msg=out_clean,
|
result = dict(changed=changed, rc=rc, cmd=cmdstr, stdout_lines=out_lines, msg=out_clean)
|
||||||
rc=rc, cmd=cmdstr, stdout_lines=out_lines)
|
|
||||||
|
if quiet:
|
||||||
|
changes = out.count(changed_marker) if changed else 0
|
||||||
|
result['msg'] = "%s files/directories have been synchronized" % changes
|
||||||
|
|
||||||
|
if module._diff:
|
||||||
|
result['diff'] = {'prepared': out_clean}
|
||||||
|
|
||||||
|
return module.exit_json(**result)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
||||||
2
tests/integration/inventory
Normal file
2
tests/integration/inventory
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
[testgroup]
|
||||||
|
testhost ansible_connection="local" ansible_pipelining="yes" ansible_python_interpreter="/Users/mandkulk/venv3.9/bin/python"
|
||||||
|
|
@ -339,6 +339,37 @@
|
||||||
- stat_result_b.stat.exists == True
|
- stat_result_b.stat.exists == True
|
||||||
- stat_result_b.stat.checksum == '2aae6c35c94fcfb415dbe95f408b9ce91ee846ed'
|
- stat_result_b.stat.checksum == '2aae6c35c94fcfb415dbe95f408b9ce91ee846ed'
|
||||||
|
|
||||||
|
- name: Synchronize files with quiet option
|
||||||
|
ansible.posix.synchronize:
|
||||||
|
src: '{{ output_dir }}/foo.txt'
|
||||||
|
dest: '{{ output_dir }}/foo.result'
|
||||||
|
quiet: true
|
||||||
|
register: sync_result
|
||||||
|
|
||||||
|
- name: Assertion for synchronize with quiet option
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- '''files/directories have been synchronized'' in sync_result.msg'
|
||||||
|
|
||||||
|
- name: Cleanup
|
||||||
|
ansible.builtin.file:
|
||||||
|
state: absent
|
||||||
|
path: '{{ output_dir }}/{{ item }}'
|
||||||
|
loop:
|
||||||
|
- foo.result
|
||||||
|
- bar.result
|
||||||
|
|
||||||
|
- name: Synchronize files without quiet option
|
||||||
|
ansible.posix.synchronize:
|
||||||
|
src: '{{ output_dir }}/foo.txt'
|
||||||
|
dest: '{{ output_dir }}/foo.result'
|
||||||
|
register: sync_result
|
||||||
|
|
||||||
|
- name: Assertion for synchronize without quiet option
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- '''files/directories have been synchronized'' not in sync_result.msg'
|
||||||
|
|
||||||
- name: Cleanup
|
- name: Cleanup
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
state: absent
|
state: absent
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue