mirror of
https://github.com/ansible-collections/ansible.posix.git
synced 2026-05-14 13:32:00 +00:00
Compare commits
99 Commits
1.3.0
...
3abd029b9f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3abd029b9f | ||
|
|
3d2681aea6 | ||
|
|
0224e4d415 | ||
|
|
cc20deaad2 | ||
|
|
5e0a6592ca | ||
|
|
acd5a2b17e | ||
|
|
e629ae2d7c | ||
|
|
abfe36c62f | ||
|
|
6c0b91a3ee | ||
|
|
f7fac90009 | ||
|
|
c4be75114b | ||
|
|
6da0cbb3d3 | ||
|
|
17fc3bcce6 | ||
|
|
d7c7d1d2c8 | ||
|
|
55bd196e82 | ||
|
|
f451f2211b | ||
|
|
18c847a8a0 | ||
|
|
ee65205607 | ||
|
|
2c9c3a0f54 | ||
|
|
c1f830f3df | ||
|
|
2d3f55caa7 | ||
|
|
ab3bf45c6c | ||
|
|
00a22a525c | ||
|
|
eebfff4eb8 | ||
|
|
2ee9cc533a | ||
|
|
6d5145e285 | ||
|
|
45519c68be | ||
|
|
33f2ef8f11 | ||
|
|
dc4da60aff | ||
|
|
c520b68276 | ||
|
|
3ab812953f | ||
|
|
0e71c0e530 | ||
|
|
04fdbffca1 | ||
|
|
def5d2bae0 | ||
|
|
aecf81a23b | ||
|
|
373250a0ce | ||
|
|
62d060a173 | ||
|
|
b5247a27d4 | ||
|
|
792714f598 | ||
|
|
b886d7691f | ||
|
|
a383c6b27c | ||
|
|
ac611b801f | ||
|
|
68e7ddb7a7 | ||
|
|
cbd915c8ea | ||
|
|
3acced944b | ||
|
|
90cdaf873d | ||
|
|
44a23e363b | ||
|
|
a45448bb26 | ||
|
|
95785bbbbd | ||
|
|
43ead73934 | ||
|
|
16436f4f55 | ||
|
|
cd04f5a092 | ||
|
|
a8fcc028c0 | ||
|
|
667ebef95c | ||
|
|
f17fda3162 | ||
|
|
35a910a698 | ||
|
|
90385b97d8 | ||
|
|
a42d7f0420 | ||
|
|
12c00aa810 | ||
|
|
deac6a412e | ||
|
|
9525e23dc7 | ||
|
|
69a46eb0e8 | ||
|
|
36efb13c23 | ||
|
|
607b7cfcb4 | ||
|
|
af2af9cff3 | ||
|
|
40a9ff36bb | ||
|
|
2768c58f90 | ||
|
|
a15e376bb9 | ||
|
|
e366b90f39 | ||
|
|
d1be5519e6 | ||
|
|
3514f9d3dc | ||
|
|
9890937bcc | ||
|
|
8fda5f8678 | ||
|
|
399f5e2f09 | ||
|
|
1ca54d181d | ||
|
|
8f58cbb41c | ||
|
|
aaa96c2011 | ||
|
|
6ca7a7c0a4 | ||
|
|
4304552677 | ||
|
|
b09750ca7f | ||
|
|
5a2b3662cb | ||
|
|
595ee76b69 | ||
|
|
96c342fd67 | ||
|
|
53d47e1763 | ||
|
|
6e2230c1b3 | ||
|
|
f0f0b0a2e2 | ||
|
|
3d57a17ed6 | ||
|
|
610717ca76 | ||
|
|
dc8f7d68df | ||
|
|
1626c3d5e6 | ||
|
|
e396e5cb43 | ||
|
|
4a67de7b08 | ||
|
|
7f16f56c5b | ||
|
|
391d113a95 | ||
|
|
01bccb08a9 | ||
|
|
249e64a64d | ||
|
|
12941f6d9a | ||
|
|
617302ba94 | ||
|
|
fee81b19a8 |
@@ -36,7 +36,7 @@ variables:
|
|||||||
resources:
|
resources:
|
||||||
containers:
|
containers:
|
||||||
- container: default
|
- container: default
|
||||||
image: quay.io/ansible/azure-pipelines-test-container:1.9.0
|
image: quay.io/ansible/azure-pipelines-test-container:3.0.0
|
||||||
|
|
||||||
pool: Standard
|
pool: Standard
|
||||||
|
|
||||||
@@ -50,13 +50,49 @@ 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 36
|
||||||
|
test: fedora36
|
||||||
|
- name: openSUSE 15 py3
|
||||||
|
test: opensuse15
|
||||||
|
- name: Ubuntu 20.04
|
||||||
|
test: ubuntu2004
|
||||||
|
- name: Ubuntu 22.04
|
||||||
|
test: ubuntu2204
|
||||||
|
- stage: Docker_2_13
|
||||||
|
displayName: Docker 2.13
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
testFormat: 2.13/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 +117,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 +141,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 +165,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 +186,42 @@ 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.6
|
||||||
|
test: rhel/8.6
|
||||||
|
- name: RHEL 9.0
|
||||||
|
test: rhel/9.0
|
||||||
|
- name: FreeBSD 13.1
|
||||||
|
test: freebsd/13.1
|
||||||
|
- stage: Remote_2_13
|
||||||
|
displayName: Remote 2.13
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
testFormat: 2.13/{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
|
||||||
@@ -181,8 +247,6 @@ stages:
|
|||||||
test: rhel/7.9
|
test: rhel/7.9
|
||||||
- name: RHEL 8.3
|
- name: RHEL 8.3
|
||||||
test: rhel/8.3
|
test: rhel/8.3
|
||||||
- name: FreeBSD 11.4
|
|
||||||
test: freebsd/11.4
|
|
||||||
- name: FreeBSD 12.2
|
- name: FreeBSD 12.2
|
||||||
test: freebsd/12.2
|
test: freebsd/12.2
|
||||||
- stage: Remote_2_10
|
- stage: Remote_2_10
|
||||||
@@ -195,15 +259,10 @@ 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
|
|
||||||
test: freebsd/11.1
|
|
||||||
- name: FreeBSD 12.1
|
|
||||||
test: freebsd/12.1
|
|
||||||
|
|
||||||
- stage: Remote_2_9
|
- stage: Remote_2_9
|
||||||
displayName: Remote 2.9
|
displayName: Remote 2.9
|
||||||
dependsOn: []
|
dependsOn: []
|
||||||
@@ -214,14 +273,11 @@ 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
|
|
||||||
test: freebsd/11.1
|
|
||||||
- name: FreeBSD 12.0
|
|
||||||
test: freebsd/12.0
|
|
||||||
## Finally
|
## Finally
|
||||||
|
|
||||||
- stage: Summary
|
- stage: Summary
|
||||||
@@ -230,9 +286,13 @@ 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_2_13
|
||||||
|
- Docker_2_13
|
||||||
- Remote_devel
|
- Remote_devel
|
||||||
- Docker_devel
|
- Docker_devel
|
||||||
jobs:
|
jobs:
|
||||||
|
|||||||
@@ -5,6 +5,34 @@ ansible.posix Release Notes
|
|||||||
.. contents:: Topics
|
.. contents:: Topics
|
||||||
|
|
||||||
|
|
||||||
|
v1.4.0
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This is the minor release of the ``ansible.posix`` collection.
|
||||||
|
This changelog contains all changes to the modules in this collection that
|
||||||
|
have been added after the release of ``ansible.posix`` 1.3.0.
|
||||||
|
|
||||||
|
Minor Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- firewalld - Show warning message that variable type of ``masquerade`` and ``icmp_block_inversion`` will be changed from ``str`` to ``boolean`` in the future release (https://github.com/ansible-collections/ansible.posix/pull/254).
|
||||||
|
- selinux - optionally update kernel boot params when disabling/re-enabling SELinux (https://github.com/ansible-collections/ansible.posix/pull/142).
|
||||||
|
|
||||||
|
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)
|
||||||
|
- Include ``PSF-license.txt`` file for ``plugins/module_utils/_version.py``.
|
||||||
|
- 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).
|
||||||
|
- firewalld - Correct usage of queryForwardPort (https://github.com/ansible-collections/ansible.posix/issues/247).
|
||||||
|
- firewalld - Refine the handling of exclusive options (https://github.com/ansible-collections/ansible.posix/issues/255).
|
||||||
|
- mount - add a newline at the end of line in ``fstab`` (https://github.com/ansible-collections/ansible.posix/issues/210).
|
||||||
|
- profile_tasks - Correctly calculate task execution time with serial execution (https://github.com/ansible-collections/ansible.posix/issues/83).
|
||||||
|
- seboolean - add ``python3-libsemanage`` package dependency for RHEL8+ systems.
|
||||||
|
|
||||||
v1.3.0
|
v1.3.0
|
||||||
======
|
======
|
||||||
|
|
||||||
|
|||||||
48
PSF-license.txt
Normal file
48
PSF-license.txt
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
1. This LICENSE AGREEMENT is between the Python Software Foundation
|
||||||
|
("PSF"), and the Individual or Organization ("Licensee") accessing and
|
||||||
|
otherwise using this software ("Python") in source or binary form and
|
||||||
|
its associated documentation.
|
||||||
|
|
||||||
|
2. Subject to the terms and conditions of this License Agreement, PSF hereby
|
||||||
|
grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
|
||||||
|
analyze, test, perform and/or display publicly, prepare derivative works,
|
||||||
|
distribute, and otherwise use Python alone or in any derivative version,
|
||||||
|
provided, however, that PSF's License Agreement and PSF's notice of copyright,
|
||||||
|
i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||||
|
2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Python Software Foundation;
|
||||||
|
All Rights Reserved" are retained in Python alone or in any derivative version
|
||||||
|
prepared by Licensee.
|
||||||
|
|
||||||
|
3. In the event Licensee prepares a derivative work that is based on
|
||||||
|
or incorporates Python or any part thereof, and wants to make
|
||||||
|
the derivative work available to others as provided herein, then
|
||||||
|
Licensee hereby agrees to include in any such work a brief summary of
|
||||||
|
the changes made to Python.
|
||||||
|
|
||||||
|
4. PSF is making Python available to Licensee on an "AS IS"
|
||||||
|
basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
||||||
|
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
|
||||||
|
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
||||||
|
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
|
||||||
|
INFRINGE ANY THIRD PARTY RIGHTS.
|
||||||
|
|
||||||
|
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
|
||||||
|
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
|
||||||
|
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
|
||||||
|
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
|
||||||
|
|
||||||
|
6. This License Agreement will automatically terminate upon a material
|
||||||
|
breach of its terms and conditions.
|
||||||
|
|
||||||
|
7. Nothing in this License Agreement shall be deemed to create any
|
||||||
|
relationship of agency, partnership, or joint venture between PSF and
|
||||||
|
Licensee. This License Agreement does not grant permission to use PSF
|
||||||
|
trademarks or trade name in a trademark sense to endorse or promote
|
||||||
|
products or services of Licensee, or any third party.
|
||||||
|
|
||||||
|
8. By copying, installing or otherwise using Python, Licensee
|
||||||
|
agrees to be bound by the terms and conditions of this License
|
||||||
|
Agreement.
|
||||||
12
README.md
12
README.md
@@ -13,6 +13,8 @@ An Ansible Collection of modules and plugins that target POSIX UNIX/Linux and de
|
|||||||
|
|
||||||
This collection has been tested against following Ansible versions: **>=2.9**.
|
This collection has been tested against following Ansible versions: **>=2.9**.
|
||||||
|
|
||||||
|
For collections that support Ansible 2.9, please ensure you update your `network_os` to use the
|
||||||
|
fully qualified collection name (for example, `cisco.ios.ios`).
|
||||||
Plugins and modules within a collection may be tested with only specific Ansible versions.
|
Plugins and modules within a collection may be tested with only specific Ansible versions.
|
||||||
A collection may contain metadata that identifies these versions.
|
A collection may contain metadata that identifies these versions.
|
||||||
PEP440 is the schema used to describe the versions of Ansible.
|
PEP440 is the schema used to describe the versions of Ansible.
|
||||||
@@ -86,10 +88,12 @@ 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.14 (devel)
|
||||||
* ansible-core 2.11 (stable)
|
- ansible-core 2.13 (stable)
|
||||||
* ansible-base 2.10 (stable)
|
- ansible-core 2.12 (stable)
|
||||||
* ansible 2.9 (stable)
|
- ansible-core 2.11 (stable)
|
||||||
|
- ansible-base 2.10 (stable)
|
||||||
|
- ansible 2.9 (stable)
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
|
|
||||||
|
|||||||
4
bindep.txt
Normal file
4
bindep.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# This is a cross-platform list tracking distribution packages needed by tests;
|
||||||
|
# see https://docs.openstack.org/infra/bindep/ for additional information.
|
||||||
|
|
||||||
|
rsync [platform:rhel-8 platform:rhel-9]
|
||||||
@@ -210,3 +210,53 @@ releases:
|
|||||||
- synchronize.yml
|
- synchronize.yml
|
||||||
- test_matrix.yml
|
- test_matrix.yml
|
||||||
release_date: '2021-08-11'
|
release_date: '2021-08-11'
|
||||||
|
1.4.0:
|
||||||
|
changes:
|
||||||
|
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)
|
||||||
|
- Include ``PSF-license.txt`` file for ``plugins/module_utils/_version.py``.
|
||||||
|
- 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).
|
||||||
|
- firewalld - Correct usage of queryForwardPort (https://github.com/ansible-collections/ansible.posix/issues/247).
|
||||||
|
- firewalld - Refine the handling of exclusive options (https://github.com/ansible-collections/ansible.posix/issues/255).
|
||||||
|
- mount - add a newline at the end of line in ``fstab`` (https://github.com/ansible-collections/ansible.posix/issues/210).
|
||||||
|
- profile_tasks - Correctly calculate task execution time with serial execution
|
||||||
|
(https://github.com/ansible-collections/ansible.posix/issues/83).
|
||||||
|
- seboolean - add ``python3-libsemanage`` package dependency for RHEL8+ systems.
|
||||||
|
minor_changes:
|
||||||
|
- firewalld - Show warning message that variable type of ``masquerade`` and
|
||||||
|
``icmp_block_inversion`` will be changed from ``str`` to ``boolean`` in the
|
||||||
|
future release (https://github.com/ansible-collections/ansible.posix/pull/254).
|
||||||
|
- selinux - optionally update kernel boot params when disabling/re-enabling
|
||||||
|
SELinux (https://github.com/ansible-collections/ansible.posix/pull/142).
|
||||||
|
release_summary: 'This is the minor release of the ``ansible.posix`` collection.
|
||||||
|
|
||||||
|
This changelog contains all changes to the modules in this collection that
|
||||||
|
|
||||||
|
have been added after the release of ``ansible.posix`` 1.3.0.'
|
||||||
|
fragments:
|
||||||
|
- 1.4.0.yml
|
||||||
|
- 211_fstab_append_newline.yml
|
||||||
|
- 247_firewalld.yml
|
||||||
|
- 254_variable_warnings.yml
|
||||||
|
- 255_authorized_key_url.yml
|
||||||
|
- 263_profile_tasks_with_serial.yml
|
||||||
|
- 272-copy_ignore_txt.yml
|
||||||
|
- 277_fix_integration_test_on_devel.yml
|
||||||
|
- 282_fix_unit_test_for_synchronize.yml
|
||||||
|
- 287_firewalld_requirements.yml
|
||||||
|
- 288_mounts_options.yml
|
||||||
|
- 297_firewalld_exclusive_options_handling.yml
|
||||||
|
- 299_seboolean_python3.yml
|
||||||
|
- 302_shippable_exit_code.yml
|
||||||
|
- 304_pep632.yml
|
||||||
|
- 346_copy_ignore_txt_for_devel.yml
|
||||||
|
- 347_add_branch_213.yml
|
||||||
|
- 349_follow_new_guidelines.yml
|
||||||
|
- 353_ci_fix_unittest_for_synchronize.yml
|
||||||
|
- disable_selinux_via_kernel_cmdline.yml
|
||||||
|
- psf-license.yml
|
||||||
|
- sanity_fixes.yml
|
||||||
|
- shell_escape_full_path_for_rsync.yml
|
||||||
|
release_date: '2022-05-23'
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
trivial:
|
||||||
|
- Update version number in galaxy.yml to 1.5.0.
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
trivial:
|
||||||
|
- CI - Refactor AZP to address new test infrastructure (https://github.com/ansible-collections/news-for-maintainers/issues/17).
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
bugfixes:
|
||||||
|
- firewall - Fixed to output a more complete missing library message.
|
||||||
3
changelogs/fragments/375_update_azp_container.yml
Normal file
3
changelogs/fragments/375_update_azp_container.yml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
trivial:
|
||||||
|
- CI - AZP test container to 3.0.0 (https://github.com/ansible-collections/news-for-maintainers/issues/18).
|
||||||
3
changelogs/fragments/380_update_usage_profile_tasks.yml
Normal file
3
changelogs/fragments/380_update_usage_profile_tasks.yml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
bugfixes:
|
||||||
|
- Removed contentious terminology to match reference documentation in profile_tasks.
|
||||||
3
changelogs/fragments/386_follow_ci_testing_rules.yml
Normal file
3
changelogs/fragments/386_follow_ci_testing_rules.yml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
trivial:
|
||||||
|
- CI - following the new CI testing rule ansible-test-sanity-docker-devel.
|
||||||
1
codecov.yml
Normal file
1
codecov.yml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
comment: false
|
||||||
@@ -240,6 +240,12 @@ Examples
|
|||||||
state: present
|
state: present
|
||||||
key: https://github.com/charlie.keys
|
key: https://github.com/charlie.keys
|
||||||
|
|
||||||
|
- name: Set authorized keys taken from url using lookup
|
||||||
|
ansible.posix.authorized_key:
|
||||||
|
user: charlie
|
||||||
|
state: present
|
||||||
|
key: "{{ lookup('url', 'https://github.com/charlie.keys', split_lines=False) }}"
|
||||||
|
|
||||||
- name: Set authorized key in alternate location
|
- name: Set authorized key in alternate location
|
||||||
ansible.posix.authorized_key:
|
ansible.posix.authorized_key:
|
||||||
user: charlie
|
user: charlie
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ Requirements
|
|||||||
The below requirements are needed on the host that executes this module.
|
The below requirements are needed on the host that executes this module.
|
||||||
|
|
||||||
- firewalld >= 0.2.11
|
- firewalld >= 0.2.11
|
||||||
|
- python-firewall >= 0.2.11
|
||||||
|
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
@@ -401,6 +402,7 @@ Notes
|
|||||||
- Requires the python2 bindings of firewalld, which may not be installed by default.
|
- Requires the python2 bindings of firewalld, which may not be installed by default.
|
||||||
- For distributions where the python2 firewalld bindings are unavailable (e.g Fedora 28 and later) you will have to set the ansible_python_interpreter for these hosts to the python3 interpreter path and install the python3 bindings.
|
- For distributions where the python2 firewalld bindings are unavailable (e.g Fedora 28 and later) you will have to set the ansible_python_interpreter for these hosts to the python3 interpreter path and install the python3 bindings.
|
||||||
- Zone transactions (creating, deleting) can be performed by using only the zone and state parameters "present" or "absent". Note that zone transactions must explicitly be permanent. This is a limitation in firewalld. This also means that you will have to reload firewalld after adding a zone that you wish to perform immediate actions on. 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 creation returns with a changed state and before you perform any other immediate, non-permanent actions on that zone.
|
- Zone transactions (creating, deleting) can be performed by using only the zone and state parameters "present" or "absent". Note that zone transactions must explicitly be permanent. This is a limitation in firewalld. This also means that you will have to reload firewalld after adding a zone that you wish to perform immediate actions on. 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 creation returns with a changed state and before you perform any other immediate, non-permanent actions on that zone.
|
||||||
|
- This module needs ``python-firewall`` or ``python3-firewall`` on managed nodes. It is usually provided as a subset with ``firewalld`` from the OS distributor for the OS default Python interpreter.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ Parameters
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<b>Default:</b><br/><div style="color: blue">0</div>
|
<b>Default:</b><br/><div style="color: blue">"0"</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Dump (see fstab(5)).</div>
|
<div>Dump (see fstab(5)).</div>
|
||||||
@@ -153,7 +153,7 @@ Parameters
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<b>Default:</b><br/><div style="color: blue">0</div>
|
<b>Default:</b><br/><div style="color: blue">"0"</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Passno (see fstab(5)).</div>
|
<div>Passno (see fstab(5)).</div>
|
||||||
@@ -295,7 +295,7 @@ Examples
|
|||||||
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
|
||||||
|
|
||||||
@@ -303,7 +303,7 @@ Examples
|
|||||||
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
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ The below requirements are needed on the host that executes this module.
|
|||||||
|
|
||||||
- libselinux-python
|
- libselinux-python
|
||||||
- libsemanage-python
|
- libsemanage-python
|
||||||
|
- python3-libsemanage
|
||||||
|
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
|
|||||||
@@ -94,6 +94,27 @@ Parameters
|
|||||||
<div>The SELinux mode.</div>
|
<div>The SELinux mode.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>update_kernel_param</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 1.4.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>If set to <em>true</em>, will update also the kernel boot parameters when disabling/enabling SELinux.</div>
|
||||||
|
<div>The <code>grubby</code> tool must be present on the target system for this to work.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace: ansible
|
namespace: ansible
|
||||||
name: posix
|
name: posix
|
||||||
version: 1.3.0
|
version: 1.5.0
|
||||||
readme: README.md
|
readme: README.md
|
||||||
authors:
|
authors:
|
||||||
- Ansible (github.com/ansible)
|
- Ansible (github.com/ansible)
|
||||||
|
|||||||
@@ -1,2 +1,8 @@
|
|||||||
---
|
---
|
||||||
requires_ansible: '>=2.9'
|
requires_ansible: '>=2.9'
|
||||||
|
plugin_routing:
|
||||||
|
callback:
|
||||||
|
skippy:
|
||||||
|
deprecation:
|
||||||
|
removal_date: '2022-06-01'
|
||||||
|
warning_text: See the plugin documentation for more details
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ ANSIBLE_METADATA = {'metadata_version': '1.1',
|
|||||||
'supported_by': 'community'}
|
'supported_by': 'community'}
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = '''
|
||||||
callback: cgroup_perf_recap
|
name: cgroup_perf_recap
|
||||||
callback_type: aggregate
|
type: aggregate
|
||||||
requirements:
|
requirements:
|
||||||
- whitelist in configuration
|
- whitelist in configuration
|
||||||
- cgroups
|
- cgroups
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from __future__ import (absolute_import, division, print_function)
|
|||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = '''
|
||||||
callback: debug
|
name: debug
|
||||||
type: stdout
|
type: stdout
|
||||||
short_description: formatted stdout/stderr display
|
short_description: formatted stdout/stderr display
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from __future__ import (absolute_import, division, print_function)
|
|||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = '''
|
||||||
callback: json
|
name: json
|
||||||
short_description: Ansible screen output as JSON
|
short_description: Ansible screen output as JSON
|
||||||
description:
|
description:
|
||||||
- This callback converts all events into JSON output to stdout
|
- This callback converts all events into JSON output to stdout
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from __future__ import (absolute_import, division, print_function)
|
|||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = '''
|
||||||
callback: profile_roles
|
name: profile_roles
|
||||||
type: aggregate
|
type: aggregate
|
||||||
short_description: adds timing information to roles
|
short_description: adds timing information to roles
|
||||||
description:
|
description:
|
||||||
@@ -102,8 +102,8 @@ class CallbackModule(CallbackBase):
|
|||||||
self._display.display(tasktime())
|
self._display.display(tasktime())
|
||||||
|
|
||||||
def playbook_on_stats(self, stats):
|
def playbook_on_stats(self, stats):
|
||||||
self._display.display(tasktime())
|
# Align summary report header with other callback plugin summary
|
||||||
self._display.display(filled("", fchar="="))
|
self._display.banner("ROLE RECAP")
|
||||||
|
|
||||||
timestamp(self)
|
timestamp(self)
|
||||||
total_time = sum(self.totals.values())
|
total_time = sum(self.totals.values())
|
||||||
@@ -116,3 +116,4 @@ class CallbackModule(CallbackBase):
|
|||||||
msg_total = u"{0:-<70}{1:->9}".format(u'total ', u' {0:.02f}s'.format(total_time))
|
msg_total = u"{0:-<70}{1:->9}".format(u'total ', u' {0:.02f}s'.format(total_time))
|
||||||
self._display.display(filled("", fchar="~"))
|
self._display.display(filled("", fchar="~"))
|
||||||
self._display.display(msg_total)
|
self._display.display(msg_total)
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ from __future__ import (absolute_import, division, print_function)
|
|||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = '''
|
||||||
callback: profile_tasks
|
name: profile_tasks
|
||||||
type: aggregate
|
type: aggregate
|
||||||
short_description: adds time information to tasks
|
short_description: adds time information to tasks
|
||||||
description:
|
description:
|
||||||
@@ -21,7 +21,7 @@ DOCUMENTATION = '''
|
|||||||
- It also lists the top/bottom time consuming tasks in the summary (configurable)
|
- It also lists the top/bottom time consuming tasks in the summary (configurable)
|
||||||
- Before 2.4 only the environment variables were available for configuration.
|
- Before 2.4 only the environment variables were available for configuration.
|
||||||
requirements:
|
requirements:
|
||||||
- whitelisting in configuration - see examples section below for details.
|
- enable in configuration - see examples section below for details.
|
||||||
options:
|
options:
|
||||||
output_limit:
|
output_limit:
|
||||||
description: Number of tasks to display in the summary
|
description: Number of tasks to display in the summary
|
||||||
@@ -46,7 +46,7 @@ EXAMPLES = '''
|
|||||||
example: >
|
example: >
|
||||||
To enable, add this to your ansible.cfg file in the defaults block
|
To enable, add this to your ansible.cfg file in the defaults block
|
||||||
[defaults]
|
[defaults]
|
||||||
callback_whitelist = ansible.posix.profile_tasks
|
callbacks_enabled=ansible.posix.profile_tasks
|
||||||
sample output: >
|
sample output: >
|
||||||
#
|
#
|
||||||
# TASK: [ensure messaging security group exists] ********************************
|
# TASK: [ensure messaging security group exists] ********************************
|
||||||
@@ -92,7 +92,8 @@ def filled(msg, fchar="*"):
|
|||||||
|
|
||||||
def timestamp(self):
|
def timestamp(self):
|
||||||
if self.current is not None:
|
if self.current is not None:
|
||||||
self.stats[self.current]['time'] = time.time() - self.stats[self.current]['time']
|
elapsed = time.time() - self.stats[self.current]['started']
|
||||||
|
self.stats[self.current]['elapsed'] += elapsed
|
||||||
|
|
||||||
|
|
||||||
def tasktime():
|
def tasktime():
|
||||||
@@ -151,8 +152,15 @@ class CallbackModule(CallbackBase):
|
|||||||
timestamp(self)
|
timestamp(self)
|
||||||
|
|
||||||
# Record the start time of the current task
|
# Record the start time of the current task
|
||||||
|
# stats[TASK_UUID]:
|
||||||
|
# started: Current task start time. This value will be updated each time a task
|
||||||
|
# with the same UUID is executed when `serial` is specified in a playbook.
|
||||||
|
# elapsed: Elapsed time since the first serialized task was started
|
||||||
self.current = task._uuid
|
self.current = task._uuid
|
||||||
self.stats[self.current] = {'time': time.time(), 'name': task.get_name()}
|
if self.current not in self.stats:
|
||||||
|
self.stats[self.current] = {'started': time.time(), 'elapsed': 0.0, 'name': task.get_name()}
|
||||||
|
else:
|
||||||
|
self.stats[self.current]['started'] = time.time()
|
||||||
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()
|
||||||
|
|
||||||
@@ -166,8 +174,8 @@ class CallbackModule(CallbackBase):
|
|||||||
self._display.display(tasktime())
|
self._display.display(tasktime())
|
||||||
|
|
||||||
def playbook_on_stats(self, stats):
|
def playbook_on_stats(self, stats):
|
||||||
self._display.display(tasktime())
|
# Align summary report header with other callback plugin summary
|
||||||
self._display.display(filled("", fchar="="))
|
self._display.banner("TASKS RECAP")
|
||||||
|
|
||||||
timestamp(self)
|
timestamp(self)
|
||||||
self.current = None
|
self.current = None
|
||||||
@@ -178,7 +186,7 @@ class CallbackModule(CallbackBase):
|
|||||||
if self.sort_order is not None:
|
if self.sort_order is not None:
|
||||||
results = sorted(
|
results = sorted(
|
||||||
self.stats.items(),
|
self.stats.items(),
|
||||||
key=lambda x: x[1]['time'],
|
key=lambda x: x[1]['elapsed'],
|
||||||
reverse=self.sort_order,
|
reverse=self.sort_order,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -187,7 +195,8 @@ class CallbackModule(CallbackBase):
|
|||||||
|
|
||||||
# Print the timings
|
# Print the timings
|
||||||
for uuid, result in results:
|
for uuid, result in results:
|
||||||
msg = u"{0:-<{2}}{1:->9}".format(result['name'] + u' ', u' {0:.02f}s'.format(result['time']), self._display.columns - 9)
|
msg = u"{0:-<{2}}{1:->9}".format(result['name'] + u' ', u' {0:.02f}s'.format(result['elapsed']), self._display.columns - 9)
|
||||||
if 'path' in result:
|
if 'path' in result:
|
||||||
msg += u"\n{0:-<{1}}".format(result['path'] + u' ', self._display.columns)
|
msg += u"\n{0:-<{1}}".format(result['path'] + u' ', self._display.columns)
|
||||||
self._display.display(msg)
|
self._display.display(msg)
|
||||||
|
|
||||||
@@ -7,14 +7,14 @@ from __future__ import (absolute_import, division, print_function)
|
|||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = '''
|
||||||
callback: skippy
|
name: skippy
|
||||||
callback_type: stdout
|
type: stdout
|
||||||
requirements:
|
requirements:
|
||||||
- set as main display callback
|
- set as main display callback
|
||||||
short_description: Ansible screen output that ignores skipped status
|
short_description: Ansible screen output that ignores skipped status
|
||||||
deprecated:
|
deprecated:
|
||||||
why: The 'default' callback plugin now supports this functionality
|
why: The 'default' callback plugin now supports this functionality
|
||||||
removed_at_date: 2022-06-01
|
removed_at_date: '2022-06-01'
|
||||||
alternative: "'default' callback plugin with 'display_skipped_hosts = no' option"
|
alternative: "'default' callback plugin with 'display_skipped_hosts = no' option"
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
- default_callback
|
- default_callback
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ from __future__ import (absolute_import, division, print_function)
|
|||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = '''
|
||||||
callback: timer
|
name: timer
|
||||||
callback_type: aggregate
|
type: aggregate
|
||||||
requirements:
|
requirements:
|
||||||
- whitelist in configuration
|
- whitelist in configuration
|
||||||
short_description: Adds time to play stats
|
short_description: Adds time to play stats
|
||||||
@@ -46,4 +46,6 @@ class CallbackModule(CallbackBase):
|
|||||||
def v2_playbook_on_stats(self, stats):
|
def v2_playbook_on_stats(self, stats):
|
||||||
end_time = datetime.utcnow()
|
end_time = datetime.utcnow()
|
||||||
runtime = end_time - self.start_time
|
runtime = end_time - self.start_time
|
||||||
self._display.display("Playbook run took %s days, %s hours, %s minutes, %s seconds" % (self.days_hours_minutes_seconds(runtime)))
|
# Align summary report header with other callback plugin summary
|
||||||
|
self._display.banner("PLAYBOOK RECAP")
|
||||||
|
self._display.display("Playbook run took %s days, %s hours, %s minutes, %s seconds\n\r" % (self.days_hours_minutes_seconds(runtime)))
|
||||||
|
|||||||
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 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,11 @@
|
|||||||
# 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
|
||||||
|
from ansible.module_utils.basic import missing_required_lib
|
||||||
|
|
||||||
__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
|
||||||
@@ -315,6 +315,5 @@ class FirewallTransaction(object):
|
|||||||
|
|
||||||
if import_failure:
|
if import_failure:
|
||||||
module.fail_json(
|
module.fail_json(
|
||||||
msg='Python Module not found: firewalld and its python module are required for this module, \
|
msg=missing_required_lib('firewall') + '. Version 0.2.11 or newer required (0.3.9 or newer for offline operations)'
|
||||||
version 0.2.11 or newer required (0.3.9 or newer for offline operations)'
|
|
||||||
)
|
)
|
||||||
|
|||||||
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
|
||||||
@@ -94,6 +94,12 @@ EXAMPLES = r'''
|
|||||||
state: present
|
state: present
|
||||||
key: https://github.com/charlie.keys
|
key: https://github.com/charlie.keys
|
||||||
|
|
||||||
|
- name: Set authorized keys taken from url using lookup
|
||||||
|
ansible.posix.authorized_key:
|
||||||
|
user: charlie
|
||||||
|
state: present
|
||||||
|
key: "{{ lookup('url', 'https://github.com/charlie.keys', split_lines=False) }}"
|
||||||
|
|
||||||
- name: Set authorized key in alternate location
|
- name: Set authorized key in alternate location
|
||||||
ansible.posix.authorized_key:
|
ansible.posix.authorized_key:
|
||||||
user: charlie
|
user: charlie
|
||||||
@@ -341,6 +347,8 @@ def keyfile(module, user, write=False, path=None, manage_dir=True, follow=False)
|
|||||||
basedir = os.path.dirname(keysfile)
|
basedir = os.path.dirname(keysfile)
|
||||||
if not os.path.exists(basedir):
|
if not os.path.exists(basedir):
|
||||||
os.makedirs(basedir)
|
os.makedirs(basedir)
|
||||||
|
|
||||||
|
f = None
|
||||||
try:
|
try:
|
||||||
f = open(keysfile, "w") # touches file so we can set ownership and perms
|
f = open(keysfile, "w") # touches file so we can set ownership and perms
|
||||||
finally:
|
finally:
|
||||||
|
|||||||
@@ -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)
|
||||||
'''
|
'''
|
||||||
@@ -213,6 +216,7 @@ EXAMPLES = r'''
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
from ansible.module_utils.parsing.convert_bool import boolean
|
||||||
from ansible_collections.ansible.posix.plugins.module_utils.firewalld import FirewallTransaction, fw_offline
|
from ansible_collections.ansible.posix.plugins.module_utils.firewalld import FirewallTransaction, fw_offline
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -706,7 +710,7 @@ class ForwardPortTransaction(FirewallTransaction):
|
|||||||
if self.fw_offline:
|
if self.fw_offline:
|
||||||
dummy, fw_settings = self.get_fw_zone_settings()
|
dummy, fw_settings = self.get_fw_zone_settings()
|
||||||
return fw_settings.queryForwardPort(port=port, protocol=proto, to_port=toport, to_addr=toaddr)
|
return fw_settings.queryForwardPort(port=port, protocol=proto, to_port=toport, to_addr=toaddr)
|
||||||
return self.fw.queryForwardPort(port=port, protocol=proto, to_port=toport, to_addr=toaddr)
|
return self.fw.queryForwardPort(zone=self.zone, port=port, protocol=proto, toport=toport, toaddr=toaddr)
|
||||||
|
|
||||||
def get_enabled_permanent(self, port, proto, toport, toaddr, timeout):
|
def get_enabled_permanent(self, port, proto, toport, toaddr, timeout):
|
||||||
dummy, fw_settings = self.get_fw_zone_settings()
|
dummy, fw_settings = self.get_fw_zone_settings()
|
||||||
@@ -756,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']
|
||||||
@@ -812,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'
|
||||||
)
|
)
|
||||||
@@ -875,6 +861,14 @@ def main():
|
|||||||
if changed is True:
|
if changed is True:
|
||||||
msgs.append("Changed icmp-block-inversion %s to %s" % (icmp_block_inversion, desired_state))
|
msgs.append("Changed icmp-block-inversion %s to %s" % (icmp_block_inversion, desired_state))
|
||||||
|
|
||||||
|
# Type of icmp_block_inversion will be changed to boolean in a future release.
|
||||||
|
try:
|
||||||
|
boolean(icmp_block_inversion, True)
|
||||||
|
except TypeError:
|
||||||
|
module.warn('The value of the icmp_block_inversion option is "%s". '
|
||||||
|
'The type of the option will be changed from string to boolean in a future release. '
|
||||||
|
'To avoid unexpected behavior, please change the value to boolean.' % icmp_block_inversion)
|
||||||
|
|
||||||
if service is not None:
|
if service is not None:
|
||||||
|
|
||||||
transaction = ServiceTransaction(
|
transaction = ServiceTransaction(
|
||||||
@@ -992,6 +986,14 @@ def main():
|
|||||||
changed, transaction_msgs = transaction.run()
|
changed, transaction_msgs = transaction.run()
|
||||||
msgs = msgs + transaction_msgs
|
msgs = msgs + transaction_msgs
|
||||||
|
|
||||||
|
# Type of masquerade will be changed to boolean in a future release.
|
||||||
|
try:
|
||||||
|
boolean(masquerade, True)
|
||||||
|
except TypeError:
|
||||||
|
module.warn('The value of the masquerade option is "%s". '
|
||||||
|
'The type of the option will be changed from string to boolean in a future release. '
|
||||||
|
'To avoid unexpected behavior, please change the value to boolean.' % masquerade)
|
||||||
|
|
||||||
if target is not None:
|
if target is not None:
|
||||||
|
|
||||||
transaction = ZoneTargetTransaction(
|
transaction = ZoneTargetTransaction(
|
||||||
@@ -1007,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:
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ options:
|
|||||||
with subsequent runs.
|
with subsequent runs.
|
||||||
- Has no effect on Solaris systems.
|
- Has no effect on Solaris systems.
|
||||||
type: str
|
type: str
|
||||||
default: 0
|
default: '0'
|
||||||
passno:
|
passno:
|
||||||
description:
|
description:
|
||||||
- Passno (see fstab(5)).
|
- Passno (see fstab(5)).
|
||||||
@@ -59,7 +59,7 @@ options:
|
|||||||
with subsequent runs.
|
with subsequent runs.
|
||||||
- Deprecated on Solaris systems.
|
- Deprecated on Solaris systems.
|
||||||
type: str
|
type: str
|
||||||
default: 0
|
default: '0'
|
||||||
state:
|
state:
|
||||||
description:
|
description:
|
||||||
- If C(mounted), the device will be actively mounted and appropriately
|
- If C(mounted), the device will be actively mounted and appropriately
|
||||||
@@ -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
|
||||||
@@ -226,7 +226,7 @@ def _escape_fstab(v):
|
|||||||
if isinstance(v, int):
|
if isinstance(v, int):
|
||||||
return v
|
return v
|
||||||
else:
|
else:
|
||||||
return(
|
return (
|
||||||
v.
|
v.
|
||||||
replace('\\', '\\134').
|
replace('\\', '\\134').
|
||||||
replace(' ', '\\040').
|
replace(' ', '\\040').
|
||||||
@@ -254,6 +254,10 @@ def _set_mount_save_old(module, args):
|
|||||||
'%(src)s - %(name)s %(fstype)s %(passno)s %(boot)s %(opts)s\n')
|
'%(src)s - %(name)s %(fstype)s %(passno)s %(boot)s %(opts)s\n')
|
||||||
|
|
||||||
for line in open(args['fstab'], 'r').readlines():
|
for line in open(args['fstab'], 'r').readlines():
|
||||||
|
# Append newline if the line in fstab does not finished with newline.
|
||||||
|
if not line.endswith('\n'):
|
||||||
|
line += '\n'
|
||||||
|
|
||||||
old_lines.append(line)
|
old_lines.append(line)
|
||||||
|
|
||||||
if not line.strip():
|
if not line.strip():
|
||||||
@@ -663,12 +667,12 @@ def main():
|
|||||||
module = AnsibleModule(
|
module = AnsibleModule(
|
||||||
argument_spec=dict(
|
argument_spec=dict(
|
||||||
boot=dict(type='bool', default=True),
|
boot=dict(type='bool', default=True),
|
||||||
dump=dict(type='str'),
|
dump=dict(type='str', default='0'),
|
||||||
fstab=dict(type='str'),
|
fstab=dict(type='str'),
|
||||||
fstype=dict(type='str'),
|
fstype=dict(type='str'),
|
||||||
path=dict(type='path', required=True, aliases=['name']),
|
path=dict(type='path', required=True, aliases=['name']),
|
||||||
opts=dict(type='str'),
|
opts=dict(type='str'),
|
||||||
passno=dict(type='str', no_log=False),
|
passno=dict(type='str', no_log=False, default='0'),
|
||||||
src=dict(type='path'),
|
src=dict(type='path'),
|
||||||
backup=dict(type='bool', default=False),
|
backup=dict(type='bool', default=False),
|
||||||
state=dict(type='str', required=True, choices=['absent', 'mounted', 'present', 'unmounted', 'remounted']),
|
state=dict(type='str', required=True, choices=['absent', 'mounted', 'present', 'unmounted', 'remounted']),
|
||||||
|
|||||||
@@ -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']
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,13 @@ options:
|
|||||||
required: true
|
required: true
|
||||||
choices: [ disabled, enforcing, permissive ]
|
choices: [ disabled, enforcing, permissive ]
|
||||||
type: str
|
type: str
|
||||||
|
update_kernel_param:
|
||||||
|
description:
|
||||||
|
- If set to I(true), will update also the kernel boot parameters when disabling/enabling SELinux.
|
||||||
|
- The C(grubby) tool must be present on the target system for this to work.
|
||||||
|
default: no
|
||||||
|
type: bool
|
||||||
|
version_added: '1.4.0'
|
||||||
configfile:
|
configfile:
|
||||||
description:
|
description:
|
||||||
- The path to the SELinux configuration file, if non-standard.
|
- The path to the SELinux configuration file, if non-standard.
|
||||||
@@ -97,6 +104,7 @@ except ImportError:
|
|||||||
HAS_SELINUX = False
|
HAS_SELINUX = False
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||||
|
from ansible.module_utils.common.process import get_bin_path
|
||||||
from ansible.module_utils.facts.utils import get_file_lines
|
from ansible.module_utils.facts.utils import get_file_lines
|
||||||
|
|
||||||
|
|
||||||
@@ -119,6 +127,34 @@ def get_config_policy(configfile):
|
|||||||
return line.split('=')[1].strip()
|
return line.split('=')[1].strip()
|
||||||
|
|
||||||
|
|
||||||
|
def get_kernel_enabled(module, grubby_bin):
|
||||||
|
if grubby_bin is None:
|
||||||
|
module.fail_json(msg="'grubby' command not found on host",
|
||||||
|
details="In order to update the kernel command line"
|
||||||
|
"enabled/disabled setting, the grubby package"
|
||||||
|
"needs to be present on the system.")
|
||||||
|
|
||||||
|
rc, stdout, stderr = module.run_command([grubby_bin, '--info=ALL'])
|
||||||
|
if rc != 0:
|
||||||
|
module.fail_json(msg="unable to run grubby")
|
||||||
|
|
||||||
|
all_enabled = True
|
||||||
|
all_disabled = True
|
||||||
|
for line in stdout.split('\n'):
|
||||||
|
match = re.match('^args="(.*)"$', line)
|
||||||
|
if match is None:
|
||||||
|
continue
|
||||||
|
args = match.group(1).split(' ')
|
||||||
|
if 'selinux=0' in args:
|
||||||
|
all_enabled = False
|
||||||
|
else:
|
||||||
|
all_disabled = False
|
||||||
|
if all_disabled == all_enabled:
|
||||||
|
# inconsistent config - return None to force update
|
||||||
|
return None
|
||||||
|
return all_enabled
|
||||||
|
|
||||||
|
|
||||||
# setter subroutines
|
# setter subroutines
|
||||||
def set_config_state(module, state, configfile):
|
def set_config_state(module, state, configfile):
|
||||||
# SELINUX=permissive
|
# SELINUX=permissive
|
||||||
@@ -153,6 +189,17 @@ def set_state(module, state):
|
|||||||
module.fail_json(msg=msg)
|
module.fail_json(msg=msg)
|
||||||
|
|
||||||
|
|
||||||
|
def set_kernel_enabled(module, grubby_bin, value):
|
||||||
|
rc, stdout, stderr = module.run_command([grubby_bin, '--update-kernel=ALL',
|
||||||
|
'--remove-args' if value else '--args',
|
||||||
|
'selinux=0'])
|
||||||
|
if rc != 0:
|
||||||
|
if value:
|
||||||
|
module.fail_json(msg='unable to remove selinux=0 from kernel config')
|
||||||
|
else:
|
||||||
|
module.fail_json(msg='unable to add selinux=0 to kernel config')
|
||||||
|
|
||||||
|
|
||||||
def set_config_policy(module, policy, configfile):
|
def set_config_policy(module, policy, configfile):
|
||||||
if not os.path.exists('/etc/selinux/%s/policy' % policy):
|
if not os.path.exists('/etc/selinux/%s/policy' % policy):
|
||||||
module.fail_json(msg='Policy %s does not exist in /etc/selinux/' % policy)
|
module.fail_json(msg='Policy %s does not exist in /etc/selinux/' % policy)
|
||||||
@@ -183,6 +230,7 @@ def main():
|
|||||||
policy=dict(type='str'),
|
policy=dict(type='str'),
|
||||||
state=dict(type='str', required=True, choices=['enforcing', 'permissive', 'disabled']),
|
state=dict(type='str', required=True, choices=['enforcing', 'permissive', 'disabled']),
|
||||||
configfile=dict(type='str', default='/etc/selinux/config', aliases=['conf', 'file']),
|
configfile=dict(type='str', default='/etc/selinux/config', aliases=['conf', 'file']),
|
||||||
|
update_kernel_param=dict(type='bool', default=False),
|
||||||
),
|
),
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
)
|
)
|
||||||
@@ -196,9 +244,11 @@ def main():
|
|||||||
configfile = module.params['configfile']
|
configfile = module.params['configfile']
|
||||||
policy = module.params['policy']
|
policy = module.params['policy']
|
||||||
state = module.params['state']
|
state = module.params['state']
|
||||||
|
update_kernel_param = module.params['update_kernel_param']
|
||||||
runtime_enabled = selinux.is_selinux_enabled()
|
runtime_enabled = selinux.is_selinux_enabled()
|
||||||
runtime_policy = selinux.selinux_getpolicytype()[1]
|
runtime_policy = selinux.selinux_getpolicytype()[1]
|
||||||
runtime_state = 'disabled'
|
runtime_state = 'disabled'
|
||||||
|
kernel_enabled = None
|
||||||
reboot_required = False
|
reboot_required = False
|
||||||
|
|
||||||
if runtime_enabled:
|
if runtime_enabled:
|
||||||
@@ -215,6 +265,12 @@ def main():
|
|||||||
|
|
||||||
config_policy = get_config_policy(configfile)
|
config_policy = get_config_policy(configfile)
|
||||||
config_state = get_config_state(configfile)
|
config_state = get_config_state(configfile)
|
||||||
|
if update_kernel_param:
|
||||||
|
try:
|
||||||
|
grubby_bin = get_bin_path('grubby')
|
||||||
|
except ValueError:
|
||||||
|
grubby_bin = None
|
||||||
|
kernel_enabled = get_kernel_enabled(module, grubby_bin)
|
||||||
|
|
||||||
# check to see if policy is set if state is not 'disabled'
|
# check to see if policy is set if state is not 'disabled'
|
||||||
if state != 'disabled':
|
if state != 'disabled':
|
||||||
@@ -269,6 +325,21 @@ def main():
|
|||||||
msgs.append("Config SELinux state changed from '%s' to '%s'" % (config_state, state))
|
msgs.append("Config SELinux state changed from '%s' to '%s'" % (config_state, state))
|
||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
|
requested_kernel_enabled = state in ('enforcing', 'permissive')
|
||||||
|
# Update kernel enabled/disabled config only when setting is consistent
|
||||||
|
# across all kernels AND the requested state differs from the current state
|
||||||
|
if update_kernel_param and kernel_enabled != requested_kernel_enabled:
|
||||||
|
if not module.check_mode:
|
||||||
|
set_kernel_enabled(module, grubby_bin, requested_kernel_enabled)
|
||||||
|
if requested_kernel_enabled:
|
||||||
|
states = ('disabled', 'enabled')
|
||||||
|
else:
|
||||||
|
states = ('enabled', 'disabled')
|
||||||
|
if kernel_enabled is None:
|
||||||
|
states = ('<inconsistent>', states[1])
|
||||||
|
msgs.append("Kernel SELinux state changed from '%s' to '%s'" % states)
|
||||||
|
changed = True
|
||||||
|
|
||||||
module.exit_json(changed=changed, msg=', '.join(msgs), configfile=configfile, policy=policy, state=state, reboot_required=reboot_required)
|
module.exit_json(changed=changed, msg=', '.join(msgs), configfile=configfile, policy=policy, state=state, reboot_required=reboot_required)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -587,8 +587,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
|
||||||
|
|||||||
@@ -4,13 +4,8 @@
|
|||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__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 = '''
|
DOCUMENTATION = '''
|
||||||
name: csh
|
name: csh
|
||||||
plugin_type: shell
|
|
||||||
short_description: C shell (/bin/csh)
|
short_description: C shell (/bin/csh)
|
||||||
description:
|
description:
|
||||||
- When you have no other option than to use csh
|
- When you have no other option than to use csh
|
||||||
@@ -18,6 +13,10 @@ DOCUMENTATION = '''
|
|||||||
- shell_common
|
- shell_common
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
from ansible.module_utils.six import text_type
|
||||||
|
from ansible.module_utils.six.moves import shlex_quote
|
||||||
|
from ansible.plugins.shell import ShellBase
|
||||||
|
|
||||||
|
|
||||||
class ShellModule(ShellBase):
|
class ShellModule(ShellBase):
|
||||||
|
|
||||||
|
|||||||
@@ -4,13 +4,8 @@
|
|||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
from ansible.module_utils.six import text_type
|
|
||||||
from ansible.module_utils.six.moves import shlex_quote
|
|
||||||
from ansible.plugins.shell.sh import ShellModule as ShModule
|
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = '''
|
||||||
name: fish
|
name: fish
|
||||||
plugin_type: shell
|
|
||||||
short_description: fish shell (/bin/fish)
|
short_description: fish shell (/bin/fish)
|
||||||
description:
|
description:
|
||||||
- This is here because some people are restricted to fish.
|
- This is here because some people are restricted to fish.
|
||||||
@@ -18,6 +13,10 @@ DOCUMENTATION = '''
|
|||||||
- shell_common
|
- shell_common
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
from ansible.module_utils.six import text_type
|
||||||
|
from ansible.module_utils.six.moves import shlex_quote
|
||||||
|
from ansible.plugins.shell.sh import ShellModule as ShModule
|
||||||
|
|
||||||
|
|
||||||
class ShellModule(ShModule):
|
class ShellModule(ShModule):
|
||||||
|
|
||||||
|
|||||||
@@ -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 }}"
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
# -------------------------------------------------------------
|
# -------------------------------------------------------------
|
||||||
# Setup steps
|
# Setup steps
|
||||||
|
- name: Clean up the working directory and files
|
||||||
|
file:
|
||||||
|
path: '{{ output_dir }}'
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Create the working directory
|
||||||
|
file:
|
||||||
|
path: '{{ output_dir }}'
|
||||||
|
state: directory
|
||||||
|
|
||||||
- name: copy an existing file in place with comments
|
- name: copy an existing file in place with comments
|
||||||
copy:
|
copy:
|
||||||
|
|||||||
@@ -14,7 +14,10 @@
|
|||||||
- include_tasks: port_test_cases.yml
|
- include_tasks: port_test_cases.yml
|
||||||
|
|
||||||
# firewalld source operation test cases
|
# firewalld source operation test cases
|
||||||
- import_tasks: source_test_cases.yml
|
- include_tasks: source_test_cases.yml
|
||||||
|
|
||||||
# firewalld zone target operation test cases
|
# firewalld zone target operation test cases
|
||||||
- import_tasks: zone_target_test_cases.yml
|
- include_tasks: zone_target_test_cases.yml
|
||||||
|
|
||||||
|
# firewalld port forwarding operation test cases
|
||||||
|
- include_tasks: port_forward_test_cases.yml
|
||||||
|
|||||||
@@ -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'"
|
||||||
|
|||||||
@@ -369,3 +369,40 @@
|
|||||||
- /tmp/myfs.img
|
- /tmp/myfs.img
|
||||||
- /tmp/myfs
|
- /tmp/myfs
|
||||||
when: ansible_system in ('Linux')
|
when: ansible_system in ('Linux')
|
||||||
|
|
||||||
|
- name: Block to test missing newline at the EOF of fstab
|
||||||
|
block:
|
||||||
|
- name: Create empty file
|
||||||
|
community.general.filesize:
|
||||||
|
path: /tmp/myfs1.img
|
||||||
|
size: 20M
|
||||||
|
- name: Format FS
|
||||||
|
community.general.filesystem:
|
||||||
|
fstype: ext3
|
||||||
|
dev: /tmp/myfs1.img
|
||||||
|
- name: Create custom fstab file without newline
|
||||||
|
copy:
|
||||||
|
content: '#TEST COMMENT WITHOUT NEWLINE'
|
||||||
|
dest: /tmp/test_fstab
|
||||||
|
- name: Mount the FS using the custom fstab
|
||||||
|
mount:
|
||||||
|
path: /tmp/myfs1
|
||||||
|
src: /tmp/myfs1.img
|
||||||
|
fstype: ext3
|
||||||
|
state: mounted
|
||||||
|
opts: defaults
|
||||||
|
fstab: /tmp/test_fstab
|
||||||
|
- name: Unmount the mount point in the custom fstab
|
||||||
|
mount:
|
||||||
|
path: /tmp/myfs1
|
||||||
|
state: absent
|
||||||
|
fstab: /tmp/test_fstab
|
||||||
|
- name: Remove the test FS and the custom fstab
|
||||||
|
file:
|
||||||
|
path: '{{ item }}'
|
||||||
|
state: absent
|
||||||
|
loop:
|
||||||
|
- /tmp/myfs1.img
|
||||||
|
- /tmp/myfs1
|
||||||
|
- /tmp/test_fstab
|
||||||
|
when: ansible_system in ('Linux')
|
||||||
|
|||||||
@@ -20,11 +20,25 @@
|
|||||||
# ##############################################################################
|
# ##############################################################################
|
||||||
# Test changing the state, which requires a reboot
|
# Test changing the state, which requires a reboot
|
||||||
|
|
||||||
|
- name: TEST 1 | Make sure grubby is present
|
||||||
|
package:
|
||||||
|
name: grubby
|
||||||
|
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
|
||||||
@@ -90,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
|
||||||
@@ -104,11 +127,52 @@
|
|||||||
- selinux_config_after[selinux_config_after.index('SELINUX=disabled')] is search("^SELINUX=\w+$")
|
- selinux_config_after[selinux_config_after.index('SELINUX=disabled')] is search("^SELINUX=\w+$")
|
||||||
- selinux_config_after[selinux_config_after.index('SELINUXTYPE=targeted')] is search("^SELINUXTYPE=\w+$")
|
- selinux_config_after[selinux_config_after.index('SELINUXTYPE=targeted')] is search("^SELINUXTYPE=\w+$")
|
||||||
|
|
||||||
- name: TEST 1 | Reset SELinux configuration for next test
|
- name: TEST 1 | Disable SELinux again, with kernel arguments update
|
||||||
|
selinux:
|
||||||
|
state: disabled
|
||||||
|
policy: targeted
|
||||||
|
update_kernel_param: true
|
||||||
|
register: _disable_test2
|
||||||
|
|
||||||
|
- name: Check kernel command-line arguments
|
||||||
|
ansible.builtin.command: grubby --info=DEFAULT
|
||||||
|
register: _grubby_test1
|
||||||
|
|
||||||
|
- name: TEST 1 | Assert that kernel cmdline contains selinux=0
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- "' selinux=0' in _grubby_test1.stdout"
|
||||||
|
|
||||||
|
- name: TEST 1 | Enable SELinux, without kernel arguments update
|
||||||
|
selinux:
|
||||||
|
state: disabled
|
||||||
|
policy: targeted
|
||||||
|
register: _disable_test2
|
||||||
|
|
||||||
|
- name: Check kernel command-line arguments
|
||||||
|
ansible.builtin.command: grubby --info=DEFAULT
|
||||||
|
register: _grubby_test1
|
||||||
|
|
||||||
|
- name: TEST 1 | Assert that kernel cmdline still contains selinux=0
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- "' selinux=0' in _grubby_test1.stdout"
|
||||||
|
|
||||||
|
- name: TEST 1 | Reset SELinux configuration for next test (also kernel args)
|
||||||
selinux:
|
selinux:
|
||||||
state: enforcing
|
state: enforcing
|
||||||
|
update_kernel_param: true
|
||||||
policy: targeted
|
policy: targeted
|
||||||
|
|
||||||
|
- name: Check kernel command-line arguments
|
||||||
|
ansible.builtin.command: grubby --info=DEFAULT
|
||||||
|
register: _grubby_test2
|
||||||
|
|
||||||
|
- name: TEST 1 | Assert that kernel cmdline doesn't contain selinux=0
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- "' selinux=0' not in _grubby_test2.stdout"
|
||||||
|
|
||||||
|
|
||||||
# Second Test
|
# Second Test
|
||||||
# ##############################################################################
|
# ##############################################################################
|
||||||
@@ -163,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
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
plugins/modules/synchronize.py pylint:blacklisted-name
|
plugins/modules/synchronize.py pylint:disallowed-name
|
||||||
plugins/modules/synchronize.py use-argspec-type-path
|
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:doc-default-does-not-match-spec
|
||||||
plugins/modules/synchronize.py validate-modules:nonexistent-parameter-documented
|
plugins/modules/synchronize.py validate-modules:nonexistent-parameter-documented
|
||||||
|
|||||||
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
|
||||||
8
tests/sanity/ignore-2.14.txt
Normal file
8
tests/sanity/ignore-2.14.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
|
||||||
@@ -46,8 +46,8 @@ class DictDataLoader(DataLoader):
|
|||||||
|
|
||||||
# TODO: the real _get_file_contents returns a bytestring, so we actually convert the
|
# TODO: the real _get_file_contents returns a bytestring, so we actually convert the
|
||||||
# unicode/text it's created with to utf-8
|
# unicode/text it's created with to utf-8
|
||||||
def _get_file_contents(self, path):
|
def _get_file_contents(self, file_name):
|
||||||
path = to_text(path)
|
path = to_text(file_name)
|
||||||
if path in self._file_mapping:
|
if path in self._file_mapping:
|
||||||
return (to_bytes(self._file_mapping[path]), False)
|
return (to_bytes(self._file_mapping[path]), False)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ class TaskMock(object):
|
|||||||
become = None
|
become = None
|
||||||
become_user = None
|
become_user = None
|
||||||
become_method = None
|
become_method = None
|
||||||
|
check_mode = False
|
||||||
|
|
||||||
|
|
||||||
class StdinMock(object):
|
class StdinMock(object):
|
||||||
@@ -125,7 +126,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
|
||||||
@@ -74,7 +74,14 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# START: HACK install dependencies
|
# START: HACK install dependencies
|
||||||
retry ansible-galaxy collection install community.general
|
if [ "${ansible_version}" == "2.9" ] || [ "${ansible_version}" == "2.10" ]; then
|
||||||
|
# Note: Since community.general 5.x, Ansible Core versions prior to 2.11 are not supported.
|
||||||
|
# So we need to use 4.8.1 for Ansible 2.9 and Ansible Engine 2.10.
|
||||||
|
retry git clone --depth=1 --single-branch -b 4.8.1 https://github.com/ansible-collections/community.general.git "${ANSIBLE_COLLECTIONS_PATHS}/ansible_collections/community/general"
|
||||||
|
else
|
||||||
|
retry git clone --depth=1 --single-branch https://github.com/ansible-collections/community.general.git "${ANSIBLE_COLLECTIONS_PATHS}/ansible_collections/community/general"
|
||||||
|
fi
|
||||||
|
# Note: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429)
|
||||||
# END: HACK
|
# END: HACK
|
||||||
|
|
||||||
export PYTHONIOENCODING='utf-8'
|
export PYTHONIOENCODING='utf-8'
|
||||||
|
|||||||
Reference in New Issue
Block a user