mirror of
https://github.com/ansible-collections/ansible.posix.git
synced 2026-01-12 15:45:20 +01:00
Merge branch 'ansible-collections:main' into patch-2
This commit is contained in:
commit
4174f53c6a
31 changed files with 611 additions and 73 deletions
|
|
@ -50,13 +50,31 @@ stages:
|
||||||
- template: templates/matrix.yml
|
- template: templates/matrix.yml
|
||||||
parameters:
|
parameters:
|
||||||
testFormat: devel/linux/{0}/1
|
testFormat: devel/linux/{0}/1
|
||||||
|
targets:
|
||||||
|
- name: CentOS 7
|
||||||
|
test: centos7
|
||||||
|
- name: Fedora 34
|
||||||
|
test: fedora34
|
||||||
|
- name: Fedora 35
|
||||||
|
test: fedora35
|
||||||
|
- name: openSUSE 15 py3
|
||||||
|
test: opensuse15
|
||||||
|
- name: Ubuntu 18.04
|
||||||
|
test: ubuntu1804
|
||||||
|
- name: Ubuntu 20.04
|
||||||
|
test: ubuntu2004
|
||||||
|
- stage: Docker_2_12
|
||||||
|
displayName: Docker 2.12
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
testFormat: 2.12/linux/{0}/1
|
||||||
targets:
|
targets:
|
||||||
- name: CentOS 6
|
- name: CentOS 6
|
||||||
test: centos6
|
test: centos6
|
||||||
- name: CentOS 7
|
- name: CentOS 7
|
||||||
test: centos7
|
test: centos7
|
||||||
- name: CentOS 8
|
|
||||||
test: centos8
|
|
||||||
- name: Fedora 33
|
- name: Fedora 33
|
||||||
test: fedora33
|
test: fedora33
|
||||||
- name: Fedora 34
|
- name: Fedora 34
|
||||||
|
|
@ -81,8 +99,6 @@ stages:
|
||||||
test: centos6
|
test: centos6
|
||||||
- name: CentOS 7
|
- name: CentOS 7
|
||||||
test: centos7
|
test: centos7
|
||||||
- name: CentOS 8
|
|
||||||
test: centos8
|
|
||||||
- name: Fedora 32
|
- name: Fedora 32
|
||||||
test: fedora32
|
test: fedora32
|
||||||
- name: Fedora 33
|
- name: Fedora 33
|
||||||
|
|
@ -107,8 +123,6 @@ stages:
|
||||||
test: centos6
|
test: centos6
|
||||||
- name: CentOS 7
|
- name: CentOS 7
|
||||||
test: centos7
|
test: centos7
|
||||||
- name: CentOS 8
|
|
||||||
test: centos8
|
|
||||||
- name: Fedora 30
|
- name: Fedora 30
|
||||||
test: fedora30
|
test: fedora30
|
||||||
- name: Fedora 31
|
- name: Fedora 31
|
||||||
|
|
@ -133,8 +147,6 @@ stages:
|
||||||
test: centos6
|
test: centos6
|
||||||
- name: CentOS 7
|
- name: CentOS 7
|
||||||
test: centos7
|
test: centos7
|
||||||
- name: CentOS 8
|
|
||||||
test: centos8
|
|
||||||
- name: Fedora 30
|
- name: Fedora 30
|
||||||
test: fedora30
|
test: fedora30
|
||||||
- name: Fedora 31
|
- name: Fedora 31
|
||||||
|
|
@ -156,6 +168,24 @@ stages:
|
||||||
- template: templates/matrix.yml
|
- template: templates/matrix.yml
|
||||||
parameters:
|
parameters:
|
||||||
testFormat: devel/{0}/1
|
testFormat: devel/{0}/1
|
||||||
|
targets:
|
||||||
|
- name: MacOS 12.0
|
||||||
|
test: macos/12.0
|
||||||
|
- name: RHEL 7.9
|
||||||
|
test: rhel/7.9
|
||||||
|
- name: RHEL 8.5
|
||||||
|
test: rhel/8.5
|
||||||
|
- name: FreeBSD 12.3
|
||||||
|
test: freebsd/12.3
|
||||||
|
- name: FreeBSD 13.0
|
||||||
|
test: freebsd/13.0
|
||||||
|
- stage: Remote_2_12
|
||||||
|
displayName: Remote 2.12
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
testFormat: 2.12/{0}/1
|
||||||
targets:
|
targets:
|
||||||
- name: MacOS 11.1
|
- name: MacOS 11.1
|
||||||
test: macos/11.1
|
test: macos/11.1
|
||||||
|
|
@ -195,8 +225,8 @@ stages:
|
||||||
targets:
|
targets:
|
||||||
- name: OS X 10.11
|
- name: OS X 10.11
|
||||||
test: osx/10.11
|
test: osx/10.11
|
||||||
- name: RHEL 7.6
|
- name: RHEL 7.9
|
||||||
test: rhel/7.6
|
test: rhel/7.9
|
||||||
- name: RHEL 8.2
|
- name: RHEL 8.2
|
||||||
test: rhel/8.2
|
test: rhel/8.2
|
||||||
- name: FreeBSD 11.1
|
- name: FreeBSD 11.1
|
||||||
|
|
@ -214,8 +244,8 @@ stages:
|
||||||
targets:
|
targets:
|
||||||
- name: OS X 10.11
|
- name: OS X 10.11
|
||||||
test: osx/10.11
|
test: osx/10.11
|
||||||
- name: RHEL 7.6
|
- name: RHEL 7.9
|
||||||
test: rhel/7.6
|
test: rhel/7.9
|
||||||
- name: RHEL 8.1
|
- name: RHEL 8.1
|
||||||
test: rhel/8.1
|
test: rhel/8.1
|
||||||
- name: FreeBSD 11.1
|
- name: FreeBSD 11.1
|
||||||
|
|
@ -230,9 +260,11 @@ stages:
|
||||||
- Remote_2_9
|
- Remote_2_9
|
||||||
- Docker_2_9
|
- Docker_2_9
|
||||||
- Remote_2_10
|
- Remote_2_10
|
||||||
- Remote_2_11
|
|
||||||
- Docker_2_10
|
- Docker_2_10
|
||||||
|
- Remote_2_11
|
||||||
- Docker_2_11
|
- Docker_2_11
|
||||||
|
- Remote_2_12
|
||||||
|
- Docker_2_12
|
||||||
- Remote_devel
|
- Remote_devel
|
||||||
- Docker_devel
|
- Docker_devel
|
||||||
jobs:
|
jobs:
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,8 @@ None
|
||||||
|
|
||||||
<!-- List the versions of Ansible the collection has been tested with. Must match what is in galaxy.yml. -->
|
<!-- List the versions of Ansible the collection has been tested with. Must match what is in galaxy.yml. -->
|
||||||
|
|
||||||
* ansible-core 2.12 (devel)
|
* ansible-core 2.13 (devel)
|
||||||
|
* ansible-core 2.12 (stable)
|
||||||
* ansible-core 2.11 (stable)
|
* ansible-core 2.11 (stable)
|
||||||
* ansible-base 2.10 (stable)
|
* ansible-base 2.10 (stable)
|
||||||
* ansible 2.9 (stable)
|
* ansible 2.9 (stable)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# This is a cross-platform list tracking distribution packages needed by tests;
|
# This is a cross-platform list tracking distribution packages needed by tests;
|
||||||
# see https://docs.openstack.org/infra/bindep/ for additional information.
|
# see https://docs.openstack.org/infra/bindep/ for additional information.
|
||||||
|
|
||||||
rsync [platform:centos-8 platform:rhel-8]
|
rsync [platform:rhel-8]
|
||||||
|
|
|
||||||
3
changelogs/fragments/272-copy_ignore_txt.yml
Normal file
3
changelogs/fragments/272-copy_ignore_txt.yml
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
trivial:
|
||||||
|
- Copy ignore-2.12.txt to ignore-2.13.txt.
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
trivial:
|
||||||
|
- Fix integration tests of synchronize and sysctl to address chaging behavior on devel branch (https://github.com/ansible-collections/overview/issues/45).
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
trivial:
|
||||||
|
- Fix unit tests of synchronize action plugin to use yaml.safe_load().
|
||||||
3
changelogs/fragments/287_firewalld_requirements.yml
Normal file
3
changelogs/fragments/287_firewalld_requirements.yml
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
trivial:
|
||||||
|
- firewalld - add python-firewall to requirements (https://github.com/ansible-collections/ansible.posix/issues/286).
|
||||||
3
changelogs/fragments/288_mounts_options.yml
Normal file
3
changelogs/fragments/288_mounts_options.yml
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
trivial:
|
||||||
|
- mount - remove deprecated option from nfs example
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
bugfixes:
|
||||||
|
- firewalld - Refine the handling of exclusive options (https://github.com/ansible-collections/ansible.posix/issues/255).
|
||||||
3
changelogs/fragments/299_seboolean_python3.yml
Normal file
3
changelogs/fragments/299_seboolean_python3.yml
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
bugfixes:
|
||||||
|
- seboolean - add ``python3-libsemanage`` package dependency for RHEL8+ systems.
|
||||||
3
changelogs/fragments/302_shippable_exit_code.yml
Normal file
3
changelogs/fragments/302_shippable_exit_code.yml
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
trivial:
|
||||||
|
- CI tests - fix exit code to address shellckeck test issue (https://github.com/ansible-collections/ansible.posix/issues/301).
|
||||||
3
changelogs/fragments/304_pep632.yml
Normal file
3
changelogs/fragments/304_pep632.yml
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
bugfixes:
|
||||||
|
- Use vendored version of ``distutils.version`` instead of the deprecated Python standard library to address PEP 632 (https://github.com/ansible-collections/ansible.posix/issues/303).
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
bugfixes:
|
||||||
|
- Fix for whitespace in source full path causing error ```code 23) at main.c(1330) [sender=3.2.3]``` (https://github.com/ansible-collections/ansible.posix/pull/278)
|
||||||
1
codecov.yml
Normal file
1
codecov.yml
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
comment: false
|
||||||
344
plugins/module_utils/_version.py
Normal file
344
plugins/module_utils/_version.py
Normal file
|
|
@ -0,0 +1,344 @@
|
||||||
|
# Vendored copy of distutils/version.py from CPython 3.9.5
|
||||||
|
#
|
||||||
|
# Implements multiple version numbering conventions for the
|
||||||
|
# Python Module Distribution Utilities.
|
||||||
|
#
|
||||||
|
# PSF License (see licenses/PSF-license.txt or https://opensource.org/licenses/Python-2.0)
|
||||||
|
#
|
||||||
|
|
||||||
|
"""Provides classes to represent module version numbers (one class for
|
||||||
|
each style of version numbering). There are currently two such classes
|
||||||
|
implemented: StrictVersion and LooseVersion.
|
||||||
|
|
||||||
|
Every version number class implements the following interface:
|
||||||
|
* the 'parse' method takes a string and parses it to some internal
|
||||||
|
representation; if the string is an invalid version number,
|
||||||
|
'parse' raises a ValueError exception
|
||||||
|
* the class constructor takes an optional string argument which,
|
||||||
|
if supplied, is passed to 'parse'
|
||||||
|
* __str__ reconstructs the string that was passed to 'parse' (or
|
||||||
|
an equivalent string -- ie. one that will generate an equivalent
|
||||||
|
version number instance)
|
||||||
|
* __repr__ generates Python code to recreate the version number instance
|
||||||
|
* _cmp compares the current instance with either another instance
|
||||||
|
of the same class or a string (which will be parsed to an instance
|
||||||
|
of the same class, thus must follow the same rules)
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
try:
|
||||||
|
RE_FLAGS = re.VERBOSE | re.ASCII
|
||||||
|
except AttributeError:
|
||||||
|
RE_FLAGS = re.VERBOSE
|
||||||
|
|
||||||
|
|
||||||
|
class Version:
|
||||||
|
"""Abstract base class for version numbering classes. Just provides
|
||||||
|
constructor (__init__) and reproducer (__repr__), because those
|
||||||
|
seem to be the same for all version numbering classes; and route
|
||||||
|
rich comparisons to _cmp.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, vstring=None):
|
||||||
|
if vstring:
|
||||||
|
self.parse(vstring)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "%s ('%s')" % (self.__class__.__name__, str(self))
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
c = self._cmp(other)
|
||||||
|
if c is NotImplemented:
|
||||||
|
return c
|
||||||
|
return c == 0
|
||||||
|
|
||||||
|
def __lt__(self, other):
|
||||||
|
c = self._cmp(other)
|
||||||
|
if c is NotImplemented:
|
||||||
|
return c
|
||||||
|
return c < 0
|
||||||
|
|
||||||
|
def __le__(self, other):
|
||||||
|
c = self._cmp(other)
|
||||||
|
if c is NotImplemented:
|
||||||
|
return c
|
||||||
|
return c <= 0
|
||||||
|
|
||||||
|
def __gt__(self, other):
|
||||||
|
c = self._cmp(other)
|
||||||
|
if c is NotImplemented:
|
||||||
|
return c
|
||||||
|
return c > 0
|
||||||
|
|
||||||
|
def __ge__(self, other):
|
||||||
|
c = self._cmp(other)
|
||||||
|
if c is NotImplemented:
|
||||||
|
return c
|
||||||
|
return c >= 0
|
||||||
|
|
||||||
|
|
||||||
|
# Interface for version-number classes -- must be implemented
|
||||||
|
# by the following classes (the concrete ones -- Version should
|
||||||
|
# be treated as an abstract class).
|
||||||
|
# __init__ (string) - create and take same action as 'parse'
|
||||||
|
# (string parameter is optional)
|
||||||
|
# parse (string) - convert a string representation to whatever
|
||||||
|
# internal representation is appropriate for
|
||||||
|
# this style of version numbering
|
||||||
|
# __str__ (self) - convert back to a string; should be very similar
|
||||||
|
# (if not identical to) the string supplied to parse
|
||||||
|
# __repr__ (self) - generate Python code to recreate
|
||||||
|
# the instance
|
||||||
|
# _cmp (self, other) - compare two version numbers ('other' may
|
||||||
|
# be an unparsed version string, or another
|
||||||
|
# instance of your version class)
|
||||||
|
|
||||||
|
|
||||||
|
class StrictVersion(Version):
|
||||||
|
"""Version numbering for anal retentives and software idealists.
|
||||||
|
Implements the standard interface for version number classes as
|
||||||
|
described above. A version number consists of two or three
|
||||||
|
dot-separated numeric components, with an optional "pre-release" tag
|
||||||
|
on the end. The pre-release tag consists of the letter 'a' or 'b'
|
||||||
|
followed by a number. If the numeric components of two version
|
||||||
|
numbers are equal, then one with a pre-release tag will always
|
||||||
|
be deemed earlier (lesser) than one without.
|
||||||
|
|
||||||
|
The following are valid version numbers (shown in the order that
|
||||||
|
would be obtained by sorting according to the supplied cmp function):
|
||||||
|
|
||||||
|
0.4 0.4.0 (these two are equivalent)
|
||||||
|
0.4.1
|
||||||
|
0.5a1
|
||||||
|
0.5b3
|
||||||
|
0.5
|
||||||
|
0.9.6
|
||||||
|
1.0
|
||||||
|
1.0.4a3
|
||||||
|
1.0.4b1
|
||||||
|
1.0.4
|
||||||
|
|
||||||
|
The following are examples of invalid version numbers:
|
||||||
|
|
||||||
|
1
|
||||||
|
2.7.2.2
|
||||||
|
1.3.a4
|
||||||
|
1.3pl1
|
||||||
|
1.3c4
|
||||||
|
|
||||||
|
The rationale for this version numbering system will be explained
|
||||||
|
in the distutils documentation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
version_re = re.compile(r"^(\d+) \. (\d+) (\. (\d+))? ([ab](\d+))?$", RE_FLAGS)
|
||||||
|
|
||||||
|
def parse(self, vstring):
|
||||||
|
match = self.version_re.match(vstring)
|
||||||
|
if not match:
|
||||||
|
raise ValueError("invalid version number '%s'" % vstring)
|
||||||
|
|
||||||
|
(major, minor, patch, prerelease, prerelease_num) = match.group(1, 2, 4, 5, 6)
|
||||||
|
|
||||||
|
if patch:
|
||||||
|
self.version = tuple(map(int, [major, minor, patch]))
|
||||||
|
else:
|
||||||
|
self.version = tuple(map(int, [major, minor])) + (0,)
|
||||||
|
|
||||||
|
if prerelease:
|
||||||
|
self.prerelease = (prerelease[0], int(prerelease_num))
|
||||||
|
else:
|
||||||
|
self.prerelease = None
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.version[2] == 0:
|
||||||
|
vstring = ".".join(map(str, self.version[0:2]))
|
||||||
|
else:
|
||||||
|
vstring = ".".join(map(str, self.version))
|
||||||
|
|
||||||
|
if self.prerelease:
|
||||||
|
vstring = vstring + self.prerelease[0] + str(self.prerelease[1])
|
||||||
|
|
||||||
|
return vstring
|
||||||
|
|
||||||
|
def _cmp(self, other):
|
||||||
|
if isinstance(other, str):
|
||||||
|
other = StrictVersion(other)
|
||||||
|
elif not isinstance(other, StrictVersion):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
if self.version != other.version:
|
||||||
|
# numeric versions don't match
|
||||||
|
# prerelease stuff doesn't matter
|
||||||
|
if self.version < other.version:
|
||||||
|
return -1
|
||||||
|
else:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
# have to compare prerelease
|
||||||
|
# case 1: neither has prerelease; they're equal
|
||||||
|
# case 2: self has prerelease, other doesn't; other is greater
|
||||||
|
# case 3: self doesn't have prerelease, other does: self is greater
|
||||||
|
# case 4: both have prerelease: must compare them!
|
||||||
|
|
||||||
|
if not self.prerelease and not other.prerelease:
|
||||||
|
return 0
|
||||||
|
elif self.prerelease and not other.prerelease:
|
||||||
|
return -1
|
||||||
|
elif not self.prerelease and other.prerelease:
|
||||||
|
return 1
|
||||||
|
elif self.prerelease and other.prerelease:
|
||||||
|
if self.prerelease == other.prerelease:
|
||||||
|
return 0
|
||||||
|
elif self.prerelease < other.prerelease:
|
||||||
|
return -1
|
||||||
|
else:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
raise AssertionError("never get here")
|
||||||
|
|
||||||
|
|
||||||
|
# end class StrictVersion
|
||||||
|
|
||||||
|
# The rules according to Greg Stein:
|
||||||
|
# 1) a version number has 1 or more numbers separated by a period or by
|
||||||
|
# sequences of letters. If only periods, then these are compared
|
||||||
|
# left-to-right to determine an ordering.
|
||||||
|
# 2) sequences of letters are part of the tuple for comparison and are
|
||||||
|
# compared lexicographically
|
||||||
|
# 3) recognize the numeric components may have leading zeroes
|
||||||
|
#
|
||||||
|
# The LooseVersion class below implements these rules: a version number
|
||||||
|
# string is split up into a tuple of integer and string components, and
|
||||||
|
# comparison is a simple tuple comparison. This means that version
|
||||||
|
# numbers behave in a predictable and obvious way, but a way that might
|
||||||
|
# not necessarily be how people *want* version numbers to behave. There
|
||||||
|
# wouldn't be a problem if people could stick to purely numeric version
|
||||||
|
# numbers: just split on period and compare the numbers as tuples.
|
||||||
|
# However, people insist on putting letters into their version numbers;
|
||||||
|
# the most common purpose seems to be:
|
||||||
|
# - indicating a "pre-release" version
|
||||||
|
# ('alpha', 'beta', 'a', 'b', 'pre', 'p')
|
||||||
|
# - indicating a post-release patch ('p', 'pl', 'patch')
|
||||||
|
# but of course this can't cover all version number schemes, and there's
|
||||||
|
# no way to know what a programmer means without asking him.
|
||||||
|
#
|
||||||
|
# The problem is what to do with letters (and other non-numeric
|
||||||
|
# characters) in a version number. The current implementation does the
|
||||||
|
# obvious and predictable thing: keep them as strings and compare
|
||||||
|
# lexically within a tuple comparison. This has the desired effect if
|
||||||
|
# an appended letter sequence implies something "post-release":
|
||||||
|
# eg. "0.99" < "0.99pl14" < "1.0", and "5.001" < "5.001m" < "5.002".
|
||||||
|
#
|
||||||
|
# However, if letters in a version number imply a pre-release version,
|
||||||
|
# the "obvious" thing isn't correct. Eg. you would expect that
|
||||||
|
# "1.5.1" < "1.5.2a2" < "1.5.2", but under the tuple/lexical comparison
|
||||||
|
# implemented here, this just isn't so.
|
||||||
|
#
|
||||||
|
# Two possible solutions come to mind. The first is to tie the
|
||||||
|
# comparison algorithm to a particular set of semantic rules, as has
|
||||||
|
# been done in the StrictVersion class above. This works great as long
|
||||||
|
# as everyone can go along with bondage and discipline. Hopefully a
|
||||||
|
# (large) subset of Python module programmers will agree that the
|
||||||
|
# particular flavour of bondage and discipline provided by StrictVersion
|
||||||
|
# provides enough benefit to be worth using, and will submit their
|
||||||
|
# version numbering scheme to its domination. The free-thinking
|
||||||
|
# anarchists in the lot will never give in, though, and something needs
|
||||||
|
# to be done to accommodate them.
|
||||||
|
#
|
||||||
|
# Perhaps a "moderately strict" version class could be implemented that
|
||||||
|
# lets almost anything slide (syntactically), and makes some heuristic
|
||||||
|
# assumptions about non-digits in version number strings. This could
|
||||||
|
# sink into special-case-hell, though; if I was as talented and
|
||||||
|
# idiosyncratic as Larry Wall, I'd go ahead and implement a class that
|
||||||
|
# somehow knows that "1.2.1" < "1.2.2a2" < "1.2.2" < "1.2.2pl3", and is
|
||||||
|
# just as happy dealing with things like "2g6" and "1.13++". I don't
|
||||||
|
# think I'm smart enough to do it right though.
|
||||||
|
#
|
||||||
|
# In any case, I've coded the test suite for this module (see
|
||||||
|
# ../test/test_version.py) specifically to fail on things like comparing
|
||||||
|
# "1.2a2" and "1.2". That's not because the *code* is doing anything
|
||||||
|
# wrong, it's because the simple, obvious design doesn't match my
|
||||||
|
# complicated, hairy expectations for real-world version numbers. It
|
||||||
|
# would be a snap to fix the test suite to say, "Yep, LooseVersion does
|
||||||
|
# the Right Thing" (ie. the code matches the conception). But I'd rather
|
||||||
|
# have a conception that matches common notions about version numbers.
|
||||||
|
|
||||||
|
|
||||||
|
class LooseVersion(Version):
|
||||||
|
"""Version numbering for anarchists and software realists.
|
||||||
|
Implements the standard interface for version number classes as
|
||||||
|
described above. A version number consists of a series of numbers,
|
||||||
|
separated by either periods or strings of letters. When comparing
|
||||||
|
version numbers, the numeric components will be compared
|
||||||
|
numerically, and the alphabetic components lexically. The following
|
||||||
|
are all valid version numbers, in no particular order:
|
||||||
|
|
||||||
|
1.5.1
|
||||||
|
1.5.2b2
|
||||||
|
161
|
||||||
|
3.10a
|
||||||
|
8.02
|
||||||
|
3.4j
|
||||||
|
1996.07.12
|
||||||
|
3.2.pl0
|
||||||
|
3.1.1.6
|
||||||
|
2g6
|
||||||
|
11g
|
||||||
|
0.960923
|
||||||
|
2.2beta29
|
||||||
|
1.13++
|
||||||
|
5.5.kw
|
||||||
|
2.0b1pl0
|
||||||
|
|
||||||
|
In fact, there is no such thing as an invalid version number under
|
||||||
|
this scheme; the rules for comparison are simple and predictable,
|
||||||
|
but may not always give the results you want (for some definition
|
||||||
|
of "want").
|
||||||
|
"""
|
||||||
|
|
||||||
|
component_re = re.compile(r"(\d+ | [a-z]+ | \.)", re.VERBOSE)
|
||||||
|
|
||||||
|
def __init__(self, vstring=None):
|
||||||
|
if vstring:
|
||||||
|
self.parse(vstring)
|
||||||
|
|
||||||
|
def parse(self, vstring):
|
||||||
|
# I've given up on thinking I can reconstruct the version string
|
||||||
|
# from the parsed tuple -- so I just store the string here for
|
||||||
|
# use by __str__
|
||||||
|
self.vstring = vstring
|
||||||
|
components = [x for x in self.component_re.split(vstring) if x and x != "."]
|
||||||
|
for i, obj in enumerate(components):
|
||||||
|
try:
|
||||||
|
components[i] = int(obj)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.version = components
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.vstring
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "LooseVersion ('%s')" % str(self)
|
||||||
|
|
||||||
|
def _cmp(self, other):
|
||||||
|
if isinstance(other, str):
|
||||||
|
other = LooseVersion(other)
|
||||||
|
elif not isinstance(other, LooseVersion):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
if self.version == other.version:
|
||||||
|
return 0
|
||||||
|
if self.version < other.version:
|
||||||
|
return -1
|
||||||
|
if self.version > other.version:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
# end class LooseVersion
|
||||||
|
|
@ -4,11 +4,10 @@
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
from ansible_collections.ansible.posix.plugins.module_utils.version import LooseVersion
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
# Imports and info for sanity checking
|
|
||||||
from distutils.version import LooseVersion
|
|
||||||
|
|
||||||
FW_VERSION = None
|
FW_VERSION = None
|
||||||
fw = None
|
fw = None
|
||||||
|
|
|
||||||
18
plugins/module_utils/version.py
Normal file
18
plugins/module_utils/version.py
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright: (c) 2021, Felix Fontein <felix@fontein.de>
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
"""Provide version object to compare version numbers."""
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
|
# Once we drop support for Ansible 2.9, ansible-base 2.10, and ansible-core 2.11, we can
|
||||||
|
# remove the _version.py file, and replace the following import by
|
||||||
|
#
|
||||||
|
# from ansible.module_utils.compat.version import LooseVersion
|
||||||
|
|
||||||
|
from ._version import LooseVersion, StrictVersion
|
||||||
|
|
@ -128,8 +128,11 @@ notes:
|
||||||
The module will not take care of this for you implicitly because that would undo any previously performed immediate actions which were not
|
The module will not take care of this for you implicitly because that would undo any previously performed immediate actions which were not
|
||||||
permanent. Therefore, if you require immediate access to a newly created zone it is recommended you reload firewalld immediately after the zone
|
permanent. Therefore, if you require immediate access to a newly created zone it is recommended you reload firewalld immediately after the zone
|
||||||
creation returns with a changed state and before you perform any other immediate, non-permanent actions on that zone.
|
creation returns with a changed state and before you perform any other immediate, non-permanent actions on that zone.
|
||||||
|
- This module needs C(python-firewall) or C(python3-firewall) on managed nodes.
|
||||||
|
It is usually provided as a subset with C(firewalld) from the OS distributor for the OS default Python interpreter.
|
||||||
requirements:
|
requirements:
|
||||||
- firewalld >= 0.2.11
|
- firewalld >= 0.2.11
|
||||||
|
- python-firewall >= 0.2.11
|
||||||
author:
|
author:
|
||||||
- Adam Miller (@maxamillion)
|
- Adam Miller (@maxamillion)
|
||||||
'''
|
'''
|
||||||
|
|
@ -757,6 +760,10 @@ def main():
|
||||||
target=('zone',),
|
target=('zone',),
|
||||||
source=('permanent',),
|
source=('permanent',),
|
||||||
),
|
),
|
||||||
|
mutually_exclusive=[
|
||||||
|
['icmp_block', 'icmp_block_inversion', 'service', 'port', 'port_forward', 'rich_rule',
|
||||||
|
'interface', 'masquerade', 'source', 'target']
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
permanent = module.params['permanent']
|
permanent = module.params['permanent']
|
||||||
|
|
@ -813,33 +820,11 @@ def main():
|
||||||
if 'toaddr' in port_forward:
|
if 'toaddr' in port_forward:
|
||||||
port_forward_toaddr = port_forward['toaddr']
|
port_forward_toaddr = port_forward['toaddr']
|
||||||
|
|
||||||
modification_count = 0
|
modification = False
|
||||||
if icmp_block is not None:
|
if any([icmp_block, icmp_block_inversion, service, port, port_forward, rich_rule,
|
||||||
modification_count += 1
|
interface, masquerade, source, target]):
|
||||||
if icmp_block_inversion is not None:
|
modification = True
|
||||||
modification_count += 1
|
if modification and desired_state in ['absent', 'present'] and target is None:
|
||||||
if service is not None:
|
|
||||||
modification_count += 1
|
|
||||||
if port is not None:
|
|
||||||
modification_count += 1
|
|
||||||
if port_forward is not None:
|
|
||||||
modification_count += 1
|
|
||||||
if rich_rule is not None:
|
|
||||||
modification_count += 1
|
|
||||||
if interface is not None:
|
|
||||||
modification_count += 1
|
|
||||||
if masquerade is not None:
|
|
||||||
modification_count += 1
|
|
||||||
if source is not None:
|
|
||||||
modification_count += 1
|
|
||||||
if target is not None:
|
|
||||||
modification_count += 1
|
|
||||||
|
|
||||||
if modification_count > 1:
|
|
||||||
module.fail_json(
|
|
||||||
msg='can only operate on port, service, rich_rule, masquerade, icmp_block, icmp_block_inversion, interface or source at once'
|
|
||||||
)
|
|
||||||
elif (modification_count > 0) and (desired_state in ['absent', 'present']) and (target is None):
|
|
||||||
module.fail_json(
|
module.fail_json(
|
||||||
msg='absent and present state can only be used in zone level operations'
|
msg='absent and present state can only be used in zone level operations'
|
||||||
)
|
)
|
||||||
|
|
@ -1024,7 +1009,7 @@ def main():
|
||||||
msgs = msgs + transaction_msgs
|
msgs = msgs + transaction_msgs
|
||||||
|
|
||||||
''' If there are no changes within the zone we are operating on the zone itself '''
|
''' If there are no changes within the zone we are operating on the zone itself '''
|
||||||
if modification_count == 0 and desired_state in ['absent', 'present']:
|
if not modification and desired_state in ['absent', 'present']:
|
||||||
|
|
||||||
transaction = ZoneTransaction(
|
transaction = ZoneTransaction(
|
||||||
module,
|
module,
|
||||||
|
|
|
||||||
|
|
@ -204,8 +204,9 @@ firewalld_info:
|
||||||
'''
|
'''
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||||
|
from ansible.module_utils.six import raise_from
|
||||||
from ansible.module_utils._text import to_native
|
from ansible.module_utils._text import to_native
|
||||||
from distutils.version import StrictVersion
|
from ansible_collections.ansible.posix.plugins.module_utils.version import StrictVersion
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -172,7 +172,7 @@ EXAMPLES = r'''
|
||||||
ansible.posix.mount:
|
ansible.posix.mount:
|
||||||
src: 192.168.1.100:/nfs/ssd/shared_data
|
src: 192.168.1.100:/nfs/ssd/shared_data
|
||||||
path: /mnt/shared_data
|
path: /mnt/shared_data
|
||||||
opts: rw,sync,hard,intr
|
opts: rw,sync,hard
|
||||||
state: mounted
|
state: mounted
|
||||||
fstype: nfs
|
fstype: nfs
|
||||||
|
|
||||||
|
|
@ -180,7 +180,7 @@ EXAMPLES = r'''
|
||||||
ansible.posix.mount:
|
ansible.posix.mount:
|
||||||
src: 192.168.1.100:/nfs/ssd/shared_data
|
src: 192.168.1.100:/nfs/ssd/shared_data
|
||||||
path: /mnt/shared_data
|
path: /mnt/shared_data
|
||||||
opts: rw,sync,hard,intr
|
opts: rw,sync,hard
|
||||||
boot: no
|
boot: no
|
||||||
state: mounted
|
state: mounted
|
||||||
fstype: nfs
|
fstype: nfs
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ notes:
|
||||||
requirements:
|
requirements:
|
||||||
- libselinux-python
|
- libselinux-python
|
||||||
- libsemanage-python
|
- libsemanage-python
|
||||||
|
- python3-libsemanage
|
||||||
author:
|
author:
|
||||||
- Stephen Fromm (@sfromm)
|
- Stephen Fromm (@sfromm)
|
||||||
'''
|
'''
|
||||||
|
|
@ -284,7 +285,7 @@ def main():
|
||||||
module.fail_json(msg=missing_required_lib('libselinux-python'), exception=SELINUX_IMP_ERR)
|
module.fail_json(msg=missing_required_lib('libselinux-python'), exception=SELINUX_IMP_ERR)
|
||||||
|
|
||||||
if not HAVE_SEMANAGE:
|
if not HAVE_SEMANAGE:
|
||||||
module.fail_json(msg=missing_required_lib('libsemanage-python'), exception=SEMANAGE_IMP_ERR)
|
module.fail_json(msg=missing_required_lib('libsemanage-python or python3-libsemanage'), exception=SEMANAGE_IMP_ERR)
|
||||||
|
|
||||||
ignore_selinux_state = module.params['ignore_selinux_state']
|
ignore_selinux_state = module.params['ignore_selinux_state']
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -586,8 +586,8 @@ def main():
|
||||||
if '@' not in dest:
|
if '@' not in dest:
|
||||||
dest = os.path.expanduser(dest)
|
dest = os.path.expanduser(dest)
|
||||||
|
|
||||||
cmd.append(source)
|
cmd.append(shlex_quote(source))
|
||||||
cmd.append(dest)
|
cmd.append(shlex_quote(dest))
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ matrix:
|
||||||
- env: T=2.9/freebsd/12.0/1
|
- env: T=2.9/freebsd/12.0/1
|
||||||
- env: T=2.9/linux/centos6/1
|
- env: T=2.9/linux/centos6/1
|
||||||
- env: T=2.9/linux/centos7/1
|
- env: T=2.9/linux/centos7/1
|
||||||
- env: T=2.9/linux/centos8/1
|
# - env: T=2.9/linux/centos8/1
|
||||||
- env: T=2.9/linux/fedora30/1
|
- env: T=2.9/linux/fedora30/1
|
||||||
- env: T=2.9/linux/fedora31/1
|
- env: T=2.9/linux/fedora31/1
|
||||||
- env: T=2.9/linux/opensuse15py2/1
|
- env: T=2.9/linux/opensuse15py2/1
|
||||||
|
|
@ -30,7 +30,7 @@ matrix:
|
||||||
- env: T=2.10/freebsd/12.1/1
|
- env: T=2.10/freebsd/12.1/1
|
||||||
- env: T=2.10/linux/centos6/1
|
- env: T=2.10/linux/centos6/1
|
||||||
- env: T=2.10/linux/centos7/1
|
- env: T=2.10/linux/centos7/1
|
||||||
- env: T=2.10/linux/centos8/1
|
# - env: T=2.10/linux/centos8/1
|
||||||
- env: T=2.10/linux/fedora30/1
|
- env: T=2.10/linux/fedora30/1
|
||||||
- env: T=2.10/linux/fedora31/1
|
- env: T=2.10/linux/fedora31/1
|
||||||
- env: T=2.10/linux/opensuse15py2/1
|
- env: T=2.10/linux/opensuse15py2/1
|
||||||
|
|
@ -45,7 +45,7 @@ matrix:
|
||||||
- env: T=devel/freebsd/12.1/1
|
- env: T=devel/freebsd/12.1/1
|
||||||
- env: T=devel/linux/centos6/1
|
- env: T=devel/linux/centos6/1
|
||||||
- env: T=devel/linux/centos7/1
|
- env: T=devel/linux/centos7/1
|
||||||
- env: T=devel/linux/centos8/1
|
# - env: T=devel/linux/centos8/1
|
||||||
- env: T=devel/linux/fedora30/1
|
- env: T=devel/linux/fedora30/1
|
||||||
- env: T=devel/linux/fedora31/1
|
- env: T=devel/linux/fedora31/1
|
||||||
- env: T=devel/linux/opensuse15py2/1
|
- env: T=devel/linux/opensuse15py2/1
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,16 @@
|
||||||
group:
|
group:
|
||||||
name: "{{ test_group }}"
|
name: "{{ test_group }}"
|
||||||
|
|
||||||
|
- name: Clean up working directory and files
|
||||||
|
file:
|
||||||
|
path: "{{ output_dir }}"
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Create working directory
|
||||||
|
file:
|
||||||
|
path: "{{ output_dir }}"
|
||||||
|
state: directory
|
||||||
|
|
||||||
- name: Create ansible file
|
- name: Create ansible file
|
||||||
file:
|
file:
|
||||||
path: "{{ test_file }}"
|
path: "{{ test_file }}"
|
||||||
|
|
|
||||||
|
|
@ -82,4 +82,4 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result is not changed
|
- result is not changed
|
||||||
- "result.msg == 'can only operate on port, service, rich_rule, masquerade, icmp_block, icmp_block_inversion, interface or source at once'"
|
- "result.msg == 'parameters are mutually exclusive: icmp_block|icmp_block_inversion|service|port|port_forward|rich_rule|interface|masquerade|source|target'"
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,19 @@
|
||||||
state: present
|
state: present
|
||||||
|
|
||||||
- name: TEST 1 | Get current SELinux config file contents
|
- name: TEST 1 | Get current SELinux config file contents
|
||||||
|
slurp:
|
||||||
|
src: /etc/sysconfig/selinux
|
||||||
|
register: selinux_config_original_base64
|
||||||
|
|
||||||
|
- name: TEST 1 | Register SELinux config and SELinux status
|
||||||
set_fact:
|
set_fact:
|
||||||
selinux_config_original: "{{ lookup('file', '/etc/sysconfig/selinux').split('\n') }}"
|
selinux_config_original_raw: "{{ selinux_config_original_base64.content | b64decode }}"
|
||||||
before_test_sestatus: "{{ ansible_selinux }}"
|
before_test_sestatus: "{{ ansible_selinux }}"
|
||||||
|
|
||||||
|
- name: TEST 1 | Split by line and register original config
|
||||||
|
set_fact:
|
||||||
|
selinux_config_original: "{{ selinux_config_original_raw.split('\n') }}"
|
||||||
|
|
||||||
- debug:
|
- debug:
|
||||||
var: "{{ item }}"
|
var: "{{ item }}"
|
||||||
verbosity: 1
|
verbosity: 1
|
||||||
|
|
@ -95,8 +104,17 @@
|
||||||
- _disable_test2.reboot_required
|
- _disable_test2.reboot_required
|
||||||
|
|
||||||
- name: TEST 1 | Get modified config file
|
- name: TEST 1 | Get modified config file
|
||||||
|
slurp:
|
||||||
|
src: /etc/sysconfig/selinux
|
||||||
|
register: selinux_config_after_base64
|
||||||
|
|
||||||
|
- name: TEST 1 | Register modified config
|
||||||
set_fact:
|
set_fact:
|
||||||
selinux_config_after: "{{ lookup('file', '/etc/sysconfig/selinux').split('\n') }}"
|
selinux_config_after_raw: "{{ selinux_config_after_base64.content | b64decode }}"
|
||||||
|
|
||||||
|
- name: TEST 1 | Split by line and register modified config
|
||||||
|
set_fact:
|
||||||
|
selinux_config_after: "{{ selinux_config_after_raw.split('\n') }}"
|
||||||
|
|
||||||
- debug:
|
- debug:
|
||||||
var: selinux_config_after
|
var: selinux_config_after
|
||||||
|
|
@ -209,8 +227,17 @@
|
||||||
- not _state_test2.reboot_required
|
- not _state_test2.reboot_required
|
||||||
|
|
||||||
- name: TEST 2 | Get modified config file
|
- name: TEST 2 | Get modified config file
|
||||||
|
slurp:
|
||||||
|
src: /etc/sysconfig/selinux
|
||||||
|
register: selinux_config_after_base64
|
||||||
|
|
||||||
|
- name: TEST 2 | Register modified config
|
||||||
set_fact:
|
set_fact:
|
||||||
selinux_config_after: "{{ lookup('file', '/etc/sysconfig/selinux').split('\n') }}"
|
selinux_config_after_raw: "{{ selinux_config_after_base64.content | b64decode }}"
|
||||||
|
|
||||||
|
- name: TEST 2 | Split by line and register modified config
|
||||||
|
set_fact:
|
||||||
|
selinux_config_after: "{{ selinux_config_after_raw.split('\n') }}"
|
||||||
|
|
||||||
- debug:
|
- debug:
|
||||||
var: selinux_config_after
|
var: selinux_config_after
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,29 @@
|
||||||
package:
|
package:
|
||||||
name: rsync
|
name: rsync
|
||||||
when: ansible_distribution != "MacOSX"
|
when: ansible_distribution != "MacOSX"
|
||||||
- name: cleanup old files
|
- name: Clean up the working directory and files
|
||||||
shell: rm -rf {{output_dir}}/*
|
file:
|
||||||
|
path: '{{ output_dir }}'
|
||||||
|
state: absent
|
||||||
|
- name: Create the working directory
|
||||||
|
file:
|
||||||
|
path: '{{ output_dir }}'
|
||||||
|
state: directory
|
||||||
- name: create test new files
|
- name: create test new files
|
||||||
copy: dest={{output_dir}}/{{item}} mode=0644 content="hello world"
|
copy:
|
||||||
|
dest: '{{output_dir}}/{{item}}'
|
||||||
|
mode: '0644'
|
||||||
|
content: 'hello world'
|
||||||
with_items:
|
with_items:
|
||||||
- foo.txt
|
- foo.txt
|
||||||
- bar.txt
|
- bar.txt
|
||||||
|
|
||||||
- name: synchronize file to new filename
|
- name: synchronize file to new filename
|
||||||
synchronize: src={{output_dir}}/foo.txt dest={{output_dir}}/foo.result
|
synchronize:
|
||||||
|
src: '{{output_dir}}/foo.txt'
|
||||||
|
dest: '{{output_dir}}/foo.result'
|
||||||
register: sync_result
|
register: sync_result
|
||||||
|
delegate_to: '{{ inventory_hostname }}'
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- '''changed'' in sync_result'
|
- '''changed'' in sync_result'
|
||||||
|
|
@ -31,9 +44,13 @@
|
||||||
that:
|
that:
|
||||||
- stat_result.stat.exists == True
|
- stat_result.stat.exists == True
|
||||||
- stat_result.stat.checksum == '2aae6c35c94fcfb415dbe95f408b9ce91ee846ed'
|
- stat_result.stat.checksum == '2aae6c35c94fcfb415dbe95f408b9ce91ee846ed'
|
||||||
|
|
||||||
- name: test that the file is not copied a second time
|
- name: test that the file is not copied a second time
|
||||||
synchronize: src={{output_dir}}/foo.txt dest={{output_dir}}/foo.result
|
synchronize:
|
||||||
|
src='{{output_dir}}/foo.txt'
|
||||||
|
dest='{{output_dir}}/foo.result'
|
||||||
register: sync_result
|
register: sync_result
|
||||||
|
delegate_to: '{{ inventory_hostname }}'
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- sync_result.changed == False
|
- sync_result.changed == False
|
||||||
|
|
@ -44,12 +61,14 @@
|
||||||
with_items:
|
with_items:
|
||||||
- foo.result
|
- foo.result
|
||||||
- bar.result
|
- bar.result
|
||||||
|
|
||||||
- name: Synchronize using the mode=push param
|
- name: Synchronize using the mode=push param
|
||||||
synchronize:
|
synchronize:
|
||||||
src: '{{output_dir}}/foo.txt'
|
src: '{{output_dir}}/foo.txt'
|
||||||
dest: '{{output_dir}}/foo.result'
|
dest: '{{output_dir}}/foo.result'
|
||||||
mode: push
|
mode: push
|
||||||
register: sync_result
|
register: sync_result
|
||||||
|
delegate_to: '{{ inventory_hostname }}'
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- '''changed'' in sync_result'
|
- '''changed'' in sync_result'
|
||||||
|
|
@ -69,12 +88,14 @@
|
||||||
that:
|
that:
|
||||||
- stat_result.stat.exists == True
|
- stat_result.stat.exists == True
|
||||||
- stat_result.stat.checksum == '2aae6c35c94fcfb415dbe95f408b9ce91ee846ed'
|
- stat_result.stat.checksum == '2aae6c35c94fcfb415dbe95f408b9ce91ee846ed'
|
||||||
|
|
||||||
- name: test that the file is not copied a second time
|
- name: test that the file is not copied a second time
|
||||||
synchronize:
|
synchronize:
|
||||||
src: '{{output_dir}}/foo.txt'
|
src: '{{output_dir}}/foo.txt'
|
||||||
dest: '{{output_dir}}/foo.result'
|
dest: '{{output_dir}}/foo.result'
|
||||||
mode: push
|
mode: push
|
||||||
register: sync_result
|
register: sync_result
|
||||||
|
delegate_to: '{{ inventory_hostname }}'
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- sync_result.changed == False
|
- sync_result.changed == False
|
||||||
|
|
@ -85,12 +106,14 @@
|
||||||
with_items:
|
with_items:
|
||||||
- foo.result
|
- foo.result
|
||||||
- bar.result
|
- bar.result
|
||||||
|
|
||||||
- name: Synchronize using the mode=pull param
|
- name: Synchronize using the mode=pull param
|
||||||
synchronize:
|
synchronize:
|
||||||
src: '{{output_dir}}/foo.txt'
|
src: '{{output_dir}}/foo.txt'
|
||||||
dest: '{{output_dir}}/foo.result'
|
dest: '{{output_dir}}/foo.result'
|
||||||
mode: pull
|
mode: pull
|
||||||
register: sync_result
|
register: sync_result
|
||||||
|
delegate_to: '{{ inventory_hostname }}'
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- '''changed'' in sync_result'
|
- '''changed'' in sync_result'
|
||||||
|
|
@ -110,12 +133,14 @@
|
||||||
that:
|
that:
|
||||||
- stat_result.stat.exists == True
|
- stat_result.stat.exists == True
|
||||||
- stat_result.stat.checksum == '2aae6c35c94fcfb415dbe95f408b9ce91ee846ed'
|
- stat_result.stat.checksum == '2aae6c35c94fcfb415dbe95f408b9ce91ee846ed'
|
||||||
|
|
||||||
- name: test that the file is not copied a second time
|
- name: test that the file is not copied a second time
|
||||||
synchronize:
|
synchronize:
|
||||||
src: '{{output_dir}}/foo.txt'
|
src: '{{output_dir}}/foo.txt'
|
||||||
dest: '{{output_dir}}/foo.result'
|
dest: '{{output_dir}}/foo.result'
|
||||||
mode: pull
|
mode: pull
|
||||||
register: sync_result
|
register: sync_result
|
||||||
|
delegate_to: '{{ inventory_hostname }}'
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- sync_result.changed == False
|
- sync_result.changed == False
|
||||||
|
|
@ -126,12 +151,16 @@
|
||||||
with_items:
|
with_items:
|
||||||
- foo.result
|
- foo.result
|
||||||
- bar.result
|
- bar.result
|
||||||
|
|
||||||
- name: synchronize files using with_items (issue#5965)
|
- name: synchronize files using with_items (issue#5965)
|
||||||
synchronize: src={{output_dir}}/{{item}} dest={{output_dir}}/{{item}}.result
|
synchronize:
|
||||||
|
src: '{{output_dir}}/{{item}}'
|
||||||
|
dest: '{{output_dir}}/{{item}}.result'
|
||||||
with_items:
|
with_items:
|
||||||
- foo.txt
|
- foo.txt
|
||||||
- bar.txt
|
- bar.txt
|
||||||
register: sync_result
|
register: sync_result
|
||||||
|
delegate_to: '{{ inventory_hostname }}'
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- sync_result.changed
|
- sync_result.changed
|
||||||
|
|
@ -151,9 +180,14 @@
|
||||||
with_items:
|
with_items:
|
||||||
- foo.txt
|
- foo.txt
|
||||||
- bar.txt
|
- bar.txt
|
||||||
|
|
||||||
- name: synchronize files using rsync_path (issue#7182)
|
- name: synchronize files using rsync_path (issue#7182)
|
||||||
synchronize: src={{output_dir}}/foo.txt dest={{output_dir}}/foo.rsync_path rsync_path="sudo rsync"
|
synchronize:
|
||||||
|
src: '{{output_dir}}/foo.txt'
|
||||||
|
dest: '{{output_dir}}/foo.rsync_path'
|
||||||
|
rsync_path: 'sudo rsync'
|
||||||
register: sync_result
|
register: sync_result
|
||||||
|
delegate_to: '{{ inventory_hostname }}'
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- '''changed'' in sync_result'
|
- '''changed'' in sync_result'
|
||||||
|
|
@ -186,6 +220,7 @@
|
||||||
dest: '{{output_dir}}/{{item}}/foo.txt'
|
dest: '{{output_dir}}/{{item}}/foo.txt'
|
||||||
with_items:
|
with_items:
|
||||||
- directory_a
|
- directory_a
|
||||||
|
delegate_to: '{{ inventory_hostname }}'
|
||||||
- name: synchronize files using link_dest
|
- name: synchronize files using link_dest
|
||||||
synchronize:
|
synchronize:
|
||||||
src: '{{output_dir}}/directory_a/foo.txt'
|
src: '{{output_dir}}/directory_a/foo.txt'
|
||||||
|
|
@ -193,6 +228,7 @@
|
||||||
link_dest:
|
link_dest:
|
||||||
- '{{output_dir}}/directory_a'
|
- '{{output_dir}}/directory_a'
|
||||||
register: sync_result
|
register: sync_result
|
||||||
|
delegate_to: '{{ inventory_hostname }}'
|
||||||
- name: get stat information for directory_a
|
- name: get stat information for directory_a
|
||||||
stat:
|
stat:
|
||||||
path: '{{ output_dir }}/directory_a/foo.txt'
|
path: '{{ output_dir }}/directory_a/foo.txt'
|
||||||
|
|
@ -214,6 +250,8 @@
|
||||||
- '{{output_dir}}'
|
- '{{output_dir}}'
|
||||||
register: sync_result
|
register: sync_result
|
||||||
ignore_errors: true
|
ignore_errors: true
|
||||||
|
delegate_to: '{{ inventory_hostname }}'
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- sync_result is not changed
|
- sync_result is not changed
|
||||||
|
|
@ -227,3 +265,46 @@
|
||||||
- directory_a/foo.txt
|
- directory_a/foo.txt
|
||||||
- directory_a
|
- directory_a
|
||||||
- directory_b
|
- directory_b
|
||||||
|
|
||||||
|
- name: setup - test for source with working dir with spaces in path
|
||||||
|
file:
|
||||||
|
state: directory
|
||||||
|
path: '{{output_dir}}/{{item}}'
|
||||||
|
delegate_to: '{{ inventory_hostname }}'
|
||||||
|
with_items:
|
||||||
|
- 'directory a'
|
||||||
|
- 'directory b'
|
||||||
|
- name: setup - create test new files
|
||||||
|
copy:
|
||||||
|
dest: '{{output_dir}}/directory a/{{item}}'
|
||||||
|
mode: '0644'
|
||||||
|
content: 'hello world'
|
||||||
|
with_items:
|
||||||
|
- foo.txt
|
||||||
|
delegate_to: '{{ inventory_hostname }}'
|
||||||
|
- name: copy source with spaces in dir path
|
||||||
|
synchronize:
|
||||||
|
src: '{{output_dir}}/directory a/foo.txt'
|
||||||
|
dest: '{{output_dir}}/directory b/'
|
||||||
|
delegate_to: '{{ inventory_hostname }}'
|
||||||
|
register: sync_result
|
||||||
|
ignore_errors: true
|
||||||
|
- name: get stat information for directory_b
|
||||||
|
stat:
|
||||||
|
path: '{{ output_dir }}/directory b/foo.txt'
|
||||||
|
register: stat_result_b
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- '''changed'' in sync_result'
|
||||||
|
- sync_result.changed == true
|
||||||
|
- stat_result_b.stat.exists == True
|
||||||
|
- stat_result_b.stat.checksum == '2aae6c35c94fcfb415dbe95f408b9ce91ee846ed'
|
||||||
|
- name: Cleanup
|
||||||
|
file:
|
||||||
|
state: absent
|
||||||
|
path: '{{output_dir}}/{{item}}'
|
||||||
|
with_items:
|
||||||
|
- 'directory b/foo.txt'
|
||||||
|
- 'directory a/foo.txt'
|
||||||
|
- 'directory a'
|
||||||
|
- 'directory b'
|
||||||
|
|
|
||||||
|
|
@ -123,10 +123,10 @@
|
||||||
that:
|
that:
|
||||||
- sysctl_test2_change_test is not changed
|
- sysctl_test2_change_test is not changed
|
||||||
|
|
||||||
- name: Try sysctl with an invalid value
|
- name: Try sysctl with an invalid name
|
||||||
sysctl:
|
sysctl:
|
||||||
name: net.ipv4.ip_forward
|
name: test.invalid
|
||||||
value: foo
|
value: 1
|
||||||
register: sysctl_test3
|
register: sysctl_test3
|
||||||
ignore_errors: yes
|
ignore_errors: yes
|
||||||
|
|
||||||
|
|
@ -196,10 +196,10 @@
|
||||||
- sysctl_no_value is failed
|
- sysctl_no_value is failed
|
||||||
- "sysctl_no_value.msg == 'value cannot be None'"
|
- "sysctl_no_value.msg == 'value cannot be None'"
|
||||||
|
|
||||||
- name: Try sysctl with an invalid value
|
- name: Try sysctl with an invalid name
|
||||||
sysctl:
|
sysctl:
|
||||||
name: net.ipv4.ip_forward
|
name: test.invalid
|
||||||
value: foo
|
value: 1
|
||||||
sysctl_set: yes
|
sysctl_set: yes
|
||||||
register: sysctl_test4
|
register: sysctl_test4
|
||||||
ignore_errors: yes
|
ignore_errors: yes
|
||||||
|
|
|
||||||
8
tests/sanity/ignore-2.13.txt
Normal file
8
tests/sanity/ignore-2.13.txt
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
plugins/modules/synchronize.py pylint:disallowed-name
|
||||||
|
plugins/modules/synchronize.py use-argspec-type-path
|
||||||
|
plugins/modules/synchronize.py validate-modules:doc-default-does-not-match-spec
|
||||||
|
plugins/modules/synchronize.py validate-modules:nonexistent-parameter-documented
|
||||||
|
plugins/modules/synchronize.py validate-modules:parameter-type-not-in-doc
|
||||||
|
plugins/modules/synchronize.py validate-modules:undocumented-parameter
|
||||||
|
tests/utils/shippable/check_matrix.py replace-urlopen
|
||||||
|
tests/utils/shippable/timing.py shebang
|
||||||
|
|
@ -125,7 +125,7 @@ class SynchronizeTester(object):
|
||||||
metapath = os.path.join(fixturepath, 'meta.yaml')
|
metapath = os.path.join(fixturepath, 'meta.yaml')
|
||||||
with open(metapath, 'rb') as f:
|
with open(metapath, 'rb') as f:
|
||||||
fdata = f.read()
|
fdata = f.read()
|
||||||
test_meta = yaml.load(fdata)
|
test_meta = yaml.safe_load(fdata)
|
||||||
|
|
||||||
# load initial play context vars
|
# load initial play context vars
|
||||||
if '_play_context' in test_meta:
|
if '_play_context' in test_meta:
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ function retry
|
||||||
echo "@* -> ${result}"
|
echo "@* -> ${result}"
|
||||||
done
|
done
|
||||||
echo "Command '@*' failed 3 times!"
|
echo "Command '@*' failed 3 times!"
|
||||||
exit -1
|
exit 255
|
||||||
}
|
}
|
||||||
|
|
||||||
command -v pip
|
command -v pip
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue