mirror of
https://github.com/ansible-collections/ansible.posix.git
synced 2026-03-26 21:33:32 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ceccecd8f3 | ||
|
|
5b3b5538f2 | ||
|
|
2d5fb42acd | ||
|
|
75a5f83602 | ||
|
|
74c8ca58e2 | ||
|
|
0062198f73 | ||
|
|
d9e0140b66 | ||
|
|
147caed10d | ||
|
|
8a11a72e0c | ||
|
|
c217a9bf8d | ||
|
|
7e70deb734 | ||
|
|
5b17c47723 | ||
|
|
6b347f3725 | ||
|
|
27482c25f9 |
@@ -5,9 +5,8 @@ readme: README.md
|
||||
authors:
|
||||
- Ansible (github.com/ansible)
|
||||
description: null
|
||||
license: GPL-3.0-or-later
|
||||
license_file: COPYING
|
||||
tags: null
|
||||
tags: [posix, networking, shell, unix]
|
||||
dependencies: {}
|
||||
repository: https://github.com/ansible-collections/ansible.posix
|
||||
documentation: https://github.com/ansible-collections/ansible.posix/tree/master/docs
|
||||
|
||||
130
hacking/cgroup_perf_recap_graph.py
Normal file
130
hacking/cgroup_perf_recap_graph.py
Normal file
@@ -0,0 +1,130 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# (c) 2018, Matt Martz <matt@sivel.net>
|
||||
#
|
||||
# This file is part of Ansible
|
||||
#
|
||||
# Ansible is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Ansible is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Make coding more python3-ish
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
import os
|
||||
import argparse
|
||||
import csv
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
try:
|
||||
import matplotlib
|
||||
matplotlib.use("Agg")
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib.dates as mdates
|
||||
except ImportError:
|
||||
raise SystemExit('matplotlib is required for this script to work')
|
||||
|
||||
|
||||
Data = namedtuple('Data', ['axis_name', 'dates', 'names', 'values'])
|
||||
|
||||
|
||||
def task_start_ticks(dates, names):
|
||||
item = None
|
||||
ret = []
|
||||
for i, name in enumerate(names):
|
||||
if name == item:
|
||||
continue
|
||||
item = name
|
||||
ret.append((dates[i], name))
|
||||
return ret
|
||||
|
||||
|
||||
def create_axis_data(filename, relative=False):
|
||||
x_base = None if relative else 0
|
||||
|
||||
axis_name, dummy = os.path.splitext(os.path.basename(filename))
|
||||
|
||||
dates = []
|
||||
names = []
|
||||
values = []
|
||||
with open(filename) as f:
|
||||
reader = csv.reader(f)
|
||||
for row in reader:
|
||||
if x_base is None:
|
||||
x_base = float(row[0])
|
||||
dates.append(mdates.epoch2num(float(row[0]) - x_base))
|
||||
names.append(row[1])
|
||||
values.append(float(row[3]))
|
||||
|
||||
return Data(axis_name, dates, names, values)
|
||||
|
||||
|
||||
def create_graph(data1, data2, width=11.0, height=8.0, filename='out.png', title=None):
|
||||
fig, ax1 = plt.subplots(figsize=(width, height), dpi=300)
|
||||
|
||||
task_ticks = task_start_ticks(data1.dates, data1.names)
|
||||
|
||||
ax1.grid(linestyle='dashed', color='lightgray')
|
||||
ax1.xaxis.set_major_formatter(mdates.DateFormatter('%X'))
|
||||
ax1.plot(data1.dates, data1.values, 'b-')
|
||||
if title:
|
||||
ax1.set_title(title)
|
||||
ax1.set_xlabel('Time')
|
||||
ax1.set_ylabel(data1.axis_name, color='b')
|
||||
for item in ax1.get_xticklabels():
|
||||
item.set_rotation(60)
|
||||
|
||||
ax2 = ax1.twiny()
|
||||
ax2.set_xticks([x[0] for x in task_ticks])
|
||||
ax2.set_xticklabels([x[1] for x in task_ticks])
|
||||
ax2.grid(axis='x', linestyle='dashed', color='lightgray')
|
||||
ax2.xaxis.set_ticks_position('bottom')
|
||||
ax2.xaxis.set_label_position('bottom')
|
||||
ax2.spines['bottom'].set_position(('outward', 86))
|
||||
ax2.set_xlabel('Task')
|
||||
ax2.set_xlim(ax1.get_xlim())
|
||||
for item in ax2.get_xticklabels():
|
||||
item.set_rotation(60)
|
||||
|
||||
ax3 = ax1.twinx()
|
||||
ax3.plot(data2.dates, data2.values, 'g-')
|
||||
ax3.set_ylabel(data2.axis_name, color='g')
|
||||
fig.tight_layout()
|
||||
fig.savefig(filename, format='png')
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('files', nargs=2, help='2 CSV files produced by cgroup_perf_recap to graph together')
|
||||
parser.add_argument('--relative', default=False, action='store_true',
|
||||
help='Use relative dates instead of absolute')
|
||||
parser.add_argument('--output', default='out.png', help='output path of PNG file: Default %s(default)s')
|
||||
parser.add_argument('--width', type=float, default=11.0,
|
||||
help='Width of output image in inches. Default %(default)s')
|
||||
parser.add_argument('--height', type=float, default=8.0,
|
||||
help='Height of output image in inches. Default %(default)s')
|
||||
parser.add_argument('--title', help='Title for graph')
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
data1 = create_axis_data(args.files[0], relative=args.relative)
|
||||
data2 = create_axis_data(args.files[1], relative=args.relative)
|
||||
create_graph(data1, data2, width=args.width, height=args.height, filename=args.output, title=args.title)
|
||||
print('Graph written to %s' % os.path.abspath(args.output))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -46,7 +46,7 @@ EXAMPLES = '''
|
||||
example: >
|
||||
To enable, add this to your ansible.cfg file in the defaults block
|
||||
[defaults]
|
||||
callback_whitelist = profile_tasks
|
||||
callback_whitelist = ansible.posix.profile_tasks
|
||||
sample output: >
|
||||
#
|
||||
# TASK: [ensure messaging security group exists] ********************************
|
||||
@@ -172,7 +172,7 @@ class CallbackModule(CallbackBase):
|
||||
timestamp(self)
|
||||
self.current = None
|
||||
|
||||
results = self.stats.items()
|
||||
results = list(self.stats.items())
|
||||
|
||||
# Sort the tasks by the specified sort
|
||||
if self.sort_order is not None:
|
||||
@@ -183,7 +183,7 @@ class CallbackModule(CallbackBase):
|
||||
)
|
||||
|
||||
# Display the number of tasks specified or the default of 20
|
||||
results = results[:self.task_output_limit]
|
||||
results = list(results)[:self.task_output_limit]
|
||||
|
||||
# Print the timings
|
||||
for uuid, result in results:
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['stableinterface'],
|
||||
'supported_by': 'core'}
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
@@ -88,7 +85,7 @@ notes:
|
||||
|
||||
EXAMPLES = r'''
|
||||
- name: Grant user Joe read access to a file
|
||||
acl:
|
||||
ansible.posix.acl:
|
||||
path: /etc/foo.conf
|
||||
entity: joe
|
||||
etype: user
|
||||
@@ -96,14 +93,14 @@ EXAMPLES = r'''
|
||||
state: present
|
||||
|
||||
- name: Removes the ACL for Joe on a specific file
|
||||
acl:
|
||||
ansible.posix.acl:
|
||||
path: /etc/foo.conf
|
||||
entity: joe
|
||||
etype: user
|
||||
state: absent
|
||||
|
||||
- name: Sets default ACL for joe on /etc/foo.d/
|
||||
acl:
|
||||
ansible.posix.acl:
|
||||
path: /etc/foo.d/
|
||||
entity: joe
|
||||
etype: user
|
||||
@@ -112,13 +109,13 @@ EXAMPLES = r'''
|
||||
state: present
|
||||
|
||||
- name: Same as previous but using entry shorthand
|
||||
acl:
|
||||
ansible.posix.acl:
|
||||
path: /etc/foo.d/
|
||||
entry: default:user:joe:rw-
|
||||
state: present
|
||||
|
||||
- name: Obtain the ACL for a specific file
|
||||
acl:
|
||||
ansible.posix.acl:
|
||||
path: /etc/foo.conf
|
||||
register: acl_info
|
||||
'''
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'core'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
@@ -55,20 +52,20 @@ author:
|
||||
- Richard Isaacson (@risaacson)
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
EXAMPLES = r'''
|
||||
- name: Schedule a command to execute in 20 minutes as root
|
||||
at:
|
||||
ansible.posix.at:
|
||||
command: ls -d / >/dev/null
|
||||
count: 20
|
||||
units: minutes
|
||||
|
||||
- name: Match a command to an existing job and delete the job
|
||||
at:
|
||||
ansible.posix.at:
|
||||
command: ls -d / >/dev/null
|
||||
state: absent
|
||||
|
||||
- name: Schedule a command to execute in 20 minutes making sure it is unique in the queue
|
||||
at:
|
||||
ansible.posix.at:
|
||||
command: ls -d / >/dev/null
|
||||
count: 20
|
||||
units: minutes
|
||||
|
||||
@@ -8,11 +8,6 @@ from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'core'}
|
||||
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: authorized_key
|
||||
@@ -86,19 +81,19 @@ author: Ansible Core Team
|
||||
|
||||
EXAMPLES = r'''
|
||||
- name: Set authorized key taken from file
|
||||
authorized_key:
|
||||
ansible.posix.authorized_key:
|
||||
user: charlie
|
||||
state: present
|
||||
key: "{{ lookup('file', '/home/charlie/.ssh/id_rsa.pub') }}"
|
||||
|
||||
- name: Set authorized keys taken from url
|
||||
authorized_key:
|
||||
ansible.posix.authorized_key:
|
||||
user: charlie
|
||||
state: present
|
||||
key: https://github.com/charlie.keys
|
||||
|
||||
- name: Set authorized key in alternate location
|
||||
authorized_key:
|
||||
ansible.posix.authorized_key:
|
||||
user: charlie
|
||||
state: present
|
||||
key: "{{ lookup('file', '/home/charlie/.ssh/id_rsa.pub') }}"
|
||||
@@ -106,7 +101,7 @@ EXAMPLES = r'''
|
||||
manage_dir: False
|
||||
|
||||
- name: Set up multiple authorized keys
|
||||
authorized_key:
|
||||
ansible.posix.authorized_key:
|
||||
user: deploy
|
||||
state: present
|
||||
key: '{{ item }}'
|
||||
@@ -115,28 +110,28 @@ EXAMPLES = r'''
|
||||
- public_keys/doe-john
|
||||
|
||||
- name: Set authorized key defining key options
|
||||
authorized_key:
|
||||
ansible.posix.authorized_key:
|
||||
user: charlie
|
||||
state: present
|
||||
key: "{{ lookup('file', '/home/charlie/.ssh/id_rsa.pub') }}"
|
||||
key_options: 'no-port-forwarding,from="10.0.1.1"'
|
||||
|
||||
- name: Set authorized key without validating the TLS/SSL certificates
|
||||
authorized_key:
|
||||
ansible.posix.authorized_key:
|
||||
user: charlie
|
||||
state: present
|
||||
key: https://github.com/user.keys
|
||||
validate_certs: False
|
||||
|
||||
- name: Set authorized key, removing all the authorized keys already set
|
||||
authorized_key:
|
||||
ansible.posix.authorized_key:
|
||||
user: root
|
||||
key: "{{ lookup('file', 'public_keys/doe-jane') }}"
|
||||
state: present
|
||||
exclusive: True
|
||||
|
||||
- name: Set authorized key for user ubuntu copying it from current user
|
||||
authorized_key:
|
||||
ansible.posix.authorized_key:
|
||||
user: ubuntu
|
||||
state: present
|
||||
key: "{{ lookup('file', lookup('env','HOME') + '/.ssh/id_rsa.pub') }}"
|
||||
|
||||
@@ -9,9 +9,6 @@
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'core'}
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
@@ -32,7 +29,7 @@ options:
|
||||
aliases: [ name ]
|
||||
src:
|
||||
description:
|
||||
- Device to be mounted on I(path).
|
||||
- Device (or NFS volume, or something else) to be mounted on I(path).
|
||||
- Required when I(state) set to C(present) or C(mounted).
|
||||
type: path
|
||||
fstype:
|
||||
@@ -75,7 +72,11 @@ options:
|
||||
point.
|
||||
- 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.
|
||||
always return changed=true. If I(opts) is set, the options will be
|
||||
applied to the remount, but will not change I(fstab). Additionally,
|
||||
if I(opts) is set, and the remount command fails, the module will
|
||||
error to prevent unexpected mount changes. Try using C(mounted)
|
||||
instead to work around this issue.
|
||||
type: str
|
||||
required: true
|
||||
choices: [ absent, mounted, present, unmounted, remounted ]
|
||||
@@ -103,12 +104,15 @@ options:
|
||||
notes:
|
||||
- As of Ansible 2.3, the I(name) option has been changed to I(path) as
|
||||
default, but I(name) still works as well.
|
||||
- Using C(remounted) with I(opts) set may create unexpected results based on
|
||||
the existing options already defined on mount, so care should be taken to
|
||||
ensure that conflicting options are not present before hand.
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
# Before 2.3, option 'name' was used instead of 'path'
|
||||
- name: Mount DVD read-only
|
||||
mount:
|
||||
ansible.posix.mount:
|
||||
path: /mnt/dvd
|
||||
src: /dev/sr0
|
||||
fstype: iso9660
|
||||
@@ -116,14 +120,14 @@ EXAMPLES = r'''
|
||||
state: present
|
||||
|
||||
- name: Mount up device by label
|
||||
mount:
|
||||
ansible.posix.mount:
|
||||
path: /srv/disk
|
||||
src: LABEL=SOME_LABEL
|
||||
fstype: ext4
|
||||
state: present
|
||||
|
||||
- name: Mount up device by UUID
|
||||
mount:
|
||||
ansible.posix.mount:
|
||||
path: /home
|
||||
src: UUID=b3e48f45-f933-4c8e-a700-22a159ec9077
|
||||
fstype: xfs
|
||||
@@ -131,12 +135,26 @@ EXAMPLES = r'''
|
||||
state: present
|
||||
|
||||
- name: Unmount a mounted volume
|
||||
mount:
|
||||
ansible.posix.mount:
|
||||
path: /tmp/mnt-pnt
|
||||
state: unmounted
|
||||
|
||||
- name: Remount a mounted volume
|
||||
ansible.posix.mount:
|
||||
path: /tmp/mnt-pnt
|
||||
state: remounted
|
||||
|
||||
# The following will not save changes to fstab, and only be temporary until
|
||||
# a reboot, or until calling "state: unmounted" followed by "state: mounted"
|
||||
# on the same "path"
|
||||
- name: Remount a mounted volume and append exec to the existing options
|
||||
ansible.posix.mount:
|
||||
path: /tmp
|
||||
state: remounted
|
||||
opts: exec
|
||||
|
||||
- name: Mount and bind a volume
|
||||
mount:
|
||||
ansible.posix.mount:
|
||||
path: /system/new_volume/boot
|
||||
src: /boot
|
||||
opts: bind
|
||||
@@ -144,7 +162,7 @@ EXAMPLES = r'''
|
||||
fstype: none
|
||||
|
||||
- name: Mount an NFS volume
|
||||
mount:
|
||||
ansible.posix.mount:
|
||||
src: 192.168.1.100:/nfs/ssd/shared_data
|
||||
path: /mnt/shared_data
|
||||
opts: rw,sync,hard,intr
|
||||
@@ -153,13 +171,14 @@ EXAMPLES = r'''
|
||||
'''
|
||||
|
||||
|
||||
import errno
|
||||
import os
|
||||
import platform
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.ansible.posix.plugins.module_utils.ismount import ismount
|
||||
from ansible.module_utils.six import iteritems
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible.module_utils._text import to_bytes, to_native
|
||||
|
||||
|
||||
def write_fstab(module, lines, path):
|
||||
@@ -195,8 +214,15 @@ def _escape_fstab(v):
|
||||
|
||||
def set_mount(module, args):
|
||||
"""Set/change a mount point location in fstab."""
|
||||
name, backup_lines, changed = _set_mount_save_old(module, args)
|
||||
return name, changed
|
||||
|
||||
|
||||
def _set_mount_save_old(module, args):
|
||||
"""Set/change a mount point location in fstab. Save the old fstab contents."""
|
||||
|
||||
to_write = []
|
||||
old_lines = []
|
||||
exists = False
|
||||
changed = False
|
||||
escaped_args = dict([(k, _escape_fstab(v)) for k, v in iteritems(args)])
|
||||
@@ -207,6 +233,8 @@ def set_mount(module, args):
|
||||
'%(src)s - %(name)s %(fstype)s %(passno)s %(boot)s %(opts)s\n')
|
||||
|
||||
for line in open(args['fstab'], 'r').readlines():
|
||||
old_lines.append(line)
|
||||
|
||||
if not line.strip():
|
||||
to_write.append(line)
|
||||
|
||||
@@ -289,7 +317,7 @@ def set_mount(module, args):
|
||||
if changed and not module.check_mode:
|
||||
write_fstab(module, to_write, args['fstab'])
|
||||
|
||||
return (args['name'], changed)
|
||||
return (args['name'], old_lines, changed)
|
||||
|
||||
|
||||
def unset_mount(module, args):
|
||||
@@ -426,9 +454,15 @@ def remount(module, args):
|
||||
|
||||
# Multiplatform remount opts
|
||||
if platform.system().lower().endswith('bsd'):
|
||||
cmd += ['-u']
|
||||
if module.params['state'] == 'remounted' and args['opts'] != 'defaults':
|
||||
cmd += ['-u', '-o', args['opts']]
|
||||
else:
|
||||
cmd += ['-u']
|
||||
else:
|
||||
cmd += ['-o', 'remount']
|
||||
if module.params['state'] == 'remounted' and args['opts'] != 'defaults':
|
||||
cmd += ['-o', 'remount,' + args['opts']]
|
||||
else:
|
||||
cmd += ['-o', 'remount']
|
||||
|
||||
if platform.system().lower() == 'openbsd':
|
||||
# Use module.params['fstab'] here as args['fstab'] has been set to the
|
||||
@@ -461,6 +495,16 @@ def remount(module, args):
|
||||
|
||||
if rc != 0:
|
||||
msg = out + err
|
||||
|
||||
if module.params['state'] == 'remounted' and args['opts'] != 'defaults':
|
||||
module.fail_json(
|
||||
msg=(
|
||||
'Options were specified with remounted, but the remount '
|
||||
'command failed. Failing in order to prevent an '
|
||||
'unexpected mount result. Try replacing this command with '
|
||||
'a "state: unmounted" followed by a "state: mounted" '
|
||||
'using the full desired mount options instead.'))
|
||||
|
||||
rc, msg = umount(module, args['name'])
|
||||
|
||||
if rc == 0:
|
||||
@@ -716,17 +760,34 @@ def main():
|
||||
|
||||
changed = True
|
||||
elif state == 'mounted':
|
||||
if not os.path.exists(args['src']):
|
||||
module.fail_json(msg="Unable to mount %s as it does not exist" % args['src'])
|
||||
|
||||
dirs_created = []
|
||||
if not os.path.exists(name) and not module.check_mode:
|
||||
try:
|
||||
os.makedirs(name)
|
||||
# Something like mkdir -p but with the possibility to undo.
|
||||
# Based on some copy-paste from the "file" module.
|
||||
curpath = ''
|
||||
for dirname in name.strip('/').split('/'):
|
||||
curpath = '/'.join([curpath, dirname])
|
||||
# Remove leading slash if we're creating a relative path
|
||||
if not os.path.isabs(name):
|
||||
curpath = curpath.lstrip('/')
|
||||
|
||||
b_curpath = to_bytes(curpath, errors='surrogate_or_strict')
|
||||
if not os.path.exists(b_curpath):
|
||||
try:
|
||||
os.mkdir(b_curpath)
|
||||
dirs_created.append(b_curpath)
|
||||
except OSError as ex:
|
||||
# Possibly something else created the dir since the os.path.exists
|
||||
# check above. As long as it's a dir, we don't need to error out.
|
||||
if not (ex.errno == errno.EEXIST and os.path.isdir(b_curpath)):
|
||||
raise
|
||||
|
||||
except (OSError, IOError) as e:
|
||||
module.fail_json(
|
||||
msg="Error making dir %s: %s" % (name, to_native(e)))
|
||||
|
||||
name, changed = set_mount(module, args)
|
||||
name, backup_lines, changed = _set_mount_save_old(module, args)
|
||||
res = 0
|
||||
|
||||
if (
|
||||
@@ -743,6 +804,21 @@ def main():
|
||||
res, msg = mount(module, args)
|
||||
|
||||
if res:
|
||||
# Not restoring fstab after a failed mount was reported as a bug,
|
||||
# ansible/ansible#59183
|
||||
# A non-working fstab entry may break the system at the reboot,
|
||||
# so undo all the changes if possible.
|
||||
try:
|
||||
write_fstab(module, backup_lines, args['fstab'])
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
try:
|
||||
for dirname in dirs_created[::-1]:
|
||||
os.rmdir(dirname)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
module.fail_json(msg="Error mounting %s: %s" % (name, msg))
|
||||
elif state == 'present':
|
||||
name, changed = set_mount(module, args)
|
||||
|
||||
@@ -9,9 +9,6 @@
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['stableinterface'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
@@ -82,18 +79,18 @@ notes:
|
||||
|
||||
EXAMPLES = r'''
|
||||
- name: Apply patch to one file
|
||||
patch:
|
||||
ansible.posix.patch:
|
||||
src: /tmp/index.html.patch
|
||||
dest: /var/www/index.html
|
||||
|
||||
- name: Apply patch to multiple files under basedir
|
||||
patch:
|
||||
ansible.posix.patch:
|
||||
src: /tmp/customize.patch
|
||||
basedir: /var/www
|
||||
strip: 1
|
||||
|
||||
- name: Revert patch to one file
|
||||
patch:
|
||||
ansible.posix.patch:
|
||||
src: /tmp/index.html.patch
|
||||
dest: /var/www/index.html
|
||||
state: absent
|
||||
|
||||
@@ -6,9 +6,6 @@
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['stableinterface'],
|
||||
'supported_by': 'core'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
@@ -45,9 +42,9 @@ author:
|
||||
- Stephen Fromm (@sfromm)
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
EXAMPLES = r'''
|
||||
- name: Set httpd_can_network_connect flag on and keep it persistent across reboots
|
||||
seboolean:
|
||||
ansible.posix.seboolean:
|
||||
name: httpd_can_network_connect
|
||||
state: yes
|
||||
persistent: yes
|
||||
|
||||
@@ -7,11 +7,6 @@
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {
|
||||
'metadata_version': '1.1',
|
||||
'status': ['stableinterface'],
|
||||
'supported_by': 'core'
|
||||
}
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
@@ -42,17 +37,17 @@ author:
|
||||
|
||||
EXAMPLES = r'''
|
||||
- name: Enable SELinux
|
||||
selinux:
|
||||
ansible.posix.selinux:
|
||||
policy: targeted
|
||||
state: enforcing
|
||||
|
||||
- name: Put SELinux in permissive mode, logging actions that would be blocked.
|
||||
selinux:
|
||||
ansible.posix.selinux:
|
||||
policy: targeted
|
||||
state: permissive
|
||||
|
||||
- name: Disable SELinux
|
||||
selinux:
|
||||
ansible.posix.selinux:
|
||||
state: disabled
|
||||
'''
|
||||
|
||||
|
||||
@@ -8,9 +8,6 @@
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'core'}
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
@@ -199,88 +196,88 @@ author:
|
||||
- Timothy Appnel (@tima)
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
EXAMPLES = r'''
|
||||
- name: Synchronization of src on the control machine to dest on the remote hosts
|
||||
synchronize:
|
||||
ansible.posix.synchronize:
|
||||
src: some/relative/path
|
||||
dest: /some/absolute/path
|
||||
|
||||
- name: Synchronization using rsync protocol (push)
|
||||
synchronize:
|
||||
ansible.posix.synchronize:
|
||||
src: some/relative/path/
|
||||
dest: rsync://somehost.com/path/
|
||||
|
||||
- name: Synchronization using rsync protocol (pull)
|
||||
synchronize:
|
||||
ansible.posix.synchronize:
|
||||
mode: pull
|
||||
src: rsync://somehost.com/path/
|
||||
dest: /some/absolute/path/
|
||||
|
||||
- name: Synchronization using rsync protocol on delegate host (push)
|
||||
synchronize:
|
||||
ansible.posix.synchronize:
|
||||
src: /some/absolute/path/
|
||||
dest: rsync://somehost.com/path/
|
||||
delegate_to: delegate.host
|
||||
|
||||
- name: Synchronization using rsync protocol on delegate host (pull)
|
||||
synchronize:
|
||||
ansible.posix.synchronize:
|
||||
mode: pull
|
||||
src: rsync://somehost.com/path/
|
||||
dest: /some/absolute/path/
|
||||
delegate_to: delegate.host
|
||||
|
||||
- name: Synchronization without any --archive options enabled
|
||||
synchronize:
|
||||
ansible.posix.synchronize:
|
||||
src: some/relative/path
|
||||
dest: /some/absolute/path
|
||||
archive: no
|
||||
|
||||
- name: Synchronization with --archive options enabled except for --recursive
|
||||
synchronize:
|
||||
ansible.posix.synchronize:
|
||||
src: some/relative/path
|
||||
dest: /some/absolute/path
|
||||
recursive: no
|
||||
|
||||
- name: Synchronization with --archive options enabled except for --times, with --checksum option enabled
|
||||
synchronize:
|
||||
ansible.posix.synchronize:
|
||||
src: some/relative/path
|
||||
dest: /some/absolute/path
|
||||
checksum: yes
|
||||
times: no
|
||||
|
||||
- name: Synchronization without --archive options enabled except use --links
|
||||
synchronize:
|
||||
ansible.posix.synchronize:
|
||||
src: some/relative/path
|
||||
dest: /some/absolute/path
|
||||
archive: no
|
||||
links: yes
|
||||
|
||||
- name: Synchronization of two paths both on the control machine
|
||||
synchronize:
|
||||
ansible.posix.synchronize:
|
||||
src: some/relative/path
|
||||
dest: /some/absolute/path
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Synchronization of src on the inventory host to the dest on the localhost in pull mode
|
||||
synchronize:
|
||||
ansible.posix.synchronize:
|
||||
mode: pull
|
||||
src: some/relative/path
|
||||
dest: /some/absolute/path
|
||||
|
||||
- name: Synchronization of src on delegate host to dest on the current inventory host.
|
||||
synchronize:
|
||||
ansible.posix.synchronize:
|
||||
src: /first/absolute/path
|
||||
dest: /second/absolute/path
|
||||
delegate_to: delegate.host
|
||||
|
||||
- name: Synchronize two directories on one remote host.
|
||||
synchronize:
|
||||
ansible.posix.synchronize:
|
||||
src: /first/absolute/path
|
||||
dest: /second/absolute/path
|
||||
delegate_to: "{{ inventory_hostname }}"
|
||||
|
||||
- name: Synchronize and delete files in dest on the remote host that are not found in src of localhost.
|
||||
synchronize:
|
||||
ansible.posix.synchronize:
|
||||
src: some/relative/path
|
||||
dest: /some/absolute/path
|
||||
delete: yes
|
||||
@@ -288,7 +285,7 @@ EXAMPLES = '''
|
||||
|
||||
# This specific command is granted su privileges on the destination
|
||||
- name: Synchronize using an alternate rsync command
|
||||
synchronize:
|
||||
ansible.posix.synchronize:
|
||||
src: some/relative/path
|
||||
dest: /some/absolute/path
|
||||
rsync_path: su -c rsync
|
||||
@@ -299,7 +296,7 @@ EXAMPLES = '''
|
||||
# + /var/conf # include /var/conf even though it was previously excluded
|
||||
|
||||
- name: Synchronize passing in extra rsync options
|
||||
synchronize:
|
||||
ansible.posix.synchronize:
|
||||
src: /tmp/helloworld
|
||||
dest: /var/www/helloworld
|
||||
rsync_opts:
|
||||
@@ -308,7 +305,7 @@ EXAMPLES = '''
|
||||
|
||||
# Hardlink files if they didn't change
|
||||
- name: Use hardlinks when synchronizing filesystems
|
||||
synchronize:
|
||||
ansible.posix.synchronize:
|
||||
src: /tmp/path_a/foo.txt
|
||||
dest: /tmp/path_b/foo.txt
|
||||
link_dest: /tmp/path_a/
|
||||
@@ -320,7 +317,7 @@ EXAMPLES = '''
|
||||
|
||||
tasks:
|
||||
- name: copy /tmp/localpath/ to remote location /tmp/remotepath
|
||||
synchronize:
|
||||
ansible.posix.synchronize:
|
||||
src: /tmp/localpath/
|
||||
dest: /tmp/remotepath
|
||||
rsync_path: /usr/gnu/bin/rsync
|
||||
|
||||
@@ -9,11 +9,6 @@ from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['stableinterface'],
|
||||
'supported_by': 'core'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: sysctl
|
||||
@@ -59,34 +54,34 @@ options:
|
||||
author: "David CHANIAL (@davixx) <david.chanial@gmail.com>"
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
EXAMPLES = r'''
|
||||
# Set vm.swappiness to 5 in /etc/sysctl.conf
|
||||
- sysctl:
|
||||
- ansible.posix.sysctl:
|
||||
name: vm.swappiness
|
||||
value: '5'
|
||||
state: present
|
||||
|
||||
# Remove kernel.panic entry from /etc/sysctl.conf
|
||||
- sysctl:
|
||||
- ansible.posix.sysctl:
|
||||
name: kernel.panic
|
||||
state: absent
|
||||
sysctl_file: /etc/sysctl.conf
|
||||
|
||||
# Set kernel.panic to 3 in /tmp/test_sysctl.conf
|
||||
- sysctl:
|
||||
- ansible.posix.sysctl:
|
||||
name: kernel.panic
|
||||
value: '3'
|
||||
sysctl_file: /tmp/test_sysctl.conf
|
||||
reload: no
|
||||
|
||||
# Set ip forwarding on in /proc and verify token value with the sysctl command
|
||||
- sysctl:
|
||||
- ansible.posix.sysctl:
|
||||
name: net.ipv4.ip_forward
|
||||
value: '1'
|
||||
sysctl_set: yes
|
||||
|
||||
# Set ip forwarding on in /proc and in the sysctl file and reload if necessary
|
||||
- sysctl:
|
||||
- ansible.posix.sysctl:
|
||||
name: net.ipv4.ip_forward
|
||||
value: '1'
|
||||
sysctl_set: yes
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
from ansible.module_utils.six import text_type
|
||||
from ansible.module_utils.six.moves import shlex_quote
|
||||
from ansible.plugins.shell import ShellBase
|
||||
|
||||
DOCUMENTATION = '''
|
||||
@@ -35,4 +37,8 @@ class ShellModule(ShellBase):
|
||||
_SHELL_GROUP_RIGHT = ')'
|
||||
|
||||
def env_prefix(self, **kwargs):
|
||||
return 'env %s' % super(ShellModule, self).env_prefix(**kwargs)
|
||||
ret = []
|
||||
# All the -u options must be first, so we process them first
|
||||
ret += ['-u %s' % k for k, v in kwargs.items() if v is None]
|
||||
ret += ['%s=%s' % (k, shlex_quote(text_type(v))) for k, v in kwargs.items() if v is not None]
|
||||
return 'env %s' % ' '.join(ret)
|
||||
|
||||
@@ -38,7 +38,13 @@ class ShellModule(ShModule):
|
||||
def env_prefix(self, **kwargs):
|
||||
env = self.env.copy()
|
||||
env.update(kwargs)
|
||||
return ' '.join(['set -lx %s %s;' % (k, shlex_quote(text_type(v))) for k, v in env.items()])
|
||||
ret = []
|
||||
for k, v in kwargs.items():
|
||||
if v is None:
|
||||
ret.append('set -e %s;' % k)
|
||||
else:
|
||||
ret.append('set -lx %s %s;' % (k, shlex_quote(text_type(v))))
|
||||
return ' '.join(ret)
|
||||
|
||||
def build_module_command(self, env_string, shebang, cmd, arg_path=None):
|
||||
# don't quote the cmd if it's an empty string, because this will break pipelining mode
|
||||
|
||||
@@ -2,4 +2,3 @@ needs/privileged
|
||||
needs/root
|
||||
shippable/posix/group1
|
||||
skip/aix
|
||||
disabled # fixme
|
||||
|
||||
@@ -262,6 +262,22 @@
|
||||
fail:
|
||||
msg: Filesytem was not remounted, testing of the module failed!
|
||||
when: last_write is defined and last_write_time2 is defined and last_write_time.stdout == last_write_time2.stdout and ansible_system in ('Linux')
|
||||
- name: Remount filesystem with different opts using remounted option (Linux only)
|
||||
mount:
|
||||
path: /tmp/myfs
|
||||
state: remounted
|
||||
opts: rw,noexec
|
||||
when: ansible_system == 'Linux'
|
||||
- name: Get remounted options (Linux only)
|
||||
shell: mount | grep myfs | grep -E -w 'noexec' | wc -l
|
||||
register: remounted_options
|
||||
when: ansible_system == 'Linux'
|
||||
- name: Make sure the filesystem now has the new opts after using remounted (Linux only)
|
||||
assert:
|
||||
that:
|
||||
- "'1' in remounted_options.stdout"
|
||||
- "1 == remounted_options.stdout_lines | length"
|
||||
when: ansible_system == 'Linux'
|
||||
always:
|
||||
- name: Umount the test FS
|
||||
mount:
|
||||
|
||||
@@ -2,9 +2,14 @@ import os
|
||||
import tempfile
|
||||
|
||||
from ansible_collections.ansible.posix.tests.unit.compat import unittest
|
||||
from ansible_collections.ansible.posix.tests.unit.compat.mock import MagicMock
|
||||
from ansible.module_utils._text import to_bytes
|
||||
|
||||
from ansible_collections.ansible.posix.plugins.modules.mount import get_linux_mounts
|
||||
from ansible_collections.ansible.posix.plugins.modules.mount import (
|
||||
get_linux_mounts,
|
||||
_set_mount_save_old,
|
||||
set_mount,
|
||||
)
|
||||
|
||||
|
||||
class LinuxMountsTestCase(unittest.TestCase):
|
||||
@@ -23,3 +28,32 @@ class LinuxMountsTestCase(unittest.TestCase):
|
||||
)
|
||||
mounts = get_linux_mounts(None, path)
|
||||
self.assertEqual(mounts['/tmp/bbb']['src'], '/tmp/aaa')
|
||||
|
||||
def test_set_mount_save_old(self):
|
||||
module = MagicMock(name='AnsibleModule')
|
||||
module.check_mode = True
|
||||
module.params = {'backup': False}
|
||||
|
||||
fstab_data = [
|
||||
'UUID=8ac075e3-1124-4bb6-bef7-a6811bf8b870 / xfs defaults 0 0\n',
|
||||
'/swapfile none swap defaults 0 0\n'
|
||||
]
|
||||
path = self._create_file("".join(fstab_data))
|
||||
args = {
|
||||
'fstab': path,
|
||||
'name': '/data',
|
||||
'src': '/dev/sdb1',
|
||||
'fstype': 'ext4',
|
||||
'opts': 'defaults',
|
||||
'dump': '0',
|
||||
'passno': '0',
|
||||
}
|
||||
|
||||
name, changed = set_mount(module, args)
|
||||
self.assertEqual(name, '/data')
|
||||
self.assertTrue(changed)
|
||||
|
||||
name, backup_lines, changed = _set_mount_save_old(module, args)
|
||||
self.assertEqual(backup_lines, fstab_data)
|
||||
self.assertEqual(name, '/data')
|
||||
self.assertTrue(changed)
|
||||
|
||||
@@ -74,7 +74,7 @@ set +ux
|
||||
set -ux
|
||||
|
||||
#pip install ansible==2.9.0 --disable-pip-version-check
|
||||
pip install git+https://github.com/ansible/ansible.git@temp-2.10-devel --disable-pip-version-check
|
||||
pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check
|
||||
|
||||
COLLECTION_DIR="${HOME}/.ansible/ansible_collections/"
|
||||
TEST_DIR="${COLLECTION_DIR}/ansible/posix"
|
||||
|
||||
Reference in New Issue
Block a user