mirror of
https://github.com/ansible-collections/ansible.posix.git
synced 2026-05-12 12:32:00 +00:00
Compare commits
250 Commits
1.1.1
...
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 | ||
|
|
ab9eaf24bc | ||
|
|
fad1d3a870 | ||
|
|
c21fb99f54 | ||
|
|
a65807edc3 | ||
|
|
dad5379461 | ||
|
|
bd594970a8 | ||
|
|
c244abd82f | ||
|
|
42d2b9c65a | ||
|
|
7a62e01af6 | ||
|
|
18614bb82d | ||
|
|
944f5416c9 | ||
|
|
ce3d0fdfa4 | ||
|
|
244c9b2066 | ||
|
|
f85f2904c9 | ||
|
|
db12a40a4c | ||
|
|
5282ece77e | ||
|
|
133ffe51fb | ||
|
|
b3e395a4a3 | ||
|
|
424004c4c0 | ||
|
|
dd2782d81c | ||
|
|
f7f5f89899 | ||
|
|
2b7a35c346 | ||
|
|
fee81b19a8 | ||
|
|
1ebacfb195 | ||
|
|
ab5c1d9911 | ||
|
|
4be66cfb34 | ||
|
|
c5d49b2a91 | ||
|
|
a03e652437 | ||
|
|
e815909859 | ||
|
|
f2601b01da | ||
|
|
27434455e5 | ||
|
|
25cfc56f6f | ||
|
|
f6fa00bfff | ||
|
|
68263bfc29 | ||
|
|
e23ea12cc5 | ||
|
|
69d17ed4b7 | ||
|
|
ed573a8223 | ||
|
|
dd7d29495d | ||
|
|
c596feab78 | ||
|
|
606e3cfe07 | ||
|
|
23fadc9f02 | ||
|
|
6d51660be4 | ||
|
|
957a7420ca | ||
|
|
b740bdaf3a | ||
|
|
049292669b | ||
|
|
310c68e6dd | ||
|
|
fcb2a466e0 | ||
|
|
757b544cf3 | ||
|
|
9f384c00a3 | ||
|
|
0118bf0cb9 | ||
|
|
a994a58b23 | ||
|
|
23afcce8b8 | ||
|
|
e2a316122a | ||
|
|
1671173e99 | ||
|
|
0b597f2e66 | ||
|
|
e068522325 | ||
|
|
51d117285f | ||
|
|
c29bbd265b | ||
|
|
7417d857f1 | ||
|
|
ceddb849b8 | ||
|
|
f5666924ab | ||
|
|
7bed8ce79e | ||
|
|
7d928e6e9d | ||
|
|
07fe3a91b6 | ||
|
|
5cebc90623 | ||
|
|
6ba8445fb1 | ||
|
|
9d4ae8b7e4 | ||
|
|
41e5b8428f | ||
|
|
1793cd70c4 | ||
|
|
b98c7926da | ||
|
|
5d0c5ae3a6 | ||
|
|
cfff8a3806 | ||
|
|
7e6adc977f | ||
|
|
54ea8777f8 | ||
|
|
5d0c8e40d8 | ||
|
|
eaf3d666cc | ||
|
|
c985096af5 | ||
|
|
92c6037900 | ||
|
|
0bef7bb164 | ||
|
|
6e60b0d454 | ||
|
|
0e6f8ab976 | ||
|
|
6b41ce1a9d | ||
|
|
052a2f6d94 | ||
|
|
13e77fd7da | ||
|
|
1f15216d0d | ||
|
|
9173166223 | ||
|
|
da82df4004 | ||
|
|
9313bf3e68 | ||
|
|
8ae6651cff | ||
|
|
86b32d8730 | ||
|
|
707523a763 | ||
|
|
8b1b4df54f | ||
|
|
fc9fce718d | ||
|
|
7511421440 | ||
|
|
d976add5da | ||
|
|
ecd5ad53e0 | ||
|
|
f6f436f227 | ||
|
|
355a99f779 | ||
|
|
c8b58875d9 | ||
|
|
bd8a3f35c2 | ||
|
|
edec4d767d | ||
|
|
0a56fb0e46 | ||
|
|
f3b6b5e690 | ||
|
|
d65a36e9ea | ||
|
|
252b531c20 | ||
|
|
bc88258687 | ||
|
|
1747370f30 | ||
|
|
72353d3f04 | ||
|
|
1822789d95 | ||
|
|
ccbb679fc3 | ||
|
|
98c86c54cd | ||
|
|
354239d6c9 | ||
|
|
4825036c7e | ||
|
|
360d0c3441 | ||
|
|
d8fb68514c | ||
|
|
d8c6add988 | ||
|
|
ea8fc70373 | ||
|
|
20f70caa1f | ||
|
|
04f976d7d3 | ||
|
|
b6a2dee8bb | ||
|
|
5b66052067 | ||
|
|
2655a6ffc1 | ||
|
|
bbba9beb70 | ||
|
|
a8594c5477 | ||
|
|
3043f737a0 | ||
|
|
080ae28e7d | ||
|
|
e1dad76ccb | ||
|
|
bc0fb3096b | ||
|
|
1e7d82af6d | ||
|
|
41d49e4e08 | ||
|
|
6241e09ccd | ||
|
|
679fe78f32 | ||
|
|
b8c5d6b1b7 | ||
|
|
665f84d996 | ||
|
|
c359200e80 | ||
|
|
793b039691 | ||
|
|
ef36fdc17d | ||
|
|
bcb08106d9 | ||
|
|
cbf54f214c | ||
|
|
931326fb70 | ||
|
|
6343dbdcff | ||
|
|
34a12eb3f9 | ||
|
|
402e0b1f76 | ||
|
|
1268d4aa0a | ||
|
|
5988748999 | ||
|
|
5935dce47f | ||
|
|
77df4ba3fd | ||
|
|
1e84bce91a | ||
|
|
d1fff45191 | ||
|
|
0eeaf61a1a | ||
|
|
c96be65ec9 | ||
|
|
4b0b50439d |
3
.azure-pipelines/README.md
Normal file
3
.azure-pipelines/README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
## Azure Pipelines Configuration
|
||||||
|
|
||||||
|
Please see the [Documentation](https://github.com/ansible/community/wiki/Testing:-Azure-Pipelines) for more information.
|
||||||
299
.azure-pipelines/azure-pipelines.yml
Normal file
299
.azure-pipelines/azure-pipelines.yml
Normal file
@@ -0,0 +1,299 @@
|
|||||||
|
trigger:
|
||||||
|
batch: true
|
||||||
|
branches:
|
||||||
|
include:
|
||||||
|
- main
|
||||||
|
- stable-*
|
||||||
|
|
||||||
|
pr:
|
||||||
|
autoCancel: true
|
||||||
|
branches:
|
||||||
|
include:
|
||||||
|
- main
|
||||||
|
- stable-*
|
||||||
|
|
||||||
|
schedules:
|
||||||
|
- cron: 0 9 * * *
|
||||||
|
displayName: Nightly
|
||||||
|
always: true
|
||||||
|
branches:
|
||||||
|
include:
|
||||||
|
- main
|
||||||
|
- stable-*
|
||||||
|
|
||||||
|
variables:
|
||||||
|
- name: checkoutPath
|
||||||
|
value: ansible_collections/ansible/posix
|
||||||
|
- name: coverageBranches
|
||||||
|
value: main
|
||||||
|
- name: pipelinesCoverage
|
||||||
|
value: coverage
|
||||||
|
- name: entryPoint
|
||||||
|
value: tests/utils/shippable/shippable.sh
|
||||||
|
- name: fetchDepth
|
||||||
|
value: 0
|
||||||
|
|
||||||
|
resources:
|
||||||
|
containers:
|
||||||
|
- container: default
|
||||||
|
image: quay.io/ansible/azure-pipelines-test-container:3.0.0
|
||||||
|
|
||||||
|
pool: Standard
|
||||||
|
|
||||||
|
stages:
|
||||||
|
|
||||||
|
## Docker
|
||||||
|
- stage: Docker_devel
|
||||||
|
displayName: Docker devel
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
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:
|
||||||
|
- name: CentOS 6
|
||||||
|
test: centos6
|
||||||
|
- name: CentOS 7
|
||||||
|
test: centos7
|
||||||
|
- name: Fedora 33
|
||||||
|
test: fedora33
|
||||||
|
- name: Fedora 34
|
||||||
|
test: fedora34
|
||||||
|
- name: openSUSE 15 py2
|
||||||
|
test: opensuse15py2
|
||||||
|
- name: openSUSE 15 py3
|
||||||
|
test: opensuse15
|
||||||
|
- name: Ubuntu 18.04
|
||||||
|
test: ubuntu1804
|
||||||
|
- name: Ubuntu 20.04
|
||||||
|
test: ubuntu2004
|
||||||
|
- stage: Docker_2_11
|
||||||
|
displayName: Docker 2.11
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
testFormat: 2.11/linux/{0}/1
|
||||||
|
targets:
|
||||||
|
- name: CentOS 6
|
||||||
|
test: centos6
|
||||||
|
- name: CentOS 7
|
||||||
|
test: centos7
|
||||||
|
- name: Fedora 32
|
||||||
|
test: fedora32
|
||||||
|
- name: Fedora 33
|
||||||
|
test: fedora33
|
||||||
|
- name: openSUSE 15 py2
|
||||||
|
test: opensuse15py2
|
||||||
|
- name: openSUSE 15 py3
|
||||||
|
test: opensuse15
|
||||||
|
- name: Ubuntu 18.04
|
||||||
|
test: ubuntu1804
|
||||||
|
- name: Ubuntu 20.04
|
||||||
|
test: ubuntu2004
|
||||||
|
- stage: Docker_2_10
|
||||||
|
displayName: Docker 2.10
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
testFormat: 2.10/linux/{0}/1
|
||||||
|
targets:
|
||||||
|
- name: CentOS 6
|
||||||
|
test: centos6
|
||||||
|
- name: CentOS 7
|
||||||
|
test: centos7
|
||||||
|
- name: Fedora 30
|
||||||
|
test: fedora30
|
||||||
|
- name: Fedora 31
|
||||||
|
test: fedora31
|
||||||
|
- name: openSUSE 15 py2
|
||||||
|
test: opensuse15py2
|
||||||
|
- name: openSUSE 15 py3
|
||||||
|
test: opensuse15
|
||||||
|
- name: Ubuntu 16.04
|
||||||
|
test: ubuntu1604
|
||||||
|
- name: Ubuntu 18.04
|
||||||
|
test: ubuntu1804
|
||||||
|
- stage: Docker_2_9
|
||||||
|
displayName: Docker 2.9
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
testFormat: 2.9/linux/{0}/1
|
||||||
|
targets:
|
||||||
|
- name: CentOS 6
|
||||||
|
test: centos6
|
||||||
|
- name: CentOS 7
|
||||||
|
test: centos7
|
||||||
|
- name: Fedora 30
|
||||||
|
test: fedora30
|
||||||
|
- name: Fedora 31
|
||||||
|
test: fedora31
|
||||||
|
- name: openSUSE 15 py2
|
||||||
|
test: opensuse15py2
|
||||||
|
- name: openSUSE 15 py3
|
||||||
|
test: opensuse15
|
||||||
|
- name: Ubuntu 16.04
|
||||||
|
test: ubuntu1604
|
||||||
|
- name: Ubuntu 18.04
|
||||||
|
test: ubuntu1804
|
||||||
|
|
||||||
|
## Remote
|
||||||
|
- stage: Remote_devel
|
||||||
|
displayName: Remote devel
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
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:
|
||||||
|
- name: MacOS 11.1
|
||||||
|
test: macos/11.1
|
||||||
|
- name: RHEL 7.9
|
||||||
|
test: rhel/7.9
|
||||||
|
- name: RHEL 8.4
|
||||||
|
test: rhel/8.4
|
||||||
|
- name: FreeBSD 12.2
|
||||||
|
test: freebsd/12.2
|
||||||
|
- name: FreeBSD 13.0
|
||||||
|
test: freebsd/13.0
|
||||||
|
- stage: Remote_2_11
|
||||||
|
displayName: Remote 2.11
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
testFormat: 2.11/{0}/1
|
||||||
|
targets:
|
||||||
|
- name: MacOS 11.1
|
||||||
|
test: macos/11.1
|
||||||
|
- name: RHEL 7.9
|
||||||
|
test: rhel/7.9
|
||||||
|
- name: RHEL 8.3
|
||||||
|
test: rhel/8.3
|
||||||
|
- name: FreeBSD 12.2
|
||||||
|
test: freebsd/12.2
|
||||||
|
- stage: Remote_2_10
|
||||||
|
displayName: Remote 2.10
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
testFormat: 2.10/{0}/1
|
||||||
|
targets:
|
||||||
|
- name: OS X 10.11
|
||||||
|
test: osx/10.11
|
||||||
|
- name: RHEL 7.9
|
||||||
|
test: rhel/7.9
|
||||||
|
- name: RHEL 8.2
|
||||||
|
test: rhel/8.2
|
||||||
|
- stage: Remote_2_9
|
||||||
|
displayName: Remote 2.9
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
testFormat: 2.9/{0}/1
|
||||||
|
targets:
|
||||||
|
- name: OS X 10.11
|
||||||
|
test: osx/10.11
|
||||||
|
- name: RHEL 7.9
|
||||||
|
test: rhel/7.9
|
||||||
|
- name: RHEL 8.1
|
||||||
|
test: rhel/8.1
|
||||||
|
|
||||||
|
## Finally
|
||||||
|
|
||||||
|
- stage: Summary
|
||||||
|
condition: succeededOrFailed()
|
||||||
|
dependsOn:
|
||||||
|
- Remote_2_9
|
||||||
|
- Docker_2_9
|
||||||
|
- Remote_2_10
|
||||||
|
- Docker_2_10
|
||||||
|
- Remote_2_11
|
||||||
|
- Docker_2_11
|
||||||
|
- Remote_2_12
|
||||||
|
- Docker_2_12
|
||||||
|
- Remote_2_13
|
||||||
|
- Docker_2_13
|
||||||
|
- Remote_devel
|
||||||
|
- Docker_devel
|
||||||
|
jobs:
|
||||||
|
- template: templates/coverage.yml
|
||||||
20
.azure-pipelines/scripts/aggregate-coverage.sh
Executable file
20
.azure-pipelines/scripts/aggregate-coverage.sh
Executable file
@@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Aggregate code coverage results for later processing.
|
||||||
|
|
||||||
|
set -o pipefail -eu
|
||||||
|
|
||||||
|
agent_temp_directory="$1"
|
||||||
|
|
||||||
|
PATH="${PWD}/bin:${PATH}"
|
||||||
|
|
||||||
|
mkdir "${agent_temp_directory}/coverage/"
|
||||||
|
|
||||||
|
options=(--venv --venv-system-site-packages --color -v)
|
||||||
|
|
||||||
|
ansible-test coverage combine --export "${agent_temp_directory}/coverage/" "${options[@]}"
|
||||||
|
|
||||||
|
if ansible-test coverage analyze targets generate --help >/dev/null 2>&1; then
|
||||||
|
# Only analyze coverage if the installed version of ansible-test supports it.
|
||||||
|
# Doing so allows this script to work unmodified for multiple Ansible versions.
|
||||||
|
ansible-test coverage analyze targets generate "${agent_temp_directory}/coverage/coverage-analyze-targets.json" "${options[@]}"
|
||||||
|
fi
|
||||||
60
.azure-pipelines/scripts/combine-coverage.py
Executable file
60
.azure-pipelines/scripts/combine-coverage.py
Executable file
@@ -0,0 +1,60 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""
|
||||||
|
Combine coverage data from multiple jobs, keeping the data only from the most recent attempt from each job.
|
||||||
|
Coverage artifacts must be named using the format: "Coverage $(System.JobAttempt) {StableUniqueNameForEachJob}"
|
||||||
|
The recommended coverage artifact name format is: Coverage $(System.JobAttempt) $(System.StageDisplayName) $(System.JobDisplayName)
|
||||||
|
Keep in mind that Azure Pipelines does not enforce unique job display names (only names).
|
||||||
|
It is up to pipeline authors to avoid name collisions when deviating from the recommended format.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Main program entry point."""
|
||||||
|
source_directory = sys.argv[1]
|
||||||
|
|
||||||
|
if '/ansible_collections/' in os.getcwd():
|
||||||
|
output_path = "tests/output"
|
||||||
|
else:
|
||||||
|
output_path = "test/results"
|
||||||
|
|
||||||
|
destination_directory = os.path.join(output_path, 'coverage')
|
||||||
|
|
||||||
|
if not os.path.exists(destination_directory):
|
||||||
|
os.makedirs(destination_directory)
|
||||||
|
|
||||||
|
jobs = {}
|
||||||
|
count = 0
|
||||||
|
|
||||||
|
for name in os.listdir(source_directory):
|
||||||
|
match = re.search('^Coverage (?P<attempt>[0-9]+) (?P<label>.+)$', name)
|
||||||
|
label = match.group('label')
|
||||||
|
attempt = int(match.group('attempt'))
|
||||||
|
jobs[label] = max(attempt, jobs.get(label, 0))
|
||||||
|
|
||||||
|
for label, attempt in jobs.items():
|
||||||
|
name = 'Coverage {attempt} {label}'.format(label=label, attempt=attempt)
|
||||||
|
source = os.path.join(source_directory, name)
|
||||||
|
source_files = os.listdir(source)
|
||||||
|
|
||||||
|
for source_file in source_files:
|
||||||
|
source_path = os.path.join(source, source_file)
|
||||||
|
destination_path = os.path.join(destination_directory, source_file + '.' + label)
|
||||||
|
print('"%s" -> "%s"' % (source_path, destination_path))
|
||||||
|
shutil.copyfile(source_path, destination_path)
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
print('Coverage file count: %d' % count)
|
||||||
|
print('##vso[task.setVariable variable=coverageFileCount]%d' % count)
|
||||||
|
print('##vso[task.setVariable variable=outputPath]%s' % output_path)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
24
.azure-pipelines/scripts/process-results.sh
Executable file
24
.azure-pipelines/scripts/process-results.sh
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Check the test results and set variables for use in later steps.
|
||||||
|
|
||||||
|
set -o pipefail -eu
|
||||||
|
|
||||||
|
if [[ "$PWD" =~ /ansible_collections/ ]]; then
|
||||||
|
output_path="tests/output"
|
||||||
|
else
|
||||||
|
output_path="test/results"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "##vso[task.setVariable variable=outputPath]${output_path}"
|
||||||
|
|
||||||
|
if compgen -G "${output_path}"'/junit/*.xml' > /dev/null; then
|
||||||
|
echo "##vso[task.setVariable variable=haveTestResults]true"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if compgen -G "${output_path}"'/bot/ansible-test-*' > /dev/null; then
|
||||||
|
echo "##vso[task.setVariable variable=haveBotResults]true"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if compgen -G "${output_path}"'/coverage/*' > /dev/null; then
|
||||||
|
echo "##vso[task.setVariable variable=haveCoverageData]true"
|
||||||
|
fi
|
||||||
27
.azure-pipelines/scripts/publish-codecov.sh
Executable file
27
.azure-pipelines/scripts/publish-codecov.sh
Executable file
@@ -0,0 +1,27 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Upload code coverage reports to codecov.io.
|
||||||
|
# Multiple coverage files from multiple languages are accepted and aggregated after upload.
|
||||||
|
# Python coverage, as well as PowerShell and Python stubs can all be uploaded.
|
||||||
|
|
||||||
|
set -o pipefail -eu
|
||||||
|
|
||||||
|
output_path="$1"
|
||||||
|
|
||||||
|
curl --silent --show-error https://ansible-ci-files.s3.us-east-1.amazonaws.com/codecov/codecov.sh > codecov.sh
|
||||||
|
|
||||||
|
for file in "${output_path}"/reports/coverage*.xml; do
|
||||||
|
name="${file}"
|
||||||
|
name="${name##*/}" # remove path
|
||||||
|
name="${name##coverage=}" # remove 'coverage=' prefix if present
|
||||||
|
name="${name%.xml}" # remove '.xml' suffix
|
||||||
|
|
||||||
|
bash codecov.sh \
|
||||||
|
-f "${file}" \
|
||||||
|
-n "${name}" \
|
||||||
|
-X coveragepy \
|
||||||
|
-X gcov \
|
||||||
|
-X fix \
|
||||||
|
-X search \
|
||||||
|
-X xcode \
|
||||||
|
|| echo "Failed to upload code coverage report to codecov.io: ${file}"
|
||||||
|
done
|
||||||
15
.azure-pipelines/scripts/report-coverage.sh
Executable file
15
.azure-pipelines/scripts/report-coverage.sh
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Generate code coverage reports for uploading to Azure Pipelines and codecov.io.
|
||||||
|
|
||||||
|
set -o pipefail -eu
|
||||||
|
|
||||||
|
PATH="${PWD}/bin:${PATH}"
|
||||||
|
|
||||||
|
if ! ansible-test --help >/dev/null 2>&1; then
|
||||||
|
# Install the devel version of ansible-test for generating code coverage reports.
|
||||||
|
# This is only used by Ansible Collections, which are typically tested against multiple Ansible versions (in separate jobs).
|
||||||
|
# Since a version of ansible-test is required that can work the output from multiple older releases, the devel version is used.
|
||||||
|
pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check
|
||||||
|
fi
|
||||||
|
|
||||||
|
ansible-test coverage xml --stub --venv --venv-system-site-packages --color -v
|
||||||
34
.azure-pipelines/scripts/run-tests.sh
Executable file
34
.azure-pipelines/scripts/run-tests.sh
Executable file
@@ -0,0 +1,34 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Configure the test environment and run the tests.
|
||||||
|
|
||||||
|
set -o pipefail -eu
|
||||||
|
|
||||||
|
entry_point="$1"
|
||||||
|
test="$2"
|
||||||
|
read -r -a coverage_branches <<< "$3" # space separated list of branches to run code coverage on for scheduled builds
|
||||||
|
|
||||||
|
export COMMIT_MESSAGE
|
||||||
|
export COMPLETE
|
||||||
|
export COVERAGE
|
||||||
|
export IS_PULL_REQUEST
|
||||||
|
|
||||||
|
if [ "${SYSTEM_PULLREQUEST_TARGETBRANCH:-}" ]; then
|
||||||
|
IS_PULL_REQUEST=true
|
||||||
|
COMMIT_MESSAGE=$(git log --format=%B -n 1 HEAD^2)
|
||||||
|
else
|
||||||
|
IS_PULL_REQUEST=
|
||||||
|
COMMIT_MESSAGE=$(git log --format=%B -n 1 HEAD)
|
||||||
|
fi
|
||||||
|
|
||||||
|
COMPLETE=
|
||||||
|
COVERAGE=
|
||||||
|
|
||||||
|
if [ "${BUILD_REASON}" = "Schedule" ]; then
|
||||||
|
COMPLETE=yes
|
||||||
|
|
||||||
|
if printf '%s\n' "${coverage_branches[@]}" | grep -q "^${BUILD_SOURCEBRANCHNAME}$"; then
|
||||||
|
COVERAGE=yes
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
"${entry_point}" "${test}" 2>&1 | "$(dirname "$0")/time-command.py"
|
||||||
25
.azure-pipelines/scripts/time-command.py
Executable file
25
.azure-pipelines/scripts/time-command.py
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""Prepends a relative timestamp to each input line from stdin and writes it to stdout."""
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Main program entry point."""
|
||||||
|
start = time.time()
|
||||||
|
|
||||||
|
sys.stdin.reconfigure(errors='surrogateescape')
|
||||||
|
sys.stdout.reconfigure(errors='surrogateescape')
|
||||||
|
|
||||||
|
for line in sys.stdin:
|
||||||
|
seconds = time.time() - start
|
||||||
|
sys.stdout.write('%02d:%02d %s' % (seconds // 60, seconds % 60, line))
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
39
.azure-pipelines/templates/coverage.yml
Normal file
39
.azure-pipelines/templates/coverage.yml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# This template adds a job for processing code coverage data.
|
||||||
|
# It will upload results to Azure Pipelines and codecov.io.
|
||||||
|
# Use it from a job stage that completes after all other jobs have completed.
|
||||||
|
# This can be done by placing it in a separate summary stage that runs after the test stage(s) have completed.
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
- job: Coverage
|
||||||
|
displayName: Code Coverage
|
||||||
|
container: default
|
||||||
|
workspace:
|
||||||
|
clean: all
|
||||||
|
steps:
|
||||||
|
- checkout: self
|
||||||
|
fetchDepth: $(fetchDepth)
|
||||||
|
path: $(checkoutPath)
|
||||||
|
- task: DownloadPipelineArtifact@2
|
||||||
|
displayName: Download Coverage Data
|
||||||
|
inputs:
|
||||||
|
path: coverage/
|
||||||
|
patterns: "Coverage */*=coverage.combined"
|
||||||
|
- bash: .azure-pipelines/scripts/combine-coverage.py coverage/
|
||||||
|
displayName: Combine Coverage Data
|
||||||
|
- bash: .azure-pipelines/scripts/report-coverage.sh
|
||||||
|
displayName: Generate Coverage Report
|
||||||
|
condition: gt(variables.coverageFileCount, 0)
|
||||||
|
- task: PublishCodeCoverageResults@1
|
||||||
|
inputs:
|
||||||
|
codeCoverageTool: Cobertura
|
||||||
|
# Azure Pipelines only accepts a single coverage data file.
|
||||||
|
# That means only Python or PowerShell coverage can be uploaded, but not both.
|
||||||
|
# Set the "pipelinesCoverage" variable to determine which type is uploaded.
|
||||||
|
# Use "coverage" for Python and "coverage-powershell" for PowerShell.
|
||||||
|
summaryFileLocation: "$(outputPath)/reports/$(pipelinesCoverage).xml"
|
||||||
|
displayName: Publish to Azure Pipelines
|
||||||
|
condition: gt(variables.coverageFileCount, 0)
|
||||||
|
- bash: .azure-pipelines/scripts/publish-codecov.sh "$(outputPath)"
|
||||||
|
displayName: Publish to codecov.io
|
||||||
|
condition: gt(variables.coverageFileCount, 0)
|
||||||
|
continueOnError: true
|
||||||
55
.azure-pipelines/templates/matrix.yml
Normal file
55
.azure-pipelines/templates/matrix.yml
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
# This template uses the provided targets and optional groups to generate a matrix which is then passed to the test template.
|
||||||
|
# If this matrix template does not provide the required functionality, consider using the test template directly instead.
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
# A required list of dictionaries, one per test target.
|
||||||
|
# Each item in the list must contain a "test" or "name" key.
|
||||||
|
# Both may be provided. If one is omitted, the other will be used.
|
||||||
|
- name: targets
|
||||||
|
type: object
|
||||||
|
|
||||||
|
# An optional list of values which will be used to multiply the targets list into a matrix.
|
||||||
|
# Values can be strings or numbers.
|
||||||
|
- name: groups
|
||||||
|
type: object
|
||||||
|
default: []
|
||||||
|
|
||||||
|
# An optional format string used to generate the job name.
|
||||||
|
# - {0} is the name of an item in the targets list.
|
||||||
|
- name: nameFormat
|
||||||
|
type: string
|
||||||
|
default: "{0}"
|
||||||
|
|
||||||
|
# An optional format string used to generate the test name.
|
||||||
|
# - {0} is the name of an item in the targets list.
|
||||||
|
- name: testFormat
|
||||||
|
type: string
|
||||||
|
default: "{0}"
|
||||||
|
|
||||||
|
# An optional format string used to add the group to the job name.
|
||||||
|
# {0} is the formatted name of an item in the targets list.
|
||||||
|
# {{1}} is the group -- be sure to include the double "{{" and "}}".
|
||||||
|
- name: nameGroupFormat
|
||||||
|
type: string
|
||||||
|
default: "{0} - {{1}}"
|
||||||
|
|
||||||
|
# An optional format string used to add the group to the test name.
|
||||||
|
# {0} is the formatted test of an item in the targets list.
|
||||||
|
# {{1}} is the group -- be sure to include the double "{{" and "}}".
|
||||||
|
- name: testGroupFormat
|
||||||
|
type: string
|
||||||
|
default: "{0}/{{1}}"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
- template: test.yml
|
||||||
|
parameters:
|
||||||
|
jobs:
|
||||||
|
- ${{ if eq(length(parameters.groups), 0) }}:
|
||||||
|
- ${{ each target in parameters.targets }}:
|
||||||
|
- name: ${{ format(parameters.nameFormat, coalesce(target.name, target.test)) }}
|
||||||
|
test: ${{ format(parameters.testFormat, coalesce(target.test, target.name)) }}
|
||||||
|
- ${{ if not(eq(length(parameters.groups), 0)) }}:
|
||||||
|
- ${{ each group in parameters.groups }}:
|
||||||
|
- ${{ each target in parameters.targets }}:
|
||||||
|
- name: ${{ format(format(parameters.nameGroupFormat, parameters.nameFormat), coalesce(target.name, target.test), group) }}
|
||||||
|
test: ${{ format(format(parameters.testGroupFormat, parameters.testFormat), coalesce(target.test, target.name), group) }}
|
||||||
45
.azure-pipelines/templates/test.yml
Normal file
45
.azure-pipelines/templates/test.yml
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
# This template uses the provided list of jobs to create test one or more test jobs.
|
||||||
|
# It can be used directly if needed, or through the matrix template.
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
# A required list of dictionaries, one per test job.
|
||||||
|
# Each item in the list must contain a "job" and "name" key.
|
||||||
|
- name: jobs
|
||||||
|
type: object
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
- ${{ each job in parameters.jobs }}:
|
||||||
|
- job: test_${{ replace(replace(replace(job.test, '/', '_'), '.', '_'), '-', '_') }}
|
||||||
|
displayName: ${{ job.name }}
|
||||||
|
container: default
|
||||||
|
workspace:
|
||||||
|
clean: all
|
||||||
|
steps:
|
||||||
|
- checkout: self
|
||||||
|
fetchDepth: $(fetchDepth)
|
||||||
|
path: $(checkoutPath)
|
||||||
|
- bash: .azure-pipelines/scripts/run-tests.sh "$(entryPoint)" "${{ job.test }}" "$(coverageBranches)"
|
||||||
|
displayName: Run Tests
|
||||||
|
- bash: .azure-pipelines/scripts/process-results.sh
|
||||||
|
condition: succeededOrFailed()
|
||||||
|
displayName: Process Results
|
||||||
|
- bash: .azure-pipelines/scripts/aggregate-coverage.sh "$(Agent.TempDirectory)"
|
||||||
|
condition: eq(variables.haveCoverageData, 'true')
|
||||||
|
displayName: Aggregate Coverage Data
|
||||||
|
- task: PublishTestResults@2
|
||||||
|
condition: eq(variables.haveTestResults, 'true')
|
||||||
|
inputs:
|
||||||
|
testResultsFiles: "$(outputPath)/junit/*.xml"
|
||||||
|
displayName: Publish Test Results
|
||||||
|
- task: PublishPipelineArtifact@1
|
||||||
|
condition: eq(variables.haveBotResults, 'true')
|
||||||
|
displayName: Publish Bot Results
|
||||||
|
inputs:
|
||||||
|
targetPath: "$(outputPath)/bot/"
|
||||||
|
artifactName: "Bot $(System.JobAttempt) $(System.StageDisplayName) $(System.JobDisplayName)"
|
||||||
|
- task: PublishPipelineArtifact@1
|
||||||
|
condition: eq(variables.haveCoverageData, 'true')
|
||||||
|
displayName: Publish Coverage Data
|
||||||
|
inputs:
|
||||||
|
targetPath: "$(Agent.TempDirectory)/coverage/"
|
||||||
|
artifactName: "Coverage $(System.JobAttempt) $(System.StageDisplayName) $(System.JobDisplayName)"
|
||||||
@@ -5,6 +5,103 @@ 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
|
||||||
|
======
|
||||||
|
|
||||||
|
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.2.0.
|
||||||
|
|
||||||
|
Minor Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- acl - add new alias ``recurse`` for ``recursive`` parameter (https://github.com/ansible-collections/ansible.posix/issues/124).
|
||||||
|
- added 2.11 branch to test matrix, added ignore-2.12.txt.
|
||||||
|
- authorized_key - add ``no_log=False`` in ``argument_spec`` to clear false-positives of ``no-log-needed`` (https://github.com/ansible-collections/ansible.posix/pull/156).
|
||||||
|
- authorized_key - add a list of valid key types (https://github.com/ansible-collections/ansible.posix/issues/134).
|
||||||
|
- mount - Change behavior of ``boot`` option to set ``noauto`` on BSD nodes (https://github.com/ansible-collections/ansible.posix/issues/28).
|
||||||
|
- mount - Change behavior of ``boot`` option to set ``noauto`` on Linux nodes (https://github.com/ansible-collections/ansible.posix/issues/28).
|
||||||
|
- mount - add ``no_log=False`` in ``argument_spec`` to clear false-positives of ``no-log-needed`` (https://github.com/ansible-collections/ansible.posix/pull/156).
|
||||||
|
- mount - returns ``backup_file`` value when a backup fstab is created.
|
||||||
|
- synchronize - add ``delay_updates`` option (https://github.com/ansible-collections/ansible.posix/issues/157).
|
||||||
|
- synchronize - fix typo (https://github.com/ansible-collections/ansible.posix/pull/198).
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- Synchronize module not recognizing remote ssh key (https://github.com/ansible-collections/ansible.posix/issues/24).
|
||||||
|
- Synchronize not using quotes around arguments like --out-format (https://github.com/ansible-collections/ansible.posix/issues/190).
|
||||||
|
- at - append line-separator to the end of the ``command`` (https://github.com/ansible-collections/ansible.posix/issues/169).
|
||||||
|
- csh - define ``ECHO`` and ``COMMAND_SEP`` (https://github.com/ansible-collections/ansible.posix/issues/204).
|
||||||
|
- firewalld - enable integration after migration (https://github.com/ansible-collections/ansible.posix/pull/239).
|
||||||
|
- firewalld - ensure idempotency with firewalld 0.9.3 (https://github.com/ansible-collections/ansible.posix/issues/179).
|
||||||
|
- firewalld - fix setting zone target to ``%%REJECT%%`` (https://github.com/ansible-collections/ansible.posix/pull/215).
|
||||||
|
- mount - Handle ``boot`` option on Solaris correctly (https://github.com/ansible-collections/ansible.posix/issues/184).
|
||||||
|
- synchronize - add ``community.podman.podman`` to the list of supported connection plugins (https://github.com/ansible-community/molecule-podman/issues/45).
|
||||||
|
- synchronize - complete podman support for synchronize module.
|
||||||
|
- synchronize - properly quote rsync CLI parameters (https://github.com/ansible-collections/ansible.posix/pull/241).
|
||||||
|
- synchronize - replace removed ``ansible_ssh_user`` by ``ansible_user`` everywhere; do the same for ``ansible_ssh_port`` and ``ansible_ssh_host`` (https://github.com/ansible-collections/ansible.posix/issues/60).
|
||||||
|
- synchronize - use SSH args from SSH connection plugin (https://github.com/ansible-collections/ansible.posix/issues/222).
|
||||||
|
- synchronize - use become_user when invoking rsync on remote with sudo (https://github.com/ansible-collections/ansible.posix/issues/186).
|
||||||
|
- sysctl - modifying conditional check for docker to fix tests being skipped (https://github.com/ansible-collections/ansible.posix/pull/226).
|
||||||
|
|
||||||
|
v1.2.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.1.0.
|
||||||
|
|
||||||
|
Minor Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- firewalld - bring the ``target`` feature back (https://github.com/ansible-collections/ansible.posix/issues/112).
|
||||||
|
- fix sanity test for various modules.
|
||||||
|
- synchronize - add the ``ssh_connection_multiplexing`` option to allow SSH connection multiplexing (https://github.com/ansible/ansible/issues/24365).
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- at - add AIX support (https://github.com/ansible-collections/ansible.posix/pull/99).
|
||||||
|
- synchronize - add ``community.docker.docker`` to the list of supported transports (https://github.com/ansible-collections/ansible.posix/issues/132).
|
||||||
|
- synchronize - do not prepend PWD when path is in form user@server:path or server:path (https://github.com/ansible-collections/ansible.posix/pull/118).
|
||||||
|
- synchronize - fix for private_key overriding in synchronize module.
|
||||||
|
- sysctl - do not persist sysctl when value is invalid (https://github.com/ansible-collections/ansible.posix/pull/101).
|
||||||
|
|
||||||
v1.1.1
|
v1.1.1
|
||||||
======
|
======
|
||||||
|
|
||||||
|
|||||||
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.
|
||||||
22
README.md
22
README.md
@@ -1,16 +1,20 @@
|
|||||||
# ansible.posix
|
# ansible.posix
|
||||||
<!-- Add CI and code coverage badges here. Samples included below. -->
|
<!-- Add CI and code coverage badges here. Samples included below. -->
|
||||||
|
[](https://dev.azure.com/ansible/ansible.posix/_build?definitionId=26)
|
||||||
[]() <!--[](https://codecov.io/gh/ansible-collections/ansible.posix)-->
|
[]() <!--[](https://codecov.io/gh/ansible-collections/ansible.posix)-->
|
||||||
|
|
||||||
<!-- Describe the collection and why a user would want to use it. What does the collection do? -->
|
<!-- Describe the collection and why a user would want to use it. What does the collection do? -->
|
||||||
An Ansible Collection of modules and plugins that target POSIX UNIX/Linux and derivative Operating Systems.
|
An Ansible Collection of modules and plugins that target POSIX UNIX/Linux and derivative Operating Systems.
|
||||||
|
|
||||||
## Supported Versions of Ansible
|
## Supported Versions of Ansible
|
||||||
<!--start requires_ansible-->
|
<!--start requires_ansible-->
|
||||||
## Ansible version compatibility
|
## Ansible version compatibility
|
||||||
|
|
||||||
This collection has been tested against following Ansible versions: **>=2.9,<2.11**.
|
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.
|
||||||
@@ -26,6 +30,7 @@ Name | Description
|
|||||||
[ansible.posix.at](https://github.com/ansible-collections/ansible.posix/blob/main/docs/ansible.posix.at_module.rst)|Schedule the execution of a command or script file via the at command
|
[ansible.posix.at](https://github.com/ansible-collections/ansible.posix/blob/main/docs/ansible.posix.at_module.rst)|Schedule the execution of a command or script file via the at command
|
||||||
[ansible.posix.authorized_key](https://github.com/ansible-collections/ansible.posix/blob/main/docs/ansible.posix.authorized_key_module.rst)|Adds or removes an SSH authorized key
|
[ansible.posix.authorized_key](https://github.com/ansible-collections/ansible.posix/blob/main/docs/ansible.posix.authorized_key_module.rst)|Adds or removes an SSH authorized key
|
||||||
[ansible.posix.firewalld](https://github.com/ansible-collections/ansible.posix/blob/main/docs/ansible.posix.firewalld_module.rst)|Manage arbitrary ports/services with firewalld
|
[ansible.posix.firewalld](https://github.com/ansible-collections/ansible.posix/blob/main/docs/ansible.posix.firewalld_module.rst)|Manage arbitrary ports/services with firewalld
|
||||||
|
[ansible.posix.firewalld_info](https://github.com/ansible-collections/ansible.posix/blob/main/docs/ansible.posix.firewalld_info_module.rst)|Gather information about firewalld
|
||||||
[ansible.posix.mount](https://github.com/ansible-collections/ansible.posix/blob/main/docs/ansible.posix.mount_module.rst)|Control active and configured mount points
|
[ansible.posix.mount](https://github.com/ansible-collections/ansible.posix/blob/main/docs/ansible.posix.mount_module.rst)|Control active and configured mount points
|
||||||
[ansible.posix.patch](https://github.com/ansible-collections/ansible.posix/blob/main/docs/ansible.posix.patch_module.rst)|Apply patch files using the GNU patch tool
|
[ansible.posix.patch](https://github.com/ansible-collections/ansible.posix/blob/main/docs/ansible.posix.patch_module.rst)|Apply patch files using the GNU patch tool
|
||||||
[ansible.posix.seboolean](https://github.com/ansible-collections/ansible.posix/blob/main/docs/ansible.posix.seboolean_module.rst)|Toggles SELinux booleans
|
[ansible.posix.seboolean](https://github.com/ansible-collections/ansible.posix/blob/main/docs/ansible.posix.seboolean_module.rst)|Toggles SELinux booleans
|
||||||
@@ -73,9 +78,7 @@ This collection follows the Ansible project's
|
|||||||
Please read and familiarize yourself with this document.
|
Please read and familiarize yourself with this document.
|
||||||
|
|
||||||
## Release notes
|
## Release notes
|
||||||
|
See [changelog](https://github.com/ansible-collections/ansible.posix/blob/main/CHANGELOG.rst) for more details.
|
||||||
* 0.1.1 Initial stable build
|
|
||||||
* 0.1.0 Internal only build
|
|
||||||
|
|
||||||
## External requirements
|
## External requirements
|
||||||
|
|
||||||
@@ -85,9 +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-base 2.11 (devel)
|
- ansible-core 2.14 (devel)
|
||||||
* ansible-base 2.10 (Beta)
|
- ansible-core 2.13 (stable)
|
||||||
* ansible-base 2.9 (stable)
|
- ansible-core 2.12 (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]
|
||||||
@@ -103,3 +103,160 @@ releases:
|
|||||||
- 74_synchronize_docker.yml
|
- 74_synchronize_docker.yml
|
||||||
- skippy_deprecation.yml
|
- skippy_deprecation.yml
|
||||||
release_date: '2020-09-02'
|
release_date: '2020-09-02'
|
||||||
|
1.2.0:
|
||||||
|
changes:
|
||||||
|
bugfixes:
|
||||||
|
- at - add AIX support (https://github.com/ansible-collections/ansible.posix/pull/99).
|
||||||
|
- synchronize - add ``community.docker.docker`` to the list of supported transports
|
||||||
|
(https://github.com/ansible-collections/ansible.posix/issues/132).
|
||||||
|
- synchronize - do not prepend PWD when path is in form user@server:path or
|
||||||
|
server:path (https://github.com/ansible-collections/ansible.posix/pull/118).
|
||||||
|
- synchronize - fix for private_key overriding in synchronize module.
|
||||||
|
- sysctl - do not persist sysctl when value is invalid (https://github.com/ansible-collections/ansible.posix/pull/101).
|
||||||
|
minor_changes:
|
||||||
|
- firewalld - bring the ``target`` feature back (https://github.com/ansible-collections/ansible.posix/issues/112).
|
||||||
|
- fix sanity test for various modules.
|
||||||
|
- synchronize - add the ``ssh_connection_multiplexing`` option to allow SSH
|
||||||
|
connection multiplexing (https://github.com/ansible/ansible/issues/24365).
|
||||||
|
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.1.0.'
|
||||||
|
fragments:
|
||||||
|
- 1.2.0.yml
|
||||||
|
- 101-sysctl-dont-persist-when-invalid.yml
|
||||||
|
- 118-synchronize_bugfix.yml
|
||||||
|
- 120-synchronize_add_option.yml
|
||||||
|
- 144_add_community_docker_connection_plugin_alias.yml
|
||||||
|
- 82-private-key-override-fix.yml
|
||||||
|
- 99-at_add_aix_support.yml
|
||||||
|
- firewalld_zone_target.yml
|
||||||
|
- misc_fix.yml
|
||||||
|
release_date: '2021-03-08'
|
||||||
|
1.3.0:
|
||||||
|
changes:
|
||||||
|
bugfixes:
|
||||||
|
- Synchronize module not recognizing remote ssh key (https://github.com/ansible-collections/ansible.posix/issues/24).
|
||||||
|
- Synchronize not using quotes around arguments like --out-format (https://github.com/ansible-collections/ansible.posix/issues/190).
|
||||||
|
- at - append line-separator to the end of the ``command`` (https://github.com/ansible-collections/ansible.posix/issues/169).
|
||||||
|
- csh - define ``ECHO`` and ``COMMAND_SEP`` (https://github.com/ansible-collections/ansible.posix/issues/204).
|
||||||
|
- firewalld - enable integration after migration (https://github.com/ansible-collections/ansible.posix/pull/239).
|
||||||
|
- firewalld - ensure idempotency with firewalld 0.9.3 (https://github.com/ansible-collections/ansible.posix/issues/179).
|
||||||
|
- firewalld - fix setting zone target to ``%%REJECT%%`` (https://github.com/ansible-collections/ansible.posix/pull/215).
|
||||||
|
- mount - Handle ``boot`` option on Solaris correctly (https://github.com/ansible-collections/ansible.posix/issues/184).
|
||||||
|
- synchronize - add ``community.podman.podman`` to the list of supported connection
|
||||||
|
plugins (https://github.com/ansible-community/molecule-podman/issues/45).
|
||||||
|
- synchronize - complete podman support for synchronize module.
|
||||||
|
- synchronize - properly quote rsync CLI parameters (https://github.com/ansible-collections/ansible.posix/pull/241).
|
||||||
|
- synchronize - replace removed ``ansible_ssh_user`` by ``ansible_user`` everywhere;
|
||||||
|
do the same for ``ansible_ssh_port`` and ``ansible_ssh_host`` (https://github.com/ansible-collections/ansible.posix/issues/60).
|
||||||
|
- synchronize - use SSH args from SSH connection plugin (https://github.com/ansible-collections/ansible.posix/issues/222).
|
||||||
|
- synchronize - use become_user when invoking rsync on remote with sudo (https://github.com/ansible-collections/ansible.posix/issues/186).
|
||||||
|
- sysctl - modifying conditional check for docker to fix tests being skipped
|
||||||
|
(https://github.com/ansible-collections/ansible.posix/pull/226).
|
||||||
|
minor_changes:
|
||||||
|
- acl - add new alias ``recurse`` for ``recursive`` parameter (https://github.com/ansible-collections/ansible.posix/issues/124).
|
||||||
|
- added 2.11 branch to test matrix, added ignore-2.12.txt.
|
||||||
|
- authorized_key - add ``no_log=False`` in ``argument_spec`` to clear false-positives
|
||||||
|
of ``no-log-needed`` (https://github.com/ansible-collections/ansible.posix/pull/156).
|
||||||
|
- authorized_key - add a list of valid key types (https://github.com/ansible-collections/ansible.posix/issues/134).
|
||||||
|
- mount - Change behavior of ``boot`` option to set ``noauto`` on BSD nodes
|
||||||
|
(https://github.com/ansible-collections/ansible.posix/issues/28).
|
||||||
|
- mount - Change behavior of ``boot`` option to set ``noauto`` on Linux nodes
|
||||||
|
(https://github.com/ansible-collections/ansible.posix/issues/28).
|
||||||
|
- mount - add ``no_log=False`` in ``argument_spec`` to clear false-positives
|
||||||
|
of ``no-log-needed`` (https://github.com/ansible-collections/ansible.posix/pull/156).
|
||||||
|
- mount - returns ``backup_file`` value when a backup fstab is created.
|
||||||
|
- synchronize - add ``delay_updates`` option (https://github.com/ansible-collections/ansible.posix/issues/157).
|
||||||
|
- synchronize - fix typo (https://github.com/ansible-collections/ansible.posix/pull/198).
|
||||||
|
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.2.0.'
|
||||||
|
fragments:
|
||||||
|
- 1.3.0.yml
|
||||||
|
- 124_acl.yml
|
||||||
|
- 126_mount_not_returning_backup_file.yml
|
||||||
|
- 134_authorized_key.yml
|
||||||
|
- 156-fix_no-log-needed_false_positives.yml
|
||||||
|
- 159-fix-60-deprecated-ansible_ssh_user.yml
|
||||||
|
- 167-synchronize-add_delay_option.yml
|
||||||
|
- 169_add_lineseparator_to_command.yml
|
||||||
|
- 175_synchronize.yml
|
||||||
|
- 179_firewalld.yml
|
||||||
|
- 181-update_codecov_sh_url.yml
|
||||||
|
- 185_mount_at_boot.yml
|
||||||
|
- 187-fix-synchronize-become-user.yml
|
||||||
|
- 193_firewalld.yml
|
||||||
|
- 196_boot_opt_for_linux.yml
|
||||||
|
- 203_boot_opt_for_bsd.yml
|
||||||
|
- 204_csh_shell.yml
|
||||||
|
- 207-mount_tests.yml
|
||||||
|
- 213_quote_cmd_args.yml
|
||||||
|
- 214-add_firewalld_info_module.yml
|
||||||
|
- 215_fix_REJECT_target_name.yml
|
||||||
|
- 217-restructure_authrized_key_test.yml
|
||||||
|
- 222_synchronize.yml
|
||||||
|
- 226_sysctl_fix_integration_test.yml
|
||||||
|
- 229_add_podman_connection_plugin_to_synchronize.yml
|
||||||
|
- 230_complete_podman_support_for_synchronize.yml
|
||||||
|
- 233-fix-wrong-firewalld-version-info.yml
|
||||||
|
- 241-synchronize-shell-quoting.yml
|
||||||
|
- firewalld_integ_test.yml
|
||||||
|
- firewalld_test.yml
|
||||||
|
- sanity_test_ignore_file.yml
|
||||||
|
- synchronize.yml
|
||||||
|
- test_matrix.yml
|
||||||
|
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'
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ changelog_filename_template: ../CHANGELOG.rst
|
|||||||
changelog_filename_version_depth: 0
|
changelog_filename_version_depth: 0
|
||||||
changes_file: changelog.yaml
|
changes_file: changelog.yaml
|
||||||
changes_format: combined
|
changes_format: combined
|
||||||
keep_fragments: true
|
keep_fragments: false
|
||||||
mention_ancestor: true
|
mention_ancestor: true
|
||||||
new_plugins_after_name: removed_features
|
new_plugins_after_name: removed_features
|
||||||
notesdir: fragments
|
notesdir: fragments
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
bugfixes:
|
|
||||||
- patch - fix FQCN usage for action plugin (https://github.com/ansible-collections/ansible.posix/issues/11)
|
|
||||||
- synchronize - fix FQCN usage for action plugin (https://github.com/ansible-collections/ansible.posix/issues/11)
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
minor_changes:
|
|
||||||
- Migrate hacking/cgroup_perf_recap_graph.py to this collection, since the cgroup_perf_recap callback lives here.
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
bugfixes:
|
|
||||||
- Mount - Handle remount with new options (https://github.com/ansible/ansible/issues/59460).
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
bugfixes:
|
|
||||||
- Profile_tasks - result was a odict_items which is not subscriptable, so the slicing was failing (https://github.com/ansible/ansible/issues/59059).
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
---
|
|
||||||
bugfixes:
|
|
||||||
- authorized_keys - Added FIDO2 security keys (https://github.com/ansible-collections/ansible.posix/issues/17).
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
minor_changes:
|
|
||||||
- Enabled tags in galaxy.yml (https://github.com/ansible-collections/ansible.posix/issues/18).
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
---
|
|
||||||
bugfixes:
|
|
||||||
- mount - fix issues with ismount module_util pathing for Ansible 2.9 (fixes https://github.com/ansible-collections/ansible.posix/issues/21)
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
---
|
|
||||||
bugfixes:
|
|
||||||
- selinux - add missing configuration keys for /etc/selinux/config (https://github.com/ansible-collections/ansible.posix/issues/23)
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
minor_changes:
|
|
||||||
- Removed ANSIBLE_METADATA from all the modules.
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
bugfixes:
|
|
||||||
- Typecast results before use in profile_tasks callback (https://github.com/ansible/ansible/issues/69563).
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
minor_changes:
|
|
||||||
- Update EXAMPLES section in modules to use FQCN.
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
bugfixes:
|
|
||||||
- Revert "mount - Check if src exists before mounted (ansible/ansible#61752)".
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
minor_changes:
|
|
||||||
- Revert "Enable at, patch and synchronize tests (https://github.com/ansible-collections/ansible.posix/pull/5)".
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
trivial:
|
||||||
|
- Update version number in galaxy.yml to 1.5.0.
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
---
|
|
||||||
bugfixes:
|
|
||||||
- authorized_keys - fix inconsistent return value for check mode (https://github.com/ansible-collections/ansible.posix/issues/37)
|
|
||||||
@@ -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,2 +0,0 @@
|
|||||||
minor_changes:
|
|
||||||
- Remove license key from galaxy.yml.
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
minor_changes:
|
|
||||||
- Remove sanity jobs from shippable (https://github.com/ansible-collections/ansible.posix/pull/43).
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
minor_changes:
|
|
||||||
- Update README.md (https://github.com/ansible-collections/ansible.posix/pull/4/).
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
minor_changes:
|
|
||||||
- Enable tests for at, patch and synchronize modules (https://github.com/ansible-collections/ansible.posix/pull/5).
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
bugfixes:
|
|
||||||
- json callback - Fix host result to task references in the resultant JSON
|
|
||||||
output for non-lockstep strategy plugins such as free
|
|
||||||
(https://github.com/ansible/ansible/issues/65931)
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
minor_changes:
|
|
||||||
- CI should use devel (https://github.com/ansible-collections/ansible.posix/pull/6).
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
bugfixes:
|
|
||||||
- Fix synchronize to work with renamed docker and buildah connection plugins.
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
bugfixes:
|
|
||||||
- Allow unsetting existing environment vars via environment by specifying a null value (https://github.com/ansible/ansible/pull/68236).
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
---
|
|
||||||
minor_changes:
|
|
||||||
- firewalld - add firewalld module to ansible.posix collection
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
major_changes:
|
|
||||||
- Bootstrap Collection (https://github.com/ansible-collections/ansible.posix/pull/1).
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
---
|
|
||||||
minor_changes:
|
|
||||||
- skippy - fixed the deprecation warning (by date) for skippy callback plugin
|
|
||||||
1
codecov.yml
Normal file
1
codecov.yml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
comment: false
|
||||||
@@ -59,7 +59,7 @@ Parameters
|
|||||||
<b>entity</b>
|
<b>entity</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">-</span>
|
<span style="color: purple">string</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -74,7 +74,7 @@ Parameters
|
|||||||
<b>entry</b>
|
<b>entry</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">-</span>
|
<span style="color: purple">string</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -94,7 +94,7 @@ Parameters
|
|||||||
<b>etype</b>
|
<b>etype</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">-</span>
|
<span style="color: purple">string</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -151,13 +151,14 @@ Parameters
|
|||||||
<b>permissions</b>
|
<b>permissions</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">-</span>
|
<span style="color: purple">string</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>The permissions to apply/remove can be any combination of <code>r</code>, <code>w</code> and <code>x</code> (read, write and execute respectively)</div>
|
<div>The permissions to apply/remove can be any combination of <code>r</code>, <code>w</code>, <code>x</code></div>
|
||||||
|
<div>(read, write and execute respectively), and <code>X</code> (execute permission if the file is a directory or already has execute permission for some user)</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -166,7 +167,7 @@ Parameters
|
|||||||
<b>recalculate_mask</b>
|
<b>recalculate_mask</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">-</span>
|
<span style="color: purple">string</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -200,6 +201,8 @@ Parameters
|
|||||||
<td>
|
<td>
|
||||||
<div>Recursively sets the specified ACL.</div>
|
<div>Recursively sets the specified ACL.</div>
|
||||||
<div>Incompatible with <code>state=query</code>.</div>
|
<div>Incompatible with <code>state=query</code>.</div>
|
||||||
|
<div>Alias <code>recurse</code> added in version 1.3.0.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: recurse</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -208,7 +211,7 @@ Parameters
|
|||||||
<b>state</b>
|
<b>state</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">-</span>
|
<span style="color: purple">string</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -259,7 +262,7 @@ Notes
|
|||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
|
|
||||||
.. code-block:: yaml+jinja
|
.. code-block:: yaml
|
||||||
|
|
||||||
- name: Grant user Joe read access to a file
|
- name: Grant user Joe read access to a file
|
||||||
ansible.posix.acl:
|
ansible.posix.acl:
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ Parameters
|
|||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">integer</span>
|
<span style="color: purple">integer</span>
|
||||||
/ <span style="color: red">required</span>
|
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -131,7 +130,6 @@ Parameters
|
|||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">string</span>
|
<span style="color: purple">string</span>
|
||||||
/ <span style="color: red">required</span>
|
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -155,7 +153,7 @@ Parameters
|
|||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
|
|
||||||
.. code-block:: yaml+jinja
|
.. code-block:: yaml
|
||||||
|
|
||||||
- name: Schedule a command to execute in 20 minutes as root
|
- name: Schedule a command to execute in 20 minutes as root
|
||||||
ansible.posix.at:
|
ansible.posix.at:
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ Parameters
|
|||||||
<b>key_options</b>
|
<b>key_options</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">-</span>
|
<span style="color: purple">string</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -226,7 +226,7 @@ Parameters
|
|||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
|
|
||||||
.. code-block:: yaml+jinja
|
.. code-block:: yaml
|
||||||
|
|
||||||
- name: Set authorized key taken from file
|
- name: Set authorized key taken from file
|
||||||
ansible.posix.authorized_key:
|
ansible.posix.authorized_key:
|
||||||
@@ -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
|
||||||
|
|||||||
520
docs/ansible.posix.firewalld_info_module.rst
Normal file
520
docs/ansible.posix.firewalld_info_module.rst
Normal file
@@ -0,0 +1,520 @@
|
|||||||
|
.. _ansible.posix.firewalld_info_module:
|
||||||
|
|
||||||
|
|
||||||
|
****************************
|
||||||
|
ansible.posix.firewalld_info
|
||||||
|
****************************
|
||||||
|
|
||||||
|
**Gather information about firewalld**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
:local:
|
||||||
|
:depth: 1
|
||||||
|
|
||||||
|
|
||||||
|
Synopsis
|
||||||
|
--------
|
||||||
|
- This module gathers information about firewalld rules.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
------------
|
||||||
|
The below requirements are needed on the host that executes this module.
|
||||||
|
|
||||||
|
- firewalld >= 0.2.11
|
||||||
|
- python-firewall
|
||||||
|
- python-dbus
|
||||||
|
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<table border=0 cellpadding=0 class="documentation-table">
|
||||||
|
<tr>
|
||||||
|
<th colspan="1">Parameter</th>
|
||||||
|
<th>Choices/<font color="blue">Defaults</font></th>
|
||||||
|
<th width="100%">Comments</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>active_zones</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</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>Gather information about active zones.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>zones</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Gather information about specific zones.</div>
|
||||||
|
<div>If only works if <code>active_zones</code> is set to <code>false</code>.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
- name: Gather information about active zones
|
||||||
|
ansible.posix.firewalld_info:
|
||||||
|
active_zones: yes
|
||||||
|
|
||||||
|
- name: Gather information about specific zones
|
||||||
|
ansible.posix.firewalld_info:
|
||||||
|
zones:
|
||||||
|
- public
|
||||||
|
- external
|
||||||
|
- internal
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Return Values
|
||||||
|
-------------
|
||||||
|
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<table border=0 cellpadding=0 class="documentation-table">
|
||||||
|
<tr>
|
||||||
|
<th colspan="4">Key</th>
|
||||||
|
<th>Returned</th>
|
||||||
|
<th width="100%">Description</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="4">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>active_zones</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>Gather active zones only if turn it <code>true</code>.</div>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="4">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>collected_zones</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>A list of collected zones.</div>
|
||||||
|
<br/>
|
||||||
|
<div style="font-size: smaller"><b>Sample:</b></div>
|
||||||
|
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">['external', 'internal']</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="4">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>firewalld_info</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">complex</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>Returns various information about firewalld configuration.</div>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="3">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>default_zones</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>The zone name of default zone.</div>
|
||||||
|
<br/>
|
||||||
|
<div style="font-size: smaller"><b>Sample:</b></div>
|
||||||
|
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">public</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="3">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>version</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>The version information of firewalld.</div>
|
||||||
|
<br/>
|
||||||
|
<div style="font-size: smaller"><b>Sample:</b></div>
|
||||||
|
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">0.8.2</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="3">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>zones</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">complex</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>A dict of zones to gather information.</div>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>zone</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">complex</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>The zone name registered in firewalld.</div>
|
||||||
|
<br/>
|
||||||
|
<div style="font-size: smaller"><b>Sample:</b></div>
|
||||||
|
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">external</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>forward</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>The network interface forwarding.</div>
|
||||||
|
<div>This parameter supports on python-firewall 0.9.0(or later) and is not collected in earlier versions.</div>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>forward_ports</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>A list of forwarding port pair with protocol.</div>
|
||||||
|
<br/>
|
||||||
|
<div style="font-size: smaller"><b>Sample:</b></div>
|
||||||
|
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">['icmp', 'ipv6-icmp']</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>icmp_block_inversion</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>The ICMP block inversion to block all ICMP requests.</div>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>icmp_blocks</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>A list of blocking icmp protocol.</div>
|
||||||
|
<br/>
|
||||||
|
<div style="font-size: smaller"><b>Sample:</b></div>
|
||||||
|
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">['echo-request']</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>interfaces</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>A list of network interfaces.</div>
|
||||||
|
<br/>
|
||||||
|
<div style="font-size: smaller"><b>Sample:</b></div>
|
||||||
|
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">['eth0', 'eth1']</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>masquerade</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>The network interface masquerading.</div>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>ports</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>A list of network port with protocol.</div>
|
||||||
|
<br/>
|
||||||
|
<div style="font-size: smaller"><b>Sample:</b></div>
|
||||||
|
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">[['22', 'tcp'], ['80', 'tcp']]</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>protocols</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>A list of network protocol.</div>
|
||||||
|
<br/>
|
||||||
|
<div style="font-size: smaller"><b>Sample:</b></div>
|
||||||
|
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">['icmp', 'ipv6-icmp']</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>rich_rules</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>A list of rich language rule.</div>
|
||||||
|
<br/>
|
||||||
|
<div style="font-size: smaller"><b>Sample:</b></div>
|
||||||
|
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">['rule protocol value="icmp" reject', 'rule priority="32767" reject']</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>services</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>A list of network services.</div>
|
||||||
|
<br/>
|
||||||
|
<div style="font-size: smaller"><b>Sample:</b></div>
|
||||||
|
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">['dhcp', 'dns', 'ssh']</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>source_ports</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>A list of network source port with protocol.</div>
|
||||||
|
<br/>
|
||||||
|
<div style="font-size: smaller"><b>Sample:</b></div>
|
||||||
|
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">[['30000', 'tcp'], ['30001', 'tcp']]</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>sources</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>A list of source network address.</div>
|
||||||
|
<br/>
|
||||||
|
<div style="font-size: smaller"><b>Sample:</b></div>
|
||||||
|
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">['172.16.30.0/24', '172.16.31.0/24']</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>target</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>A list of services in the zone.</div>
|
||||||
|
<br/>
|
||||||
|
<div style="font-size: smaller"><b>Sample:</b></div>
|
||||||
|
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">ACCEPT</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="4">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>undefined_zones</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>A list of undefined zones in <code>zones</code> option.</div>
|
||||||
|
<div><code>undefined_zones</code> will be ignored for gathering process.</div>
|
||||||
|
<br/>
|
||||||
|
<div style="font-size: smaller"><b>Sample:</b></div>
|
||||||
|
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">['foo', 'bar']</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<br/><br/>
|
||||||
|
|
||||||
|
|
||||||
|
Status
|
||||||
|
------
|
||||||
|
|
||||||
|
|
||||||
|
Authors
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
- Hideki Saito (@saito-hideki)
|
||||||
@@ -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
|
||||||
@@ -34,12 +35,12 @@ Parameters
|
|||||||
|
|
||||||
<table border=0 cellpadding=0 class="documentation-table">
|
<table border=0 cellpadding=0 class="documentation-table">
|
||||||
<tr>
|
<tr>
|
||||||
<th colspan="1">Parameter</th>
|
<th colspan="2">Parameter</th>
|
||||||
<th>Choices/<font color="blue">Defaults</font></th>
|
<th>Choices/<font color="blue">Defaults</font></th>
|
||||||
<th width="100%">Comments</th>
|
<th width="100%">Comments</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>icmp_block</b>
|
<b>icmp_block</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -54,7 +55,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>icmp_block_inversion</b>
|
<b>icmp_block_inversion</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -69,7 +70,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>immediate</b>
|
<b>immediate</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -88,7 +89,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>interface</b>
|
<b>interface</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -103,7 +104,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>masquerade</b>
|
<b>masquerade</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -118,7 +119,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>offline</b>
|
<b>offline</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -137,7 +138,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>permanent</b>
|
<b>permanent</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -153,12 +154,12 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Should this configuration be in the running firewalld configuration or persist across reboots.</div>
|
<div>Should this configuration be in the running firewalld configuration or persist across reboots.</div>
|
||||||
<div>As of Ansible 2.3, permanent operations can operate on firewalld configs when it is not running (requires firewalld >= 3.0.9).</div>
|
<div>As of Ansible 2.3, permanent operations can operate on firewalld configs when it is not running (requires firewalld >= 0.3.9).</div>
|
||||||
<div>Note that if this is <code>no</code>, immediate is assumed <code>yes</code>.</div>
|
<div>Note that if this is <code>no</code>, immediate is assumed <code>yes</code>.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>port</b>
|
<b>port</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -174,7 +175,95 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>port_forward</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=dictionary</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Port and protocol to forward using firewalld.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
<td colspan="1">
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>port</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
/ <span style="color: red">required</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Source port to forward from</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>proto</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
/ <span style="color: red">required</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li>udp</li>
|
||||||
|
<li>tcp</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>protocol to forward</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>toaddr</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Optional address to forward to</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>toport</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
/ <span style="color: red">required</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>destination port</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>rich_rule</b>
|
<b>rich_rule</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -190,7 +279,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>service</b>
|
<b>service</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -206,7 +295,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>source</b>
|
<b>source</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -221,7 +310,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>state</b>
|
<b>state</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -245,7 +334,30 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>target</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 1.2.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li>default</li>
|
||||||
|
<li>ACCEPT</li>
|
||||||
|
<li>DROP</li>
|
||||||
|
<li>%%REJECT%%</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>firewalld Zone target</div>
|
||||||
|
<div>If state is set to <code>absent</code>, this will reset the target to default</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>timeout</b>
|
<b>timeout</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -257,11 +369,11 @@ Parameters
|
|||||||
<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>The amount of time the rule should be in effect for when non-permanent.</div>
|
<div>The amount of time in seconds the rule should be in effect for when non-permanent.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>zone</b>
|
<b>zone</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -290,13 +402,14 @@ 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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
|
|
||||||
.. code-block:: yaml+jinja
|
.. code-block:: yaml
|
||||||
|
|
||||||
- name: permit traffic in default zone for https service
|
- name: permit traffic in default zone for https service
|
||||||
ansible.posix.firewalld:
|
ansible.posix.firewalld:
|
||||||
@@ -360,6 +473,12 @@ Examples
|
|||||||
permanent: yes
|
permanent: yes
|
||||||
icmp_block: echo-request
|
icmp_block: echo-request
|
||||||
|
|
||||||
|
- ansible.posix.firewalld:
|
||||||
|
zone: internal
|
||||||
|
state: present
|
||||||
|
permanent: yes
|
||||||
|
target: ACCEPT
|
||||||
|
|
||||||
- name: Redirect port 443 to 8443 with Rich Rule
|
- name: Redirect port 443 to 8443 with Rich Rule
|
||||||
ansible.posix.firewalld:
|
ansible.posix.firewalld:
|
||||||
rich_rule: rule family=ipv4 forward-port port=443 protocol=tcp to-port=8443
|
rich_rule: rule family=ipv4 forward-port port=443 protocol=tcp to-port=8443
|
||||||
|
|||||||
@@ -69,7 +69,10 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Determines if the filesystem should be mounted on boot.</div>
|
<div>Determines if the filesystem should be mounted on boot.</div>
|
||||||
<div>Only applies to Solaris systems.</div>
|
<div>Only applies to Solaris and Linux systems.</div>
|
||||||
|
<div>For Solaris systems, <code>true</code> will set <code>yes</code> as the value of mount at boot in <em>/etc/vfstab</em>.</div>
|
||||||
|
<div>For Linux, FreeBSD, NetBSD and OpenBSD systems, <code>false</code> will add <code>noauto</code> to mount options in <em>/etc/fstab</em>.</div>
|
||||||
|
<div>To avoid mount option conflicts, if <code>noauto</code> specified in <code>opts</code>, mount module will ignore <code>boot</code>.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -82,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>
|
||||||
@@ -150,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>
|
||||||
@@ -235,7 +238,7 @@ Notes
|
|||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
|
|
||||||
.. code-block:: yaml+jinja
|
.. code-block:: yaml
|
||||||
|
|
||||||
# Before 2.3, option 'name' was used instead of 'path'
|
# Before 2.3, option 'name' was used instead of 'path'
|
||||||
- name: Mount DVD read-only
|
- name: Mount DVD read-only
|
||||||
@@ -292,7 +295,16 @@ 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
|
||||||
|
fstype: nfs
|
||||||
|
|
||||||
|
- name: Mount NFS volumes with noauto according to boot option
|
||||||
|
ansible.posix.mount:
|
||||||
|
src: 192.168.1.100:/nfs/ssd/shared_data
|
||||||
|
path: /mnt/shared_data
|
||||||
|
opts: rw,sync,hard
|
||||||
|
boot: no
|
||||||
state: mounted
|
state: mounted
|
||||||
fstype: nfs
|
fstype: nfs
|
||||||
|
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ Notes
|
|||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
|
|
||||||
.. code-block:: yaml+jinja
|
.. code-block:: yaml
|
||||||
|
|
||||||
- name: Apply patch to one file
|
- name: Apply patch to one file
|
||||||
ansible.posix.patch:
|
ansible.posix.patch:
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -65,7 +66,7 @@ Parameters
|
|||||||
<b>name</b>
|
<b>name</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">-</span>
|
<span style="color: purple">string</span>
|
||||||
/ <span style="color: red">required</span>
|
/ <span style="color: red">required</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
@@ -129,7 +130,7 @@ Notes
|
|||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
|
|
||||||
.. code-block:: yaml+jinja
|
.. code-block:: yaml
|
||||||
|
|
||||||
- name: Set httpd_can_network_connect flag on and keep it persistent across reboots
|
- name: Set httpd_can_network_connect flag on and keep it persistent across reboots
|
||||||
ansible.posix.seboolean:
|
ansible.posix.seboolean:
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ Parameters
|
|||||||
<b>configfile</b>
|
<b>configfile</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">-</span>
|
<span style="color: purple">string</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -64,13 +64,13 @@ Parameters
|
|||||||
<b>policy</b>
|
<b>policy</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">-</span>
|
<span style="color: purple">string</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>The name of the SELinux policy to use (e.g. <code>targeted</code>) will be required if state is not <code>disabled</code>.</div>
|
<div>The name of the SELinux policy to use (e.g. <code>targeted</code>) will be required if <em>state</em> is not <code>disabled</code>.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -79,7 +79,7 @@ Parameters
|
|||||||
<b>state</b>
|
<b>state</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">-</span>
|
<span style="color: purple">string</span>
|
||||||
/ <span style="color: red">required</span>
|
/ <span style="color: red">required</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
@@ -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/>
|
||||||
|
|
||||||
@@ -103,7 +124,7 @@ Parameters
|
|||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
|
|
||||||
.. code-block:: yaml+jinja
|
.. code-block:: yaml
|
||||||
|
|
||||||
- name: Enable SELinux
|
- name: Enable SELinux
|
||||||
ansible.posix.selinux:
|
ansible.posix.selinux:
|
||||||
|
|||||||
@@ -113,6 +113,26 @@ Parameters
|
|||||||
<div>Copy symlinks as the item that they point to (the referent) is copied, rather than the symlink.</div>
|
<div>Copy symlinks as the item that they point to (the referent) is copied, rather than the symlink.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>delay_updates</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.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li>no</li>
|
||||||
|
<li><div style="color: blue"><b>yes</b> ←</div></li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>This option puts the temporary file from each updated file into a holding directory until the end of the transfer, at which time all the files are renamed into place in rapid succession.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="1">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -129,9 +149,9 @@ Parameters
|
|||||||
</ul>
|
</ul>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Delete files in <code>dest</code> that don't exist (after transfer, not before) in the <code>src</code> path.</div>
|
<div>Delete files in <em>dest</em> that do not exist (after transfer, not before) in the <em>src</em> path.</div>
|
||||||
<div>This option requires <code>recursive=yes</code>.</div>
|
<div>This option requires <em>recursive=yes</em>.</div>
|
||||||
<div>This option ignores excluded files and behaves like the rsync opt --delete-excluded.</div>
|
<div>This option ignores excluded files and behaves like the rsync opt <code>--delete-after</code>.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -165,7 +185,7 @@ Parameters
|
|||||||
<td>
|
<td>
|
||||||
<div>Port number for ssh on the destination host.</div>
|
<div>Port number for ssh on the destination host.</div>
|
||||||
<div>Prior to Ansible 2.0, the ansible_ssh_port inventory var took precedence over this value.</div>
|
<div>Prior to Ansible 2.0, the ansible_ssh_port inventory var took precedence over this value.</div>
|
||||||
<div>This parameter defaults to the value of <code>ansible_ssh_port</code> or <code>ansible_port</code>, the <code>remote_port</code> config setting or the value from ssh client configuration if none of the former have been set.</div>
|
<div>This parameter defaults to the value of <code>ansible_port</code>, the <code>remote_port</code> config setting or the value from ssh client configuration if none of the former have been set.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -233,6 +253,7 @@ Parameters
|
|||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">list</span>
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -384,6 +405,7 @@ Parameters
|
|||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">list</span>
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -463,6 +485,27 @@ Parameters
|
|||||||
<div>The path can be absolute or relative.</div>
|
<div>The path can be absolute or relative.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>ssh_connection_multiplexing</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</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>SSH connection multiplexing for rsync is disabled by default to prevent misconfigured ControlSockets from resulting in failed SSH connections. This is accomplished by setting the SSH <code>ControlSocket</code> to <code>none</code>.</div>
|
||||||
|
<div>Set this option to <code>yes</code> to allow multiplexing and reduce SSH connection overhead.</div>
|
||||||
|
<div>Note that simply setting this option to <code>yes</code> is not enough; You must also configure SSH connection multiplexing in your SSH client config by setting values for <code>ControlMaster</code>, <code>ControlPersist</code> and <code>ControlPath</code>.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="1">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -499,7 +542,8 @@ Parameters
|
|||||||
</ul>
|
</ul>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Use the ssh_args specified in ansible.cfg.</div>
|
<div>In Ansible 2.10 and lower, it uses the ssh_args specified in <code>ansible.cfg</code>.</div>
|
||||||
|
<div>In Ansible 2.11 and onwards, when set to <code>true</code>, it uses all SSH connection configurations like <code>ansible_ssh_args</code>, <code>ansible_ssh_common_args</code>, and <code>ansible_ssh_extra_args</code>.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -542,7 +586,7 @@ Notes
|
|||||||
- Inspect the verbose output to validate the destination user/host/path are what was expected.
|
- Inspect the verbose output to validate the destination user/host/path are what was expected.
|
||||||
- To exclude files and directories from being synchronized, you may add ``.rsync-filter`` files to the source directory.
|
- To exclude files and directories from being synchronized, you may add ``.rsync-filter`` files to the source directory.
|
||||||
- rsync daemon must be up and running with correct permission when using rsync protocol in source or destination path.
|
- rsync daemon must be up and running with correct permission when using rsync protocol in source or destination path.
|
||||||
- The ``synchronize`` module forces `--delay-updates` to avoid leaving a destination in a broken in-between state if the underlying rsync process encounters an error. Those synchronizing large numbers of files that are willing to trade safety for performance should call rsync directly.
|
- The ``synchronize`` module enables `--delay-updates` by default to avoid leaving a destination in a broken in-between state if the underlying rsync process encounters an error. Those synchronizing large numbers of files that are willing to trade safety for performance should disable this option.
|
||||||
- link_destination is subject to the same limitations as the underlying rsync daemon. Hard links are only preserved if the relative subtrees of the source and destination are the same. Attempts to hardlink into a directory that is a subdirectory of the source will be prevented.
|
- link_destination is subject to the same limitations as the underlying rsync daemon. Hard links are only preserved if the relative subtrees of the source and destination are the same. Attempts to hardlink into a directory that is a subdirectory of the source will be prevented.
|
||||||
|
|
||||||
|
|
||||||
@@ -560,7 +604,7 @@ See Also
|
|||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
|
|
||||||
.. code-block:: yaml+jinja
|
.. code-block:: yaml
|
||||||
|
|
||||||
- name: Synchronization of src on the control machine to dest on the remote hosts
|
- name: Synchronization of src on the control machine to dest on the remote hosts
|
||||||
ansible.posix.synchronize:
|
ansible.posix.synchronize:
|
||||||
@@ -678,7 +722,7 @@ Examples
|
|||||||
# Specify the rsync binary to use on remote host and on local host
|
# Specify the rsync binary to use on remote host and on local host
|
||||||
- hosts: groupofhosts
|
- hosts: groupofhosts
|
||||||
vars:
|
vars:
|
||||||
ansible_rsync_path: /usr/gnu/bin/rsync
|
ansible_rsync_path: /usr/gnu/bin/rsync
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
- name: copy /tmp/localpath/ to remote location /tmp/remotepath
|
- name: copy /tmp/localpath/ to remote location /tmp/remotepath
|
||||||
|
|||||||
@@ -58,14 +58,14 @@ Parameters
|
|||||||
<b>name</b>
|
<b>name</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">-</span>
|
<span style="color: purple">string</span>
|
||||||
/ <span style="color: red">required</span>
|
/ <span style="color: red">required</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>The dot-separated path (aka <em>key</em>) specifying the sysctl variable.</div>
|
<div>The dot-separated path (also known as <em>key</em>) specifying the sysctl variable.</div>
|
||||||
<div style="font-size: small; color: darkgreen"><br/>aliases: key</div>
|
<div style="font-size: small; color: darkgreen"><br/>aliases: key</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -94,7 +94,7 @@ Parameters
|
|||||||
<b>state</b>
|
<b>state</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">-</span>
|
<span style="color: purple">string</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -113,7 +113,7 @@ Parameters
|
|||||||
<b>sysctl_file</b>
|
<b>sysctl_file</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">-</span>
|
<span style="color: purple">path</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -148,7 +148,7 @@ Parameters
|
|||||||
<b>value</b>
|
<b>value</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">-</span>
|
<span style="color: purple">string</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -167,7 +167,7 @@ Parameters
|
|||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
|
|
||||||
.. code-block:: yaml+jinja
|
.. code-block:: yaml
|
||||||
|
|
||||||
# Set vm.swappiness to 5 in /etc/sysctl.conf
|
# Set vm.swappiness to 5 in /etc/sysctl.conf
|
||||||
- ansible.posix.sysctl:
|
- ansible.posix.sysctl:
|
||||||
@@ -212,4 +212,4 @@ Status
|
|||||||
Authors
|
Authors
|
||||||
~~~~~~~
|
~~~~~~~
|
||||||
|
|
||||||
- David CHANIAL (@davixx) <david.chanial@gmail.com>
|
- David CHANIAL (@davixx)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace: ansible
|
namespace: ansible
|
||||||
name: posix
|
name: posix
|
||||||
version: 1.1.1
|
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,<2.11'
|
requires_ansible: '>=2.9'
|
||||||
|
plugin_routing:
|
||||||
|
callback:
|
||||||
|
skippy:
|
||||||
|
deprecation:
|
||||||
|
removal_date: '2022-06-01'
|
||||||
|
warning_text: See the plugin documentation for more details
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import os.path
|
|||||||
|
|
||||||
from ansible import constants as C
|
from ansible import constants as C
|
||||||
from ansible.module_utils.six import string_types
|
from ansible.module_utils.six import string_types
|
||||||
|
from ansible.module_utils.six.moves import shlex_quote
|
||||||
from ansible.module_utils._text import to_text
|
from ansible.module_utils._text import to_text
|
||||||
from ansible.module_utils.common._collections_compat import MutableSequence
|
from ansible.module_utils.common._collections_compat import MutableSequence
|
||||||
from ansible.module_utils.parsing.convert_bool import boolean
|
from ansible.module_utils.parsing.convert_bool import boolean
|
||||||
@@ -28,12 +29,23 @@ from ansible.plugins.action import ActionBase
|
|||||||
from ansible.plugins.loader import connection_loader
|
from ansible.plugins.loader import connection_loader
|
||||||
|
|
||||||
|
|
||||||
|
DOCKER = ['docker', 'community.general.docker', 'community.docker.docker']
|
||||||
|
PODMAN = ['podman', 'ansible.builtin.podman', 'containers.podman.podman']
|
||||||
|
BUILDAH = ['buildah', 'containers.podman.buildah']
|
||||||
|
|
||||||
|
|
||||||
class ActionModule(ActionBase):
|
class ActionModule(ActionBase):
|
||||||
|
|
||||||
def _get_absolute_path(self, path):
|
def _get_absolute_path(self, path):
|
||||||
original_path = path
|
original_path = path
|
||||||
|
|
||||||
if path.startswith('rsync://'):
|
#
|
||||||
|
# Check if we have a local relative path and do not process
|
||||||
|
# * remote paths (some.server.domain:/some/remote/path/...)
|
||||||
|
# * URLs (rsync://...)
|
||||||
|
# * local absolute paths (/some/local/path/...)
|
||||||
|
#
|
||||||
|
if ':' in path or path.startswith('/'):
|
||||||
return path
|
return path
|
||||||
|
|
||||||
if self._task._role is not None:
|
if self._task._role is not None:
|
||||||
@@ -60,21 +72,19 @@ class ActionModule(ActionBase):
|
|||||||
return path
|
return path
|
||||||
|
|
||||||
# If using docker or buildah, do not add user information
|
# If using docker or buildah, do not add user information
|
||||||
if self._remote_transport not in ['docker', 'community.general.docker', 'buildah', 'containers.podman.buildah'] and user:
|
if self._remote_transport not in DOCKER + PODMAN + BUILDAH and user:
|
||||||
user_prefix = '%s@' % (user, )
|
user_prefix = '%s@' % (user, )
|
||||||
|
|
||||||
if self._host_is_ipv6_address(host):
|
if self._host_is_ipv6_address(host):
|
||||||
return '[%s%s]:%s' % (user_prefix, host, path)
|
return '[%s%s]:%s' % (user_prefix, host, path)
|
||||||
else:
|
return '%s%s:%s' % (user_prefix, host, path)
|
||||||
return '%s%s:%s' % (user_prefix, host, path)
|
|
||||||
|
|
||||||
def _process_origin(self, host, path, user):
|
def _process_origin(self, host, path, user):
|
||||||
|
|
||||||
if host not in C.LOCALHOST:
|
if host not in C.LOCALHOST:
|
||||||
return self._format_rsync_rsh_target(host, path, user)
|
return self._format_rsync_rsh_target(host, path, user)
|
||||||
|
|
||||||
if ':' not in path and not path.startswith('/'):
|
path = self._get_absolute_path(path=path)
|
||||||
path = self._get_absolute_path(path=path)
|
|
||||||
return path
|
return path
|
||||||
|
|
||||||
def _process_remote(self, task_args, host, path, user, port_matches_localhost_port):
|
def _process_remote(self, task_args, host, path, user, port_matches_localhost_port):
|
||||||
@@ -103,8 +113,7 @@ class ActionModule(ActionBase):
|
|||||||
task_args['_substitute_controller'] = True
|
task_args['_substitute_controller'] = True
|
||||||
return self._format_rsync_rsh_target(host, path, user)
|
return self._format_rsync_rsh_target(host, path, user)
|
||||||
|
|
||||||
if ':' not in path and not path.startswith('/'):
|
path = self._get_absolute_path(path=path)
|
||||||
path = self._get_absolute_path(path=path)
|
|
||||||
return path
|
return path
|
||||||
|
|
||||||
def _override_module_replaced_vars(self, task_vars):
|
def _override_module_replaced_vars(self, task_vars):
|
||||||
@@ -168,12 +177,25 @@ class ActionModule(ActionBase):
|
|||||||
|
|
||||||
# Store remote connection type
|
# Store remote connection type
|
||||||
self._remote_transport = self._connection.transport
|
self._remote_transport = self._connection.transport
|
||||||
|
use_ssh_args = _tmp_args.pop('use_ssh_args', None)
|
||||||
|
|
||||||
|
if use_ssh_args and self._connection.transport == 'ssh':
|
||||||
|
ssh_args = [
|
||||||
|
self._connection.get_option('ssh_args'),
|
||||||
|
self._connection.get_option('ssh_common_args'),
|
||||||
|
self._connection.get_option('ssh_extra_args'),
|
||||||
|
]
|
||||||
|
_tmp_args['ssh_args'] = ' '.join([a for a in ssh_args if a])
|
||||||
|
|
||||||
# Handle docker connection options
|
# Handle docker connection options
|
||||||
if self._remote_transport in ['docker', 'community.general.docker']:
|
if self._remote_transport in DOCKER:
|
||||||
self._docker_cmd = self._connection.docker_cmd
|
self._docker_cmd = self._connection.docker_cmd
|
||||||
if self._play_context.docker_extra_args:
|
if self._play_context.docker_extra_args:
|
||||||
self._docker_cmd = "%s %s" % (self._docker_cmd, self._play_context.docker_extra_args)
|
self._docker_cmd = "%s %s" % (self._docker_cmd, self._play_context.docker_extra_args)
|
||||||
|
elif self._remote_transport in PODMAN:
|
||||||
|
self._docker_cmd = self._connection._options['podman_executable']
|
||||||
|
if self._connection._options.get('podman_extra_args'):
|
||||||
|
self._docker_cmd = "%s %s" % (self._docker_cmd, self._connection._options['podman_extra_args'])
|
||||||
|
|
||||||
# self._connection accounts for delegate_to so
|
# self._connection accounts for delegate_to so
|
||||||
# remote_transport is the transport ansible thought it would need
|
# remote_transport is the transport ansible thought it would need
|
||||||
@@ -191,8 +213,8 @@ class ActionModule(ActionBase):
|
|||||||
|
|
||||||
# ssh paramiko docker buildah and local are fully supported transports. Anything
|
# ssh paramiko docker buildah and local are fully supported transports. Anything
|
||||||
# else only works with delegate_to
|
# else only works with delegate_to
|
||||||
if delegate_to is None and self._connection.transport not in \
|
if delegate_to is None and self._connection.transport not in [
|
||||||
('ssh', 'paramiko', 'local', 'docker', 'community.general.docker', 'buildah', 'containers.podman.buildah'):
|
'ssh', 'paramiko', 'local'] + DOCKER + PODMAN + BUILDAH:
|
||||||
result['failed'] = True
|
result['failed'] = True
|
||||||
result['msg'] = (
|
result['msg'] = (
|
||||||
"synchronize uses rsync to function. rsync needs to connect to the remote "
|
"synchronize uses rsync to function. rsync needs to connect to the remote "
|
||||||
@@ -201,8 +223,6 @@ class ActionModule(ActionBase):
|
|||||||
"so it cannot work." % self._connection.transport)
|
"so it cannot work." % self._connection.transport)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
use_ssh_args = _tmp_args.pop('use_ssh_args', None)
|
|
||||||
|
|
||||||
# Parameter name needed by the ansible module
|
# Parameter name needed by the ansible module
|
||||||
_tmp_args['_local_rsync_path'] = task_vars.get('ansible_rsync_path') or 'rsync'
|
_tmp_args['_local_rsync_path'] = task_vars.get('ansible_rsync_path') or 'rsync'
|
||||||
_tmp_args['_local_rsync_password'] = task_vars.get('ansible_ssh_pass') or task_vars.get('ansible_password')
|
_tmp_args['_local_rsync_password'] = task_vars.get('ansible_ssh_pass') or task_vars.get('ansible_password')
|
||||||
@@ -215,14 +235,10 @@ class ActionModule(ActionBase):
|
|||||||
src_host = '127.0.0.1'
|
src_host = '127.0.0.1'
|
||||||
inventory_hostname = task_vars.get('inventory_hostname')
|
inventory_hostname = task_vars.get('inventory_hostname')
|
||||||
dest_host_inventory_vars = task_vars['hostvars'].get(inventory_hostname)
|
dest_host_inventory_vars = task_vars['hostvars'].get(inventory_hostname)
|
||||||
try:
|
dest_host = dest_host_inventory_vars.get('ansible_host', inventory_hostname)
|
||||||
dest_host = dest_host_inventory_vars['ansible_host']
|
|
||||||
except KeyError:
|
|
||||||
dest_host = dest_host_inventory_vars.get('ansible_ssh_host', inventory_hostname)
|
|
||||||
|
|
||||||
dest_host_ids = [hostid for hostid in (dest_host_inventory_vars.get('inventory_hostname'),
|
dest_host_ids = [hostid for hostid in (dest_host_inventory_vars.get('inventory_hostname'),
|
||||||
dest_host_inventory_vars.get('ansible_host'),
|
dest_host_inventory_vars.get('ansible_host'))
|
||||||
dest_host_inventory_vars.get('ansible_ssh_host'))
|
|
||||||
if hostid is not None]
|
if hostid is not None]
|
||||||
|
|
||||||
localhost_ports = set()
|
localhost_ports = set()
|
||||||
@@ -246,7 +262,7 @@ class ActionModule(ActionBase):
|
|||||||
dest_is_local = True
|
dest_is_local = True
|
||||||
|
|
||||||
# CHECK FOR NON-DEFAULT SSH PORT
|
# CHECK FOR NON-DEFAULT SSH PORT
|
||||||
inv_port = task_vars.get('ansible_ssh_port', None) or C.DEFAULT_REMOTE_PORT
|
inv_port = task_vars.get('ansible_port', None) or C.DEFAULT_REMOTE_PORT
|
||||||
if _tmp_args.get('dest_port', None) is None:
|
if _tmp_args.get('dest_port', None) is None:
|
||||||
if inv_port is not None:
|
if inv_port is not None:
|
||||||
_tmp_args['dest_port'] = inv_port
|
_tmp_args['dest_port'] = inv_port
|
||||||
@@ -323,20 +339,18 @@ class ActionModule(ActionBase):
|
|||||||
# Src and dest rsync "path" handling
|
# Src and dest rsync "path" handling
|
||||||
if boolean(_tmp_args.get('set_remote_user', 'yes'), strict=False):
|
if boolean(_tmp_args.get('set_remote_user', 'yes'), strict=False):
|
||||||
if use_delegate:
|
if use_delegate:
|
||||||
user = task_vars.get('ansible_delegated_vars', dict()).get('ansible_ssh_user', None)
|
user = task_vars.get('ansible_delegated_vars', dict()).get('ansible_user', None)
|
||||||
if not user:
|
if not user:
|
||||||
user = task_vars.get('ansible_ssh_user') or self._play_context.remote_user
|
user = task_vars.get('ansible_user') or self._play_context.remote_user
|
||||||
if not user:
|
if not user:
|
||||||
user = C.DEFAULT_REMOTE_USER
|
user = C.DEFAULT_REMOTE_USER
|
||||||
|
|
||||||
else:
|
else:
|
||||||
user = task_vars.get('ansible_ssh_user') or self._play_context.remote_user
|
user = task_vars.get('ansible_user') or self._play_context.remote_user
|
||||||
|
|
||||||
# Private key handling
|
# Private key handling
|
||||||
private_key = self._play_context.private_key_file
|
# Use the private_key parameter if passed else use context private_key_file
|
||||||
|
_tmp_args['private_key'] = _tmp_args.get('private_key', self._play_context.private_key_file)
|
||||||
if private_key is not None:
|
|
||||||
_tmp_args['private_key'] = private_key
|
|
||||||
|
|
||||||
# use the mode to define src and dest's url
|
# use the mode to define src and dest's url
|
||||||
if _tmp_args.get('mode', 'push') == 'pull':
|
if _tmp_args.get('mode', 'push') == 'pull':
|
||||||
@@ -350,10 +364,8 @@ class ActionModule(ActionBase):
|
|||||||
else:
|
else:
|
||||||
# Still need to munge paths (to account for roles) even if we aren't
|
# Still need to munge paths (to account for roles) even if we aren't
|
||||||
# copying files between hosts
|
# copying files between hosts
|
||||||
if not src.startswith('/'):
|
src = self._get_absolute_path(path=src)
|
||||||
src = self._get_absolute_path(path=src)
|
dest = self._get_absolute_path(path=dest)
|
||||||
if not dest.startswith('/'):
|
|
||||||
dest = self._get_absolute_path(path=dest)
|
|
||||||
|
|
||||||
_tmp_args['src'] = src
|
_tmp_args['src'] = src
|
||||||
_tmp_args['dest'] = dest
|
_tmp_args['dest'] = dest
|
||||||
@@ -367,11 +379,14 @@ class ActionModule(ActionBase):
|
|||||||
if not dest_is_local:
|
if not dest_is_local:
|
||||||
# don't escalate for docker. doing --rsync-path with docker exec fails
|
# don't escalate for docker. doing --rsync-path with docker exec fails
|
||||||
# and we can switch directly to the user via docker arguments
|
# and we can switch directly to the user via docker arguments
|
||||||
if self._play_context.become and not rsync_path and self._remote_transport not in ['docker', 'community.general.docker']:
|
if self._play_context.become and not rsync_path and self._remote_transport not in DOCKER + PODMAN:
|
||||||
# If no rsync_path is set, become was originally set, and dest is
|
# If no rsync_path is set, become was originally set, and dest is
|
||||||
# remote then add privilege escalation here.
|
# remote then add privilege escalation here.
|
||||||
if self._play_context.become_method == 'sudo':
|
if self._play_context.become_method == 'sudo':
|
||||||
rsync_path = 'sudo rsync'
|
if self._play_context.become_user:
|
||||||
|
rsync_path = 'sudo -u %s rsync' % self._play_context.become_user
|
||||||
|
else:
|
||||||
|
rsync_path = 'sudo rsync'
|
||||||
# TODO: have to add in the rest of the become methods here
|
# TODO: have to add in the rest of the become methods here
|
||||||
|
|
||||||
# We cannot use privilege escalation on the machine running the
|
# We cannot use privilege escalation on the machine running the
|
||||||
@@ -381,17 +396,9 @@ class ActionModule(ActionBase):
|
|||||||
|
|
||||||
_tmp_args['rsync_path'] = rsync_path
|
_tmp_args['rsync_path'] = rsync_path
|
||||||
|
|
||||||
if use_ssh_args:
|
|
||||||
ssh_args = [
|
|
||||||
getattr(self._play_context, 'ssh_args', ''),
|
|
||||||
getattr(self._play_context, 'ssh_common_args', ''),
|
|
||||||
getattr(self._play_context, 'ssh_extra_args', ''),
|
|
||||||
]
|
|
||||||
_tmp_args['ssh_args'] = ' '.join([a for a in ssh_args if a])
|
|
||||||
|
|
||||||
# If launching synchronize against docker container
|
# If launching synchronize against docker container
|
||||||
# use rsync_opts to support container to override rsh options
|
# use rsync_opts to support container to override rsh options
|
||||||
if self._remote_transport in ['docker', 'community.general.docker', 'buildah', 'containers.podman.buildah'] and not use_delegate:
|
if self._remote_transport in DOCKER + BUILDAH + PODMAN and not use_delegate:
|
||||||
# Replicate what we do in the module argumentspec handling for lists
|
# Replicate what we do in the module argumentspec handling for lists
|
||||||
if not isinstance(_tmp_args.get('rsync_opts'), MutableSequence):
|
if not isinstance(_tmp_args.get('rsync_opts'), MutableSequence):
|
||||||
tmp_rsync_opts = _tmp_args.get('rsync_opts', [])
|
tmp_rsync_opts = _tmp_args.get('rsync_opts', [])
|
||||||
@@ -404,15 +411,15 @@ class ActionModule(ActionBase):
|
|||||||
if '--blocking-io' not in _tmp_args['rsync_opts']:
|
if '--blocking-io' not in _tmp_args['rsync_opts']:
|
||||||
_tmp_args['rsync_opts'].append('--blocking-io')
|
_tmp_args['rsync_opts'].append('--blocking-io')
|
||||||
|
|
||||||
if self._remote_transport in ['docker', 'community.general.docker']:
|
if self._remote_transport in DOCKER + PODMAN:
|
||||||
if become and self._play_context.become_user:
|
if become and self._play_context.become_user:
|
||||||
_tmp_args['rsync_opts'].append("--rsh=%s exec -u %s -i" % (self._docker_cmd, self._play_context.become_user))
|
_tmp_args['rsync_opts'].append('--rsh=' + shlex_quote('%s exec -u %s -i' % (self._docker_cmd, self._play_context.become_user)))
|
||||||
elif user is not None:
|
elif user is not None:
|
||||||
_tmp_args['rsync_opts'].append("--rsh=%s exec -u %s -i" % (self._docker_cmd, user))
|
_tmp_args['rsync_opts'].append('--rsh=' + shlex_quote('%s exec -u %s -i' % (self._docker_cmd, user)))
|
||||||
else:
|
else:
|
||||||
_tmp_args['rsync_opts'].append("--rsh=%s exec -i" % self._docker_cmd)
|
_tmp_args['rsync_opts'].append('--rsh=' + shlex_quote('%s exec -i' % self._docker_cmd))
|
||||||
elif self._remote_transport in ['buildah', 'containers.podman.buildah']:
|
elif self._remote_transport in BUILDAH:
|
||||||
_tmp_args['rsync_opts'].append("--rsh=buildah run --")
|
_tmp_args['rsync_opts'].append('--rsh=' + shlex_quote('buildah run --'))
|
||||||
|
|
||||||
# run the module and store the result
|
# run the module and store the result
|
||||||
result.update(self._execute_module('ansible.posix.synchronize', module_args=_tmp_args, task_vars=task_vars))
|
result.update(self._execute_module('ansible.posix.synchronize', module_args=_tmp_args, task_vars=task_vars))
|
||||||
|
|||||||
@@ -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,19 +7,19 @@ 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
|
||||||
description:
|
description:
|
||||||
- This callback does the same as the default except it does not output skipped host/task/item status
|
- This callback does the same as the default except it does not output skipped host/task/item status
|
||||||
'''
|
'''
|
||||||
|
|
||||||
from ansible.plugins.callback.default import CallbackModule as CallbackModule_default
|
from ansible.plugins.callback.default import CallbackModule as CallbackModule_default
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -3,8 +3,12 @@
|
|||||||
# (c) 2013-2018, Adam Miller (maxamillion@fedoraproject.org)
|
# (c) 2013-2018, Adam Miller (maxamillion@fedoraproject.org)
|
||||||
# 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)
|
||||||
|
|
||||||
# Imports and info for sanity checking
|
from __future__ import absolute_import, division, print_function
|
||||||
from distutils.version import LooseVersion
|
from ansible_collections.ansible.posix.plugins.module_utils.version import LooseVersion
|
||||||
|
from ansible.module_utils.basic import missing_required_lib
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
FW_VERSION = None
|
FW_VERSION = None
|
||||||
fw = None
|
fw = None
|
||||||
@@ -311,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)'
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -48,6 +48,10 @@
|
|||||||
# agrees to be bound by the terms and conditions of this License
|
# agrees to be bound by the terms and conditions of this License
|
||||||
# Agreement.
|
# Agreement.
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
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
|
||||||
@@ -28,6 +28,7 @@ options:
|
|||||||
- The C(query) state gets the current ACL without changing it, for use in C(register) operations.
|
- The C(query) state gets the current ACL without changing it, for use in C(register) operations.
|
||||||
choices: [ absent, present, query ]
|
choices: [ absent, present, query ]
|
||||||
default: query
|
default: query
|
||||||
|
type: str
|
||||||
follow:
|
follow:
|
||||||
description:
|
description:
|
||||||
- Whether to follow symlinks on the path if a symlink is encountered.
|
- Whether to follow symlinks on the path if a symlink is encountered.
|
||||||
@@ -42,13 +43,17 @@ options:
|
|||||||
entity:
|
entity:
|
||||||
description:
|
description:
|
||||||
- The actual user or group that the ACL applies to when matching entity types user or group are selected.
|
- The actual user or group that the ACL applies to when matching entity types user or group are selected.
|
||||||
|
type: str
|
||||||
etype:
|
etype:
|
||||||
description:
|
description:
|
||||||
- The entity type of the ACL to apply, see C(setfacl) documentation for more info.
|
- The entity type of the ACL to apply, see C(setfacl) documentation for more info.
|
||||||
choices: [ group, mask, other, user ]
|
choices: [ group, mask, other, user ]
|
||||||
|
type: str
|
||||||
permissions:
|
permissions:
|
||||||
description:
|
description:
|
||||||
- The permissions to apply/remove can be any combination of C(r), C(w) and C(x) (read, write and execute respectively)
|
- The permissions to apply/remove can be any combination of C(r), C(w), C(x)
|
||||||
|
- (read, write and execute respectively), and C(X) (execute permission if the file is a directory or already has execute permission for some user)
|
||||||
|
type: str
|
||||||
entry:
|
entry:
|
||||||
description:
|
description:
|
||||||
- DEPRECATED.
|
- DEPRECATED.
|
||||||
@@ -57,12 +62,15 @@ options:
|
|||||||
- The qualifier may be empty for some types, but the type and perms are always required.
|
- The qualifier may be empty for some types, but the type and perms are always required.
|
||||||
- C(-) can be used as placeholder when you do not care about permissions.
|
- C(-) can be used as placeholder when you do not care about permissions.
|
||||||
- This is now superseded by entity, type and permissions fields.
|
- This is now superseded by entity, type and permissions fields.
|
||||||
|
type: str
|
||||||
recursive:
|
recursive:
|
||||||
description:
|
description:
|
||||||
- Recursively sets the specified ACL.
|
- Recursively sets the specified ACL.
|
||||||
- Incompatible with C(state=query).
|
- Incompatible with C(state=query).
|
||||||
|
- Alias C(recurse) added in version 1.3.0.
|
||||||
type: bool
|
type: bool
|
||||||
default: no
|
default: no
|
||||||
|
aliases: [ recurse ]
|
||||||
use_nfsv4_acls:
|
use_nfsv4_acls:
|
||||||
description:
|
description:
|
||||||
- Use NFSv4 ACLs instead of POSIX ACLs.
|
- Use NFSv4 ACLs instead of POSIX ACLs.
|
||||||
@@ -75,6 +83,7 @@ options:
|
|||||||
- Incompatible with C(state=query).
|
- Incompatible with C(state=query).
|
||||||
choices: [ default, mask, no_mask ]
|
choices: [ default, mask, no_mask ]
|
||||||
default: default
|
default: default
|
||||||
|
type: str
|
||||||
author:
|
author:
|
||||||
- Brian Coca (@bcoca)
|
- Brian Coca (@bcoca)
|
||||||
- Jérémie Astori (@astorije)
|
- Jérémie Astori (@astorije)
|
||||||
@@ -266,7 +275,7 @@ def main():
|
|||||||
),
|
),
|
||||||
follow=dict(type='bool', default=True),
|
follow=dict(type='bool', default=True),
|
||||||
default=dict(type='bool', default=False),
|
default=dict(type='bool', default=False),
|
||||||
recursive=dict(type='bool', default=False),
|
recursive=dict(type='bool', default=False, aliases=['recurse']),
|
||||||
recalculate_mask=dict(
|
recalculate_mask=dict(
|
||||||
type='str',
|
type='str',
|
||||||
default='default',
|
default='default',
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from __future__ import absolute_import, division, print_function
|
|||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = r'''
|
||||||
---
|
---
|
||||||
module: at
|
module: at
|
||||||
short_description: Schedule the execution of a command or script file via the at command
|
short_description: Schedule the execution of a command or script file via the at command
|
||||||
@@ -29,12 +29,10 @@ options:
|
|||||||
description:
|
description:
|
||||||
- The count of units in the future to execute the command or script file.
|
- The count of units in the future to execute the command or script file.
|
||||||
type: int
|
type: int
|
||||||
required: true
|
|
||||||
units:
|
units:
|
||||||
description:
|
description:
|
||||||
- The type of units in the future to execute the command or script file.
|
- The type of units in the future to execute the command or script file.
|
||||||
type: str
|
type: str
|
||||||
required: true
|
|
||||||
choices: [ minutes, hours, days, weeks ]
|
choices: [ minutes, hours, days, weeks ]
|
||||||
state:
|
state:
|
||||||
description:
|
description:
|
||||||
@@ -74,6 +72,7 @@ EXAMPLES = r'''
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import platform
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
@@ -89,7 +88,7 @@ def add_job(module, result, at_cmd, count, units, command, script_file):
|
|||||||
|
|
||||||
def delete_job(module, result, at_cmd, command, script_file):
|
def delete_job(module, result, at_cmd, command, script_file):
|
||||||
for matching_job in get_matching_jobs(module, at_cmd, script_file):
|
for matching_job in get_matching_jobs(module, at_cmd, script_file):
|
||||||
at_command = "%s -d %s" % (at_cmd, matching_job)
|
at_command = "%s -r %s" % (at_cmd, matching_job)
|
||||||
rc, out, err = module.run_command(at_command, check_rc=True)
|
rc, out, err = module.run_command(at_command, check_rc=True)
|
||||||
result['changed'] = True
|
result['changed'] = True
|
||||||
if command:
|
if command:
|
||||||
@@ -117,7 +116,8 @@ def get_matching_jobs(module, at_cmd, script_file):
|
|||||||
# If the script text is contained in a job add job number to list.
|
# If the script text is contained in a job add job number to list.
|
||||||
for current_job in current_jobs:
|
for current_job in current_jobs:
|
||||||
split_current_job = current_job.split()
|
split_current_job = current_job.split()
|
||||||
at_command = "%s -c %s" % (at_cmd, split_current_job[0])
|
at_opt = '-c' if platform.system() != 'AIX' else '-lv'
|
||||||
|
at_command = "%s %s %s" % (at_cmd, at_opt, split_current_job[0])
|
||||||
rc, out, err = module.run_command(at_command, check_rc=True)
|
rc, out, err = module.run_command(at_command, check_rc=True)
|
||||||
if script_file_string in out:
|
if script_file_string in out:
|
||||||
matching_jobs.append(split_current_job[0])
|
matching_jobs.append(split_current_job[0])
|
||||||
@@ -129,7 +129,7 @@ def get_matching_jobs(module, at_cmd, script_file):
|
|||||||
def create_tempfile(command):
|
def create_tempfile(command):
|
||||||
filed, script_file = tempfile.mkstemp(prefix='at')
|
filed, script_file = tempfile.mkstemp(prefix='at')
|
||||||
fileh = os.fdopen(filed, 'w')
|
fileh = os.fdopen(filed, 'w')
|
||||||
fileh.write(command)
|
fileh.write(command + os.linesep)
|
||||||
fileh.close()
|
fileh.close()
|
||||||
return script_file
|
return script_file
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ options:
|
|||||||
key_options:
|
key_options:
|
||||||
description:
|
description:
|
||||||
- A string of ssh key options to be prepended to the key in the authorized_keys file.
|
- A string of ssh key options to be prepended to the key in the authorized_keys file.
|
||||||
|
type: str
|
||||||
exclusive:
|
exclusive:
|
||||||
description:
|
description:
|
||||||
- Whether to remove all other non-specified keys from the authorized_keys file.
|
- Whether to remove all other non-specified keys from the authorized_keys file.
|
||||||
@@ -93,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
|
||||||
@@ -340,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:
|
||||||
@@ -388,13 +397,28 @@ def parsekey(module, raw_key, rank=None):
|
|||||||
|
|
||||||
VALID_SSH2_KEY_TYPES = [
|
VALID_SSH2_KEY_TYPES = [
|
||||||
'sk-ecdsa-sha2-nistp256@openssh.com',
|
'sk-ecdsa-sha2-nistp256@openssh.com',
|
||||||
|
'sk-ecdsa-sha2-nistp256-cert-v01@openssh.com',
|
||||||
|
'webauthn-sk-ecdsa-sha2-nistp256@openssh.com',
|
||||||
'ecdsa-sha2-nistp256',
|
'ecdsa-sha2-nistp256',
|
||||||
|
'ecdsa-sha2-nistp256-cert-v01@openssh.com',
|
||||||
'ecdsa-sha2-nistp384',
|
'ecdsa-sha2-nistp384',
|
||||||
|
'ecdsa-sha2-nistp384-cert-v01@openssh.com',
|
||||||
'ecdsa-sha2-nistp521',
|
'ecdsa-sha2-nistp521',
|
||||||
|
'ecdsa-sha2-nistp521-cert-v01@openssh.com',
|
||||||
'sk-ssh-ed25519@openssh.com',
|
'sk-ssh-ed25519@openssh.com',
|
||||||
|
'sk-ssh-ed25519-cert-v01@openssh.com',
|
||||||
'ssh-ed25519',
|
'ssh-ed25519',
|
||||||
|
'ssh-ed25519-cert-v01@openssh.com',
|
||||||
'ssh-dss',
|
'ssh-dss',
|
||||||
'ssh-rsa',
|
'ssh-rsa',
|
||||||
|
'ssh-xmss@openssh.com',
|
||||||
|
'ssh-xmss-cert-v01@openssh.com',
|
||||||
|
'rsa-sha2-256',
|
||||||
|
'rsa-sha2-512',
|
||||||
|
'ssh-rsa-cert-v01@openssh.com',
|
||||||
|
'rsa-sha2-256-cert-v01@openssh.com',
|
||||||
|
'rsa-sha2-512-cert-v01@openssh.com',
|
||||||
|
'ssh-dss-cert-v01@openssh.com',
|
||||||
]
|
]
|
||||||
|
|
||||||
options = None # connection options
|
options = None # connection options
|
||||||
@@ -647,11 +671,11 @@ def main():
|
|||||||
module = AnsibleModule(
|
module = AnsibleModule(
|
||||||
argument_spec=dict(
|
argument_spec=dict(
|
||||||
user=dict(type='str', required=True),
|
user=dict(type='str', required=True),
|
||||||
key=dict(type='str', required=True),
|
key=dict(type='str', required=True, no_log=False),
|
||||||
path=dict(type='path'),
|
path=dict(type='path'),
|
||||||
manage_dir=dict(type='bool', default=True),
|
manage_dir=dict(type='bool', default=True),
|
||||||
state=dict(type='str', default='present', choices=['absent', 'present']),
|
state=dict(type='str', default='present', choices=['absent', 'present']),
|
||||||
key_options=dict(type='str'),
|
key_options=dict(type='str', no_log=False),
|
||||||
exclusive=dict(type='bool', default=False),
|
exclusive=dict(type='bool', default=False),
|
||||||
comment=dict(type='str'),
|
comment=dict(type='str'),
|
||||||
validate_certs=dict(type='bool', default=True),
|
validate_certs=dict(type='bool', default=True),
|
||||||
|
|||||||
@@ -24,6 +24,32 @@ options:
|
|||||||
- Name of a port or port range to add/remove to/from firewalld.
|
- Name of a port or port range to add/remove to/from firewalld.
|
||||||
- Must be in the form PORT/PROTOCOL or PORT-PORT/PROTOCOL for port ranges.
|
- Must be in the form PORT/PROTOCOL or PORT-PORT/PROTOCOL for port ranges.
|
||||||
type: str
|
type: str
|
||||||
|
port_forward:
|
||||||
|
description:
|
||||||
|
- Port and protocol to forward using firewalld.
|
||||||
|
type: list
|
||||||
|
elements: dict
|
||||||
|
suboptions:
|
||||||
|
port:
|
||||||
|
type: str
|
||||||
|
required: true
|
||||||
|
description:
|
||||||
|
- Source port to forward from
|
||||||
|
proto:
|
||||||
|
type: str
|
||||||
|
required: true
|
||||||
|
description:
|
||||||
|
- protocol to forward
|
||||||
|
choices: [udp, tcp]
|
||||||
|
toport:
|
||||||
|
type: str
|
||||||
|
required: true
|
||||||
|
description:
|
||||||
|
- destination port
|
||||||
|
toaddr:
|
||||||
|
type: str
|
||||||
|
description:
|
||||||
|
- Optional address to forward to
|
||||||
rich_rule:
|
rich_rule:
|
||||||
description:
|
description:
|
||||||
- Rich rule to add/remove to/from firewalld.
|
- Rich rule to add/remove to/from firewalld.
|
||||||
@@ -55,7 +81,7 @@ options:
|
|||||||
permanent:
|
permanent:
|
||||||
description:
|
description:
|
||||||
- Should this configuration be in the running firewalld configuration or persist across reboots.
|
- Should this configuration be in the running firewalld configuration or persist across reboots.
|
||||||
- As of Ansible 2.3, permanent operations can operate on firewalld configs when it is not running (requires firewalld >= 3.0.9).
|
- As of Ansible 2.3, permanent operations can operate on firewalld configs when it is not running (requires firewalld >= 0.3.9).
|
||||||
- Note that if this is C(no), immediate is assumed C(yes).
|
- Note that if this is C(no), immediate is assumed C(yes).
|
||||||
type: bool
|
type: bool
|
||||||
immediate:
|
immediate:
|
||||||
@@ -73,7 +99,7 @@ options:
|
|||||||
choices: [ absent, disabled, enabled, present ]
|
choices: [ absent, disabled, enabled, present ]
|
||||||
timeout:
|
timeout:
|
||||||
description:
|
description:
|
||||||
- The amount of time the rule should be in effect for when non-permanent.
|
- The amount of time in seconds the rule should be in effect for when non-permanent.
|
||||||
type: int
|
type: int
|
||||||
default: 0
|
default: 0
|
||||||
masquerade:
|
masquerade:
|
||||||
@@ -84,6 +110,13 @@ options:
|
|||||||
description:
|
description:
|
||||||
- Whether to run this module even when firewalld is offline.
|
- Whether to run this module even when firewalld is offline.
|
||||||
type: bool
|
type: bool
|
||||||
|
target:
|
||||||
|
description:
|
||||||
|
- firewalld Zone target
|
||||||
|
- If state is set to C(absent), this will reset the target to default
|
||||||
|
choices: [ default, ACCEPT, DROP, "%%REJECT%%" ]
|
||||||
|
type: str
|
||||||
|
version_added: 1.2.0
|
||||||
notes:
|
notes:
|
||||||
- Not tested on any Debian based system.
|
- Not tested on any Debian based system.
|
||||||
- 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.
|
||||||
@@ -95,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)
|
||||||
'''
|
'''
|
||||||
@@ -164,6 +200,12 @@ EXAMPLES = r'''
|
|||||||
permanent: yes
|
permanent: yes
|
||||||
icmp_block: echo-request
|
icmp_block: echo-request
|
||||||
|
|
||||||
|
- ansible.posix.firewalld:
|
||||||
|
zone: internal
|
||||||
|
state: present
|
||||||
|
permanent: yes
|
||||||
|
target: ACCEPT
|
||||||
|
|
||||||
- name: Redirect port 443 to 8443 with Rich Rule
|
- name: Redirect port 443 to 8443 with Rich Rule
|
||||||
ansible.posix.firewalld:
|
ansible.posix.firewalld:
|
||||||
rich_rule: rule family=ipv4 forward-port port=443 protocol=tcp to-port=8443
|
rich_rule: rule family=ipv4 forward-port port=443 protocol=tcp to-port=8443
|
||||||
@@ -174,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:
|
||||||
@@ -354,26 +397,14 @@ class PortTransaction(FirewallTransaction):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def get_enabled_immediate(self, port, protocol, timeout):
|
def get_enabled_immediate(self, port, protocol, timeout):
|
||||||
port_proto = [port, protocol]
|
|
||||||
if self.fw_offline:
|
if self.fw_offline:
|
||||||
fw_zone, fw_settings = self.get_fw_zone_settings()
|
dummy, fw_settings = self.get_fw_zone_settings()
|
||||||
ports_list = fw_settings.getPorts()
|
return fw_settings.queryPort(port=port, protocol=protocol)
|
||||||
else:
|
return self.fw.queryPort(zone=self.zone, port=port, protocol=protocol)
|
||||||
ports_list = self.fw.getPorts(self.zone)
|
|
||||||
|
|
||||||
if port_proto in ports_list:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def get_enabled_permanent(self, port, protocol, timeout):
|
def get_enabled_permanent(self, port, protocol, timeout):
|
||||||
port_proto = (port, protocol)
|
dummy, fw_settings = self.get_fw_zone_settings()
|
||||||
fw_zone, fw_settings = self.get_fw_zone_settings()
|
return fw_settings.queryPort(port=port, protocol=protocol)
|
||||||
|
|
||||||
if port_proto in fw_settings.getPorts():
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def set_enabled_immediate(self, port, protocol, timeout):
|
def set_enabled_immediate(self, port, protocol, timeout):
|
||||||
self.fw.addPort(self.zone, port, protocol, timeout)
|
self.fw.addPort(self.zone, port, protocol, timeout)
|
||||||
@@ -571,6 +602,53 @@ class SourceTransaction(FirewallTransaction):
|
|||||||
self.update_fw_settings(fw_zone, fw_settings)
|
self.update_fw_settings(fw_zone, fw_settings)
|
||||||
|
|
||||||
|
|
||||||
|
class ZoneTargetTransaction(FirewallTransaction):
|
||||||
|
"""
|
||||||
|
ZoneTargetTransaction
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, module, action_args=None, zone=None, desired_state=None,
|
||||||
|
permanent=True, immediate=False, enabled_values=None, disabled_values=None):
|
||||||
|
super(ZoneTargetTransaction, self).__init__(
|
||||||
|
module, action_args=action_args, desired_state=desired_state, zone=zone,
|
||||||
|
permanent=permanent, immediate=immediate,
|
||||||
|
enabled_values=enabled_values or ["present", "enabled"],
|
||||||
|
disabled_values=disabled_values or ["absent", "disabled"])
|
||||||
|
|
||||||
|
self.enabled_msg = "Set zone %s target to %s" % \
|
||||||
|
(self.zone, action_args[0])
|
||||||
|
|
||||||
|
self.disabled_msg = "Reset zone %s target to default" % \
|
||||||
|
(self.zone)
|
||||||
|
|
||||||
|
self.tx_not_permanent_error_msg = "Zone operations must be permanent. " \
|
||||||
|
"Make sure you didn't set the 'permanent' flag to 'false' or the 'immediate' flag to 'true'."
|
||||||
|
|
||||||
|
def get_enabled_immediate(self, target):
|
||||||
|
self.module.fail_json(msg=self.tx_not_permanent_error_msg)
|
||||||
|
|
||||||
|
def get_enabled_permanent(self, target):
|
||||||
|
fw_zone, fw_settings = self.get_fw_zone_settings()
|
||||||
|
current_target = fw_settings.getTarget()
|
||||||
|
return (current_target == target)
|
||||||
|
|
||||||
|
def set_enabled_immediate(self, target):
|
||||||
|
self.module.fail_json(msg=self.tx_not_permanent_error_msg)
|
||||||
|
|
||||||
|
def set_enabled_permanent(self, target):
|
||||||
|
fw_zone, fw_settings = self.get_fw_zone_settings()
|
||||||
|
fw_settings.setTarget(target)
|
||||||
|
self.update_fw_settings(fw_zone, fw_settings)
|
||||||
|
|
||||||
|
def set_disabled_immediate(self, target):
|
||||||
|
self.module.fail_json(msg=self.tx_not_permanent_error_msg)
|
||||||
|
|
||||||
|
def set_disabled_permanent(self, target):
|
||||||
|
fw_zone, fw_settings = self.get_fw_zone_settings()
|
||||||
|
fw_settings.setTarget("default")
|
||||||
|
self.update_fw_settings(fw_zone, fw_settings)
|
||||||
|
|
||||||
|
|
||||||
class ZoneTransaction(FirewallTransaction):
|
class ZoneTransaction(FirewallTransaction):
|
||||||
"""
|
"""
|
||||||
ZoneTransaction
|
ZoneTransaction
|
||||||
@@ -618,6 +696,43 @@ class ZoneTransaction(FirewallTransaction):
|
|||||||
zone_obj.remove()
|
zone_obj.remove()
|
||||||
|
|
||||||
|
|
||||||
|
class ForwardPortTransaction(FirewallTransaction):
|
||||||
|
"""
|
||||||
|
ForwardPortTransaction
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, module, action_args=None, zone=None, desired_state=None, permanent=False, immediate=False):
|
||||||
|
super(ForwardPortTransaction, self).__init__(
|
||||||
|
module, action_args=action_args, desired_state=desired_state, zone=zone, permanent=permanent, immediate=immediate
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_enabled_immediate(self, port, proto, toport, toaddr, timeout):
|
||||||
|
if self.fw_offline:
|
||||||
|
dummy, fw_settings = self.get_fw_zone_settings()
|
||||||
|
return fw_settings.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):
|
||||||
|
dummy, fw_settings = self.get_fw_zone_settings()
|
||||||
|
return fw_settings.queryForwardPort(port=port, protocol=proto, to_port=toport, to_addr=toaddr)
|
||||||
|
|
||||||
|
def set_enabled_immediate(self, port, proto, toport, toaddr, timeout):
|
||||||
|
self.fw.addForwardPort(self.zone, port, proto, toport, toaddr, timeout)
|
||||||
|
|
||||||
|
def set_enabled_permanent(self, port, proto, toport, toaddr, timeout):
|
||||||
|
fw_zone, fw_settings = self.get_fw_zone_settings()
|
||||||
|
fw_settings.addForwardPort(port, proto, toport, toaddr)
|
||||||
|
self.update_fw_settings(fw_zone, fw_settings)
|
||||||
|
|
||||||
|
def set_disabled_immediate(self, port, proto, toport, toaddr, timeout):
|
||||||
|
self.fw.removeForwardPort(self.zone, port, proto, toport, toaddr)
|
||||||
|
|
||||||
|
def set_disabled_permanent(self, port, proto, toport, toaddr, timeout):
|
||||||
|
fw_zone, fw_settings = self.get_fw_zone_settings()
|
||||||
|
fw_settings.removeForwardPort(port, proto, toport, toaddr)
|
||||||
|
self.update_fw_settings(fw_zone, fw_settings)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
module = AnsibleModule(
|
module = AnsibleModule(
|
||||||
@@ -626,6 +741,7 @@ def main():
|
|||||||
icmp_block_inversion=dict(type='str'),
|
icmp_block_inversion=dict(type='str'),
|
||||||
service=dict(type='str'),
|
service=dict(type='str'),
|
||||||
port=dict(type='str'),
|
port=dict(type='str'),
|
||||||
|
port_forward=dict(type='list', elements='dict'),
|
||||||
rich_rule=dict(type='str'),
|
rich_rule=dict(type='str'),
|
||||||
zone=dict(type='str'),
|
zone=dict(type='str'),
|
||||||
immediate=dict(type='bool', default=False),
|
immediate=dict(type='bool', default=False),
|
||||||
@@ -636,12 +752,18 @@ def main():
|
|||||||
interface=dict(type='str'),
|
interface=dict(type='str'),
|
||||||
masquerade=dict(type='str'),
|
masquerade=dict(type='str'),
|
||||||
offline=dict(type='bool'),
|
offline=dict(type='bool'),
|
||||||
|
target=dict(type='str', choices=['default', 'ACCEPT', 'DROP', '%%REJECT%%']),
|
||||||
),
|
),
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_by=dict(
|
required_by=dict(
|
||||||
interface=('zone',),
|
interface=('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']
|
||||||
@@ -671,6 +793,7 @@ def main():
|
|||||||
rich_rule = module.params['rich_rule']
|
rich_rule = module.params['rich_rule']
|
||||||
source = module.params['source']
|
source = module.params['source']
|
||||||
zone = module.params['zone']
|
zone = module.params['zone']
|
||||||
|
target = module.params['target']
|
||||||
|
|
||||||
if module.params['port'] is not None:
|
if module.params['port'] is not None:
|
||||||
if '/' in module.params['port']:
|
if '/' in module.params['port']:
|
||||||
@@ -682,29 +805,26 @@ def main():
|
|||||||
else:
|
else:
|
||||||
port = None
|
port = None
|
||||||
|
|
||||||
modification_count = 0
|
port_forward_toaddr = ''
|
||||||
if icmp_block is not None:
|
port_forward = None
|
||||||
modification_count += 1
|
if module.params['port_forward'] is not None:
|
||||||
if icmp_block_inversion is not None:
|
if len(module.params['port_forward']) > 1:
|
||||||
modification_count += 1
|
module.fail_json(msg='Only one port forward supported at a time')
|
||||||
if service is not None:
|
port_forward = module.params['port_forward'][0]
|
||||||
modification_count += 1
|
if 'port' not in port_forward:
|
||||||
if port is not None:
|
module.fail_json(msg='port must be specified for port forward')
|
||||||
modification_count += 1
|
if 'proto' not in port_forward:
|
||||||
if rich_rule is not None:
|
module.fail_json(msg='proto udp/tcp must be specified for port forward')
|
||||||
modification_count += 1
|
if 'toport' not in port_forward:
|
||||||
if interface is not None:
|
module.fail_json(msg='toport must be specified for port forward')
|
||||||
modification_count += 1
|
if 'toaddr' in port_forward:
|
||||||
if masquerade is not None:
|
port_forward_toaddr = port_forward['toaddr']
|
||||||
modification_count += 1
|
|
||||||
if source is not None:
|
|
||||||
modification_count += 1
|
|
||||||
|
|
||||||
if modification_count > 1:
|
modification = False
|
||||||
module.fail_json(
|
if any([icmp_block, icmp_block_inversion, service, port, port_forward, rich_rule,
|
||||||
msg='can only operate on port, service, rich_rule, masquerade, icmp_block, icmp_block_inversion, interface or source at once'
|
interface, masquerade, source, target]):
|
||||||
)
|
modification = True
|
||||||
elif modification_count > 0 and desired_state in ['absent', 'present']:
|
if modification 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'
|
||||||
)
|
)
|
||||||
@@ -741,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(
|
||||||
@@ -791,6 +919,29 @@ def main():
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if port_forward is not None:
|
||||||
|
transaction = ForwardPortTransaction(
|
||||||
|
module,
|
||||||
|
action_args=(str(port_forward['port']), port_forward['proto'],
|
||||||
|
str(port_forward['toport']), port_forward_toaddr, timeout),
|
||||||
|
zone=zone,
|
||||||
|
desired_state=desired_state,
|
||||||
|
permanent=permanent,
|
||||||
|
immediate=immediate
|
||||||
|
)
|
||||||
|
|
||||||
|
changed, transaction_msgs = transaction.run()
|
||||||
|
msgs = msgs + transaction_msgs
|
||||||
|
if changed is True:
|
||||||
|
msgs.append(
|
||||||
|
"Changed port_forward %s to %s" % (
|
||||||
|
"port=%s:proto=%s:toport=%s:toaddr=%s" % (
|
||||||
|
port_forward['port'], port_forward['proto'],
|
||||||
|
port_forward['toport'], port_forward_toaddr
|
||||||
|
), desired_state
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if rich_rule is not None:
|
if rich_rule is not None:
|
||||||
|
|
||||||
transaction = RichRuleTransaction(
|
transaction = RichRuleTransaction(
|
||||||
@@ -835,8 +986,30 @@ 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:
|
||||||
|
|
||||||
|
transaction = ZoneTargetTransaction(
|
||||||
|
module,
|
||||||
|
action_args=(target,),
|
||||||
|
zone=zone,
|
||||||
|
desired_state=desired_state,
|
||||||
|
permanent=permanent,
|
||||||
|
immediate=immediate,
|
||||||
|
)
|
||||||
|
|
||||||
|
changed, transaction_msgs = transaction.run()
|
||||||
|
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,
|
||||||
|
|||||||
392
plugins/modules/firewalld_info.py
Normal file
392
plugins/modules/firewalld_info.py
Normal file
@@ -0,0 +1,392 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright: (c) 2021, Hideki Saito <saito@fgrep.org>
|
||||||
|
# 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)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
DOCUMENTATION = r'''
|
||||||
|
---
|
||||||
|
module: firewalld_info
|
||||||
|
short_description: Gather information about firewalld
|
||||||
|
description:
|
||||||
|
- This module gathers information about firewalld rules.
|
||||||
|
options:
|
||||||
|
active_zones:
|
||||||
|
description: Gather information about active zones.
|
||||||
|
type: bool
|
||||||
|
default: no
|
||||||
|
zones:
|
||||||
|
description:
|
||||||
|
- Gather information about specific zones.
|
||||||
|
- If only works if C(active_zones) is set to C(false).
|
||||||
|
required: false
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
requirements:
|
||||||
|
- firewalld >= 0.2.11
|
||||||
|
- python-firewall
|
||||||
|
- python-dbus
|
||||||
|
author:
|
||||||
|
- Hideki Saito (@saito-hideki)
|
||||||
|
'''
|
||||||
|
|
||||||
|
EXAMPLES = r'''
|
||||||
|
- name: Gather information about active zones
|
||||||
|
ansible.posix.firewalld_info:
|
||||||
|
active_zones: yes
|
||||||
|
|
||||||
|
- name: Gather information about specific zones
|
||||||
|
ansible.posix.firewalld_info:
|
||||||
|
zones:
|
||||||
|
- public
|
||||||
|
- external
|
||||||
|
- internal
|
||||||
|
'''
|
||||||
|
|
||||||
|
RETURN = r'''
|
||||||
|
active_zones:
|
||||||
|
description:
|
||||||
|
- Gather active zones only if turn it C(true).
|
||||||
|
returned: success
|
||||||
|
type: bool
|
||||||
|
sample: false
|
||||||
|
collected_zones:
|
||||||
|
description:
|
||||||
|
- A list of collected zones.
|
||||||
|
returned: success
|
||||||
|
type: list
|
||||||
|
sample: [external, internal]
|
||||||
|
undefined_zones:
|
||||||
|
description:
|
||||||
|
- A list of undefined zones in C(zones) option.
|
||||||
|
- C(undefined_zones) will be ignored for gathering process.
|
||||||
|
returned: success
|
||||||
|
type: list
|
||||||
|
sample: [foo, bar]
|
||||||
|
firewalld_info:
|
||||||
|
description:
|
||||||
|
- Returns various information about firewalld configuration.
|
||||||
|
returned: success
|
||||||
|
type: complex
|
||||||
|
contains:
|
||||||
|
version:
|
||||||
|
description:
|
||||||
|
- The version information of firewalld.
|
||||||
|
returned: success
|
||||||
|
type: str
|
||||||
|
sample: 0.8.2
|
||||||
|
default_zones:
|
||||||
|
description:
|
||||||
|
- The zone name of default zone.
|
||||||
|
returned: success
|
||||||
|
type: str
|
||||||
|
sample: public
|
||||||
|
zones:
|
||||||
|
description:
|
||||||
|
- A dict of zones to gather information.
|
||||||
|
returned: success
|
||||||
|
type: complex
|
||||||
|
contains:
|
||||||
|
zone:
|
||||||
|
description:
|
||||||
|
- The zone name registered in firewalld.
|
||||||
|
returned: success
|
||||||
|
type: complex
|
||||||
|
sample: external
|
||||||
|
contains:
|
||||||
|
target:
|
||||||
|
description:
|
||||||
|
- A list of services in the zone.
|
||||||
|
returned: success
|
||||||
|
type: str
|
||||||
|
sample: ACCEPT
|
||||||
|
icmp_block_inversion:
|
||||||
|
description:
|
||||||
|
- The ICMP block inversion to block
|
||||||
|
all ICMP requests.
|
||||||
|
returned: success
|
||||||
|
type: bool
|
||||||
|
sample: false
|
||||||
|
interfaces:
|
||||||
|
description:
|
||||||
|
- A list of network interfaces.
|
||||||
|
returned: success
|
||||||
|
type: list
|
||||||
|
sample:
|
||||||
|
- 'eth0'
|
||||||
|
- 'eth1'
|
||||||
|
sources:
|
||||||
|
description:
|
||||||
|
- A list of source network address.
|
||||||
|
returned: success
|
||||||
|
type: list
|
||||||
|
sample:
|
||||||
|
- '172.16.30.0/24'
|
||||||
|
- '172.16.31.0/24'
|
||||||
|
services:
|
||||||
|
description:
|
||||||
|
- A list of network services.
|
||||||
|
returned: success
|
||||||
|
type: list
|
||||||
|
sample:
|
||||||
|
- 'dhcp'
|
||||||
|
- 'dns'
|
||||||
|
- 'ssh'
|
||||||
|
ports:
|
||||||
|
description:
|
||||||
|
- A list of network port with protocol.
|
||||||
|
returned: success
|
||||||
|
type: list
|
||||||
|
sample:
|
||||||
|
- - "22"
|
||||||
|
- "tcp"
|
||||||
|
- - "80"
|
||||||
|
- "tcp"
|
||||||
|
protocols:
|
||||||
|
description:
|
||||||
|
- A list of network protocol.
|
||||||
|
returned: success
|
||||||
|
type: list
|
||||||
|
sample:
|
||||||
|
- "icmp"
|
||||||
|
- "ipv6-icmp"
|
||||||
|
forward:
|
||||||
|
description:
|
||||||
|
- The network interface forwarding.
|
||||||
|
- This parameter supports on python-firewall
|
||||||
|
0.9.0(or later) and is not collected in earlier
|
||||||
|
versions.
|
||||||
|
returned: success
|
||||||
|
type: bool
|
||||||
|
sample: false
|
||||||
|
masquerade:
|
||||||
|
description:
|
||||||
|
- The network interface masquerading.
|
||||||
|
returned: success
|
||||||
|
type: bool
|
||||||
|
sample: false
|
||||||
|
forward_ports:
|
||||||
|
description:
|
||||||
|
- A list of forwarding port pair with protocol.
|
||||||
|
returned: success
|
||||||
|
type: list
|
||||||
|
sample:
|
||||||
|
- "icmp"
|
||||||
|
- "ipv6-icmp"
|
||||||
|
source_ports:
|
||||||
|
description:
|
||||||
|
- A list of network source port with protocol.
|
||||||
|
returned: success
|
||||||
|
type: list
|
||||||
|
sample:
|
||||||
|
- - "30000"
|
||||||
|
- "tcp"
|
||||||
|
- - "30001"
|
||||||
|
- "tcp"
|
||||||
|
icmp_blocks:
|
||||||
|
description:
|
||||||
|
- A list of blocking icmp protocol.
|
||||||
|
returned: success
|
||||||
|
type: list
|
||||||
|
sample:
|
||||||
|
- "echo-request"
|
||||||
|
rich_rules:
|
||||||
|
description:
|
||||||
|
- A list of rich language rule.
|
||||||
|
returned: success
|
||||||
|
type: list
|
||||||
|
sample:
|
||||||
|
- "rule protocol value=\"icmp\" reject"
|
||||||
|
- "rule priority=\"32767\" reject"
|
||||||
|
'''
|
||||||
|
|
||||||
|
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_collections.ansible.posix.plugins.module_utils.version import StrictVersion
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
import dbus
|
||||||
|
HAS_DBUS = True
|
||||||
|
except ImportError:
|
||||||
|
HAS_DBUS = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
import firewall.client as fw_client
|
||||||
|
import firewall.config as fw_config
|
||||||
|
HAS_FIREWALLD = True
|
||||||
|
except ImportError:
|
||||||
|
HAS_FIREWALLD = False
|
||||||
|
|
||||||
|
|
||||||
|
def get_version():
|
||||||
|
return fw_config.VERSION
|
||||||
|
|
||||||
|
|
||||||
|
def get_active_zones(client):
|
||||||
|
return client.getActiveZones().keys()
|
||||||
|
|
||||||
|
|
||||||
|
def get_all_zones(client):
|
||||||
|
return client.getZones()
|
||||||
|
|
||||||
|
|
||||||
|
def get_default_zone(client):
|
||||||
|
return client.getDefaultZone()
|
||||||
|
|
||||||
|
|
||||||
|
def get_zone_settings(client, zone):
|
||||||
|
return client.getZoneSettings(zone)
|
||||||
|
|
||||||
|
|
||||||
|
def get_zone_target(zone_settings):
|
||||||
|
return zone_settings.getTarget()
|
||||||
|
|
||||||
|
|
||||||
|
def get_zone_icmp_block_inversion(zone_settings):
|
||||||
|
return zone_settings.getIcmpBlockInversion()
|
||||||
|
|
||||||
|
|
||||||
|
def get_zone_interfaces(zone_settings):
|
||||||
|
return zone_settings.getInterfaces()
|
||||||
|
|
||||||
|
|
||||||
|
def get_zone_sources(zone_settings):
|
||||||
|
return zone_settings.getSources()
|
||||||
|
|
||||||
|
|
||||||
|
def get_zone_services(zone_settings):
|
||||||
|
return zone_settings.getServices()
|
||||||
|
|
||||||
|
|
||||||
|
def get_zone_ports(zone_settings):
|
||||||
|
return zone_settings.getPorts()
|
||||||
|
|
||||||
|
|
||||||
|
def get_zone_protocols(zone_settings):
|
||||||
|
return zone_settings.getProtocols()
|
||||||
|
|
||||||
|
|
||||||
|
# This function supports python-firewall 0.9.0(or later).
|
||||||
|
def get_zone_forward(zone_settings):
|
||||||
|
return zone_settings.getForward()
|
||||||
|
|
||||||
|
|
||||||
|
def get_zone_masquerade(zone_settings):
|
||||||
|
return zone_settings.getMasquerade()
|
||||||
|
|
||||||
|
|
||||||
|
def get_zone_forward_ports(zone_settings):
|
||||||
|
return zone_settings.getForwardPorts()
|
||||||
|
|
||||||
|
|
||||||
|
def get_zone_source_ports(zone_settings):
|
||||||
|
return zone_settings.getSourcePorts()
|
||||||
|
|
||||||
|
|
||||||
|
def get_zone_icmp_blocks(zone_settings):
|
||||||
|
return zone_settings.getIcmpBlocks()
|
||||||
|
|
||||||
|
|
||||||
|
def get_zone_rich_rules(zone_settings):
|
||||||
|
return zone_settings.getRichRules()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
module_args = dict(
|
||||||
|
active_zones=dict(required=False, type='bool', default=False),
|
||||||
|
zones=dict(required=False, type='list', elements='str'),
|
||||||
|
)
|
||||||
|
|
||||||
|
module = AnsibleModule(
|
||||||
|
argument_spec=module_args,
|
||||||
|
supports_check_mode=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
firewalld_info = dict()
|
||||||
|
result = dict(
|
||||||
|
changed=False,
|
||||||
|
active_zones=module.params['active_zones'],
|
||||||
|
collected_zones=list(),
|
||||||
|
undefined_zones=list(),
|
||||||
|
warnings=list(),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Exit with failure message if requirements modules are not installed.
|
||||||
|
if not HAS_DBUS:
|
||||||
|
module.fail_json(msg=missing_required_lib('python-dbus'))
|
||||||
|
if not HAS_FIREWALLD:
|
||||||
|
module.fail_json(msg=missing_required_lib('python-firewall'))
|
||||||
|
|
||||||
|
# If you want to show warning messages in the task running process,
|
||||||
|
# you can append the message to the 'warn' list.
|
||||||
|
warn = list()
|
||||||
|
|
||||||
|
try:
|
||||||
|
client = fw_client.FirewallClient()
|
||||||
|
|
||||||
|
# Gather general information of firewalld.
|
||||||
|
firewalld_info['version'] = get_version()
|
||||||
|
firewalld_info['default_zone'] = get_default_zone(client)
|
||||||
|
|
||||||
|
# Gather information for zones.
|
||||||
|
zones_info = dict()
|
||||||
|
collect_zones = list()
|
||||||
|
ignore_zones = list()
|
||||||
|
if module.params['active_zones']:
|
||||||
|
collect_zones = get_active_zones(client)
|
||||||
|
elif module.params['zones']:
|
||||||
|
all_zones = get_all_zones(client)
|
||||||
|
specified_zones = module.params['zones']
|
||||||
|
collect_zones = list(set(specified_zones) & set(all_zones))
|
||||||
|
ignore_zones = list(set(specified_zones) - set(collect_zones))
|
||||||
|
warn.append(
|
||||||
|
'Please note: zone:(%s) have been ignored in the gathering process.' % ','.join(ignore_zones))
|
||||||
|
else:
|
||||||
|
collect_zones = get_all_zones(client)
|
||||||
|
|
||||||
|
for zone in collect_zones:
|
||||||
|
# Gather settings for each zone based on the output of
|
||||||
|
# 'firewall-cmd --info-zone=<ZONE>' command.
|
||||||
|
zone_info = dict()
|
||||||
|
zone_settings = get_zone_settings(client, zone)
|
||||||
|
zone_info['target'] = get_zone_target(zone_settings)
|
||||||
|
zone_info['icmp_block_inversion'] = get_zone_icmp_block_inversion(zone_settings)
|
||||||
|
zone_info['interfaces'] = get_zone_interfaces(zone_settings)
|
||||||
|
zone_info['sources'] = get_zone_sources(zone_settings)
|
||||||
|
zone_info['services'] = get_zone_services(zone_settings)
|
||||||
|
zone_info['ports'] = get_zone_ports(zone_settings)
|
||||||
|
zone_info['protocols'] = get_zone_protocols(zone_settings)
|
||||||
|
zone_info['masquerade'] = get_zone_masquerade(zone_settings)
|
||||||
|
zone_info['forward_ports'] = get_zone_forward_ports(zone_settings)
|
||||||
|
zone_info['source_ports'] = get_zone_source_ports(zone_settings)
|
||||||
|
zone_info['icmp_blocks'] = get_zone_icmp_blocks(zone_settings)
|
||||||
|
zone_info['rich_rules'] = get_zone_rich_rules(zone_settings)
|
||||||
|
|
||||||
|
# The 'forward' parameter supports on python-firewall 0.9.0(or later).
|
||||||
|
if StrictVersion(firewalld_info['version']) >= StrictVersion('0.9.0'):
|
||||||
|
zone_info['forward'] = get_zone_forward(zone_settings)
|
||||||
|
|
||||||
|
zones_info[zone] = zone_info
|
||||||
|
firewalld_info['zones'] = zones_info
|
||||||
|
except AttributeError as e:
|
||||||
|
module.fail_json(msg=('firewalld probably not be running, Or the following method '
|
||||||
|
'is not supported with your python-firewall version. (Error: %s)') % to_native(e))
|
||||||
|
except dbus.exceptions.DBusException as e:
|
||||||
|
module.fail_json(msg=('Unable to gather firewalld settings.'
|
||||||
|
' You may need to run as the root user or'
|
||||||
|
' use become. (Error: %s)' % to_native(e)))
|
||||||
|
|
||||||
|
result['collected_zones'] = collect_zones
|
||||||
|
result['undefined_zones'] = ignore_zones
|
||||||
|
result['firewalld_info'] = firewalld_info
|
||||||
|
result['warnings'] = warn
|
||||||
|
module.exit_json(**result)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
@@ -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
|
||||||
@@ -93,7 +93,13 @@ options:
|
|||||||
boot:
|
boot:
|
||||||
description:
|
description:
|
||||||
- Determines if the filesystem should be mounted on boot.
|
- Determines if the filesystem should be mounted on boot.
|
||||||
- Only applies to Solaris systems.
|
- Only applies to Solaris and Linux systems.
|
||||||
|
- For Solaris systems, C(true) will set C(yes) as the value of mount at boot
|
||||||
|
in I(/etc/vfstab).
|
||||||
|
- For Linux, FreeBSD, NetBSD and OpenBSD systems, C(false) will add C(noauto)
|
||||||
|
to mount options in I(/etc/fstab).
|
||||||
|
- To avoid mount option conflicts, if C(noauto) specified in C(opts),
|
||||||
|
mount module will ignore C(boot).
|
||||||
type: bool
|
type: bool
|
||||||
default: yes
|
default: yes
|
||||||
backup:
|
backup:
|
||||||
@@ -166,12 +172,20 @@ 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
|
||||||
|
fstype: nfs
|
||||||
|
|
||||||
|
- name: Mount NFS volumes with noauto according to boot option
|
||||||
|
ansible.posix.mount:
|
||||||
|
src: 192.168.1.100:/nfs/ssd/shared_data
|
||||||
|
path: /mnt/shared_data
|
||||||
|
opts: rw,sync,hard
|
||||||
|
boot: no
|
||||||
state: mounted
|
state: mounted
|
||||||
fstype: nfs
|
fstype: nfs
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
import errno
|
import errno
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
@@ -180,11 +194,15 @@ from ansible.module_utils.basic import AnsibleModule
|
|||||||
from ansible_collections.ansible.posix.plugins.module_utils.mount import ismount
|
from ansible_collections.ansible.posix.plugins.module_utils.mount import ismount
|
||||||
from ansible.module_utils.six import iteritems
|
from ansible.module_utils.six import iteritems
|
||||||
from ansible.module_utils._text import to_bytes, to_native
|
from ansible.module_utils._text import to_bytes, to_native
|
||||||
|
from ansible.module_utils.parsing.convert_bool import boolean
|
||||||
|
|
||||||
|
|
||||||
def write_fstab(module, lines, path):
|
def write_fstab(module, lines, path):
|
||||||
|
|
||||||
if module.params['backup']:
|
if module.params['backup']:
|
||||||
module.backup_local(path)
|
backup_file = module.backup_local(path)
|
||||||
|
else:
|
||||||
|
backup_file = ""
|
||||||
|
|
||||||
fs_w = open(path, 'w')
|
fs_w = open(path, 'w')
|
||||||
|
|
||||||
@@ -194,6 +212,8 @@ def write_fstab(module, lines, path):
|
|||||||
fs_w.flush()
|
fs_w.flush()
|
||||||
fs_w.close()
|
fs_w.close()
|
||||||
|
|
||||||
|
return backup_file
|
||||||
|
|
||||||
|
|
||||||
def _escape_fstab(v):
|
def _escape_fstab(v):
|
||||||
"""Escape invalid characters in fstab fields.
|
"""Escape invalid characters in fstab fields.
|
||||||
@@ -206,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').
|
||||||
@@ -226,7 +246,7 @@ def _set_mount_save_old(module, args):
|
|||||||
old_lines = []
|
old_lines = []
|
||||||
exists = False
|
exists = False
|
||||||
changed = False
|
changed = False
|
||||||
escaped_args = dict([(k, _escape_fstab(v)) for k, v in iteritems(args)])
|
escaped_args = dict([(k, _escape_fstab(v)) for k, v in iteritems(args) if k != 'warnings'])
|
||||||
new_line = '%(src)s %(name)s %(fstype)s %(opts)s %(dump)s %(passno)s\n'
|
new_line = '%(src)s %(name)s %(fstype)s %(opts)s %(dump)s %(passno)s\n'
|
||||||
|
|
||||||
if platform.system() == 'SunOS':
|
if platform.system() == 'SunOS':
|
||||||
@@ -234,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():
|
||||||
@@ -316,7 +340,7 @@ def _set_mount_save_old(module, args):
|
|||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
if changed and not module.check_mode:
|
if changed and not module.check_mode:
|
||||||
write_fstab(module, to_write, args['fstab'])
|
args['backup_file'] = write_fstab(module, to_write, args['fstab'])
|
||||||
|
|
||||||
return (args['name'], old_lines, changed)
|
return (args['name'], old_lines, changed)
|
||||||
|
|
||||||
@@ -643,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'),
|
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']),
|
||||||
@@ -672,7 +696,8 @@ def main():
|
|||||||
opts='-',
|
opts='-',
|
||||||
passno='-',
|
passno='-',
|
||||||
fstab=module.params['fstab'],
|
fstab=module.params['fstab'],
|
||||||
boot='yes'
|
boot='yes' if module.params['boot'] else 'no',
|
||||||
|
warnings=[]
|
||||||
)
|
)
|
||||||
if args['fstab'] is None:
|
if args['fstab'] is None:
|
||||||
args['fstab'] = '/etc/vfstab'
|
args['fstab'] = '/etc/vfstab'
|
||||||
@@ -682,7 +707,9 @@ def main():
|
|||||||
opts='defaults',
|
opts='defaults',
|
||||||
dump='0',
|
dump='0',
|
||||||
passno='0',
|
passno='0',
|
||||||
fstab=module.params['fstab']
|
fstab=module.params['fstab'],
|
||||||
|
boot='yes',
|
||||||
|
warnings=[]
|
||||||
)
|
)
|
||||||
if args['fstab'] is None:
|
if args['fstab'] is None:
|
||||||
args['fstab'] = '/etc/fstab'
|
args['fstab'] = '/etc/fstab'
|
||||||
@@ -691,6 +718,7 @@ def main():
|
|||||||
if platform.system() == 'FreeBSD':
|
if platform.system() == 'FreeBSD':
|
||||||
args['opts'] = 'rw'
|
args['opts'] = 'rw'
|
||||||
|
|
||||||
|
args['backup_file'] = ""
|
||||||
linux_mounts = []
|
linux_mounts = []
|
||||||
|
|
||||||
# Cache all mounts here in order we have consistent results if we need to
|
# Cache all mounts here in order we have consistent results if we need to
|
||||||
@@ -699,14 +727,27 @@ def main():
|
|||||||
linux_mounts = get_linux_mounts(module)
|
linux_mounts = get_linux_mounts(module)
|
||||||
|
|
||||||
if linux_mounts is None:
|
if linux_mounts is None:
|
||||||
args['warnings'] = (
|
args['warnings'].append('Cannot open file /proc/self/mountinfo.'
|
||||||
'Cannot open file /proc/self/mountinfo. '
|
' Bind mounts might be misinterpreted.')
|
||||||
'Bind mounts might be misinterpreted.')
|
|
||||||
|
|
||||||
# Override defaults with user specified params
|
# Override defaults with user specified params
|
||||||
for key in ('src', 'fstype', 'passno', 'opts', 'dump', 'fstab'):
|
for key in ('src', 'fstype', 'passno', 'opts', 'dump', 'fstab'):
|
||||||
if module.params[key] is not None:
|
if module.params[key] is not None:
|
||||||
args[key] = module.params[key]
|
args[key] = module.params[key]
|
||||||
|
if platform.system().lower() == 'linux' or platform.system().lower().endswith('bsd'):
|
||||||
|
# Linux, FreeBSD, NetBSD and OpenBSD have 'noauto' as mount option to
|
||||||
|
# handle mount on boot. To avoid mount option conflicts, if 'noauto'
|
||||||
|
# specified in 'opts', mount module will ignore 'boot'.
|
||||||
|
opts = args['opts'].split(',')
|
||||||
|
if 'noauto' in opts:
|
||||||
|
args['warnings'].append("Ignore the 'boot' due to 'opts' contains 'noauto'.")
|
||||||
|
elif not module.params['boot']:
|
||||||
|
args['boot'] = 'no'
|
||||||
|
if 'defaults' in opts:
|
||||||
|
args['warnings'].append("Ignore the 'boot' due to 'opts' contains 'defaults'.")
|
||||||
|
else:
|
||||||
|
opts.append('noauto')
|
||||||
|
args['opts'] = ','.join(opts)
|
||||||
|
|
||||||
# If fstab file does not exist, we first need to create it. This mainly
|
# If fstab file does not exist, we first need to create it. This mainly
|
||||||
# happens when fstab option is passed to the module.
|
# happens when fstab option is passed to the module.
|
||||||
@@ -834,6 +875,10 @@ def main():
|
|||||||
else:
|
else:
|
||||||
module.fail_json(msg='Unexpected position reached')
|
module.fail_json(msg='Unexpected position reached')
|
||||||
|
|
||||||
|
# If the managed node is Solaris, convert the boot value type to Boolean
|
||||||
|
# to match the type of return value with the module argument.
|
||||||
|
if platform.system().lower() == 'sunos':
|
||||||
|
args['boot'] = boolean(args['boot'])
|
||||||
module.exit_json(changed=changed, **args)
|
module.exit_json(changed=changed, **args)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from __future__ import absolute_import, division, print_function
|
|||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = r'''
|
||||||
---
|
---
|
||||||
module: seboolean
|
module: seboolean
|
||||||
short_description: Toggles SELinux booleans
|
short_description: Toggles SELinux booleans
|
||||||
@@ -19,6 +19,7 @@ options:
|
|||||||
description:
|
description:
|
||||||
- Name of the boolean to configure.
|
- Name of the boolean to configure.
|
||||||
required: true
|
required: true
|
||||||
|
type: str
|
||||||
persistent:
|
persistent:
|
||||||
description:
|
description:
|
||||||
- Set to C(yes) if the boolean setting should survive a reboot.
|
- Set to C(yes) if the boolean setting should survive a reboot.
|
||||||
@@ -39,6 +40,7 @@ notes:
|
|||||||
requirements:
|
requirements:
|
||||||
- libselinux-python
|
- libselinux-python
|
||||||
- libsemanage-python
|
- libsemanage-python
|
||||||
|
- python3-libsemanage
|
||||||
author:
|
author:
|
||||||
- Stephen Fromm (@sfromm)
|
- Stephen Fromm (@sfromm)
|
||||||
'''
|
'''
|
||||||
@@ -283,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']
|
||||||
|
|
||||||
|
|||||||
@@ -20,17 +20,27 @@ version_added: "1.0.0"
|
|||||||
options:
|
options:
|
||||||
policy:
|
policy:
|
||||||
description:
|
description:
|
||||||
- The name of the SELinux policy to use (e.g. C(targeted)) will be required if state is not C(disabled).
|
- The name of the SELinux policy to use (e.g. C(targeted)) will be required if I(state) is not C(disabled).
|
||||||
|
type: str
|
||||||
state:
|
state:
|
||||||
description:
|
description:
|
||||||
- The SELinux mode.
|
- The SELinux mode.
|
||||||
required: true
|
required: true
|
||||||
choices: [ disabled, enforcing, permissive ]
|
choices: [ disabled, enforcing, permissive ]
|
||||||
|
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.
|
||||||
default: /etc/selinux/config
|
default: /etc/selinux/config
|
||||||
aliases: [ conf, file ]
|
aliases: [ conf, file ]
|
||||||
|
type: str
|
||||||
requirements: [ libselinux-python ]
|
requirements: [ libselinux-python ]
|
||||||
author:
|
author:
|
||||||
- Derek Carter (@goozbach) <goozbach@friocorte.com>
|
- Derek Carter (@goozbach) <goozbach@friocorte.com>
|
||||||
@@ -94,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
|
||||||
|
|
||||||
|
|
||||||
@@ -116,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
|
||||||
@@ -150,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)
|
||||||
@@ -178,8 +228,9 @@ def main():
|
|||||||
module = AnsibleModule(
|
module = AnsibleModule(
|
||||||
argument_spec=dict(
|
argument_spec=dict(
|
||||||
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,
|
||||||
)
|
)
|
||||||
@@ -193,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:
|
||||||
@@ -212,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':
|
||||||
@@ -266,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)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -38,9 +38,8 @@ options:
|
|||||||
description:
|
description:
|
||||||
- Port number for ssh on the destination host.
|
- Port number for ssh on the destination host.
|
||||||
- Prior to Ansible 2.0, the ansible_ssh_port inventory var took precedence over this value.
|
- Prior to Ansible 2.0, the ansible_ssh_port inventory var took precedence over this value.
|
||||||
- This parameter defaults to the value of C(ansible_ssh_port) or C(ansible_port),
|
- This parameter defaults to the value of C(ansible_port), the C(remote_port) config setting
|
||||||
the C(remote_port) config setting or the value from ssh client configuration
|
or the value from ssh client configuration if none of the former have been set.
|
||||||
if none of the former have been set.
|
|
||||||
type: int
|
type: int
|
||||||
mode:
|
mode:
|
||||||
description:
|
description:
|
||||||
@@ -74,9 +73,9 @@ options:
|
|||||||
default: no
|
default: no
|
||||||
delete:
|
delete:
|
||||||
description:
|
description:
|
||||||
- Delete files in C(dest) that don't exist (after transfer, not before) in the C(src) path.
|
- Delete files in I(dest) that do not exist (after transfer, not before) in the I(src) path.
|
||||||
- This option requires C(recursive=yes).
|
- This option requires I(recursive=yes).
|
||||||
- This option ignores excluded files and behaves like the rsync opt --delete-excluded.
|
- This option ignores excluded files and behaves like the rsync opt C(--delete-after).
|
||||||
type: bool
|
type: bool
|
||||||
default: no
|
default: no
|
||||||
dirs:
|
dirs:
|
||||||
@@ -138,7 +137,19 @@ options:
|
|||||||
default: yes
|
default: yes
|
||||||
use_ssh_args:
|
use_ssh_args:
|
||||||
description:
|
description:
|
||||||
- Use the ssh_args specified in ansible.cfg.
|
- In Ansible 2.10 and lower, it uses the ssh_args specified in C(ansible.cfg).
|
||||||
|
- In Ansible 2.11 and onwards, when set to C(true), it uses all SSH connection configurations like
|
||||||
|
C(ansible_ssh_args), C(ansible_ssh_common_args), and C(ansible_ssh_extra_args).
|
||||||
|
type: bool
|
||||||
|
default: no
|
||||||
|
ssh_connection_multiplexing:
|
||||||
|
description:
|
||||||
|
- SSH connection multiplexing for rsync is disabled by default to prevent misconfigured ControlSockets from resulting in failed SSH connections.
|
||||||
|
This is accomplished by setting the SSH C(ControlSocket) to C(none).
|
||||||
|
- Set this option to C(yes) to allow multiplexing and reduce SSH connection overhead.
|
||||||
|
- Note that simply setting this option to C(yes) is not enough;
|
||||||
|
You must also configure SSH connection multiplexing in your SSH client config by setting values for
|
||||||
|
C(ControlMaster), C(ControlPersist) and C(ControlPath).
|
||||||
type: bool
|
type: bool
|
||||||
default: no
|
default: no
|
||||||
rsync_opts:
|
rsync_opts:
|
||||||
@@ -147,6 +158,7 @@ options:
|
|||||||
- Note that an empty string in C(rsync_opts) will end up transfer the current working directory.
|
- Note that an empty string in C(rsync_opts) will end up transfer the current working directory.
|
||||||
type: list
|
type: list
|
||||||
default:
|
default:
|
||||||
|
elements: str
|
||||||
partial:
|
partial:
|
||||||
description:
|
description:
|
||||||
- Tells rsync to keep the partial file which should make a subsequent transfer of the rest of the file much faster.
|
- Tells rsync to keep the partial file which should make a subsequent transfer of the rest of the file much faster.
|
||||||
@@ -166,6 +178,15 @@ options:
|
|||||||
- Add a destination to hard link against during the rsync.
|
- Add a destination to hard link against during the rsync.
|
||||||
type: list
|
type: list
|
||||||
default:
|
default:
|
||||||
|
elements: str
|
||||||
|
delay_updates:
|
||||||
|
description:
|
||||||
|
- This option puts the temporary file from each updated file into a holding directory until the end of the transfer,
|
||||||
|
at which time all the files are renamed into place in rapid succession.
|
||||||
|
type: bool
|
||||||
|
default: yes
|
||||||
|
version_added: '1.3.0'
|
||||||
|
|
||||||
notes:
|
notes:
|
||||||
- rsync must be installed on both the local and remote host.
|
- rsync must be installed on both the local and remote host.
|
||||||
- For the C(synchronize) module, the "local host" is the host `the synchronize task originates on`, and the "destination host" is the host
|
- For the C(synchronize) module, the "local host" is the host `the synchronize task originates on`, and the "destination host" is the host
|
||||||
@@ -186,8 +207,8 @@ notes:
|
|||||||
- Inspect the verbose output to validate the destination user/host/path are what was expected.
|
- Inspect the verbose output to validate the destination user/host/path are what was expected.
|
||||||
- To exclude files and directories from being synchronized, you may add C(.rsync-filter) files to the source directory.
|
- To exclude files and directories from being synchronized, you may add C(.rsync-filter) files to the source directory.
|
||||||
- rsync daemon must be up and running with correct permission when using rsync protocol in source or destination path.
|
- rsync daemon must be up and running with correct permission when using rsync protocol in source or destination path.
|
||||||
- The C(synchronize) module forces `--delay-updates` to avoid leaving a destination in a broken in-between state if the underlying rsync process
|
- The C(synchronize) module enables `--delay-updates` by default to avoid leaving a destination in a broken in-between state if the underlying rsync process
|
||||||
encounters an error. Those synchronizing large numbers of files that are willing to trade safety for performance should call rsync directly.
|
encounters an error. Those synchronizing large numbers of files that are willing to trade safety for performance should disable this option.
|
||||||
- link_destination is subject to the same limitations as the underlying rsync daemon. Hard links are only preserved if the relative subtrees
|
- link_destination is subject to the same limitations as the underlying rsync daemon. Hard links are only preserved if the relative subtrees
|
||||||
of the source and destination are the same. Attempts to hardlink into a directory that is a subdirectory of the source will be prevented.
|
of the source and destination are the same. Attempts to hardlink into a directory that is a subdirectory of the source will be prevented.
|
||||||
seealso:
|
seealso:
|
||||||
@@ -314,7 +335,7 @@ EXAMPLES = r'''
|
|||||||
# Specify the rsync binary to use on remote host and on local host
|
# Specify the rsync binary to use on remote host and on local host
|
||||||
- hosts: groupofhosts
|
- hosts: groupofhosts
|
||||||
vars:
|
vars:
|
||||||
ansible_rsync_path: /usr/gnu/bin/rsync
|
ansible_rsync_path: /usr/gnu/bin/rsync
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
- name: copy /tmp/localpath/ to remote location /tmp/remotepath
|
- name: copy /tmp/localpath/ to remote location /tmp/remotepath
|
||||||
@@ -390,12 +411,14 @@ def main():
|
|||||||
group=dict(type='bool'),
|
group=dict(type='bool'),
|
||||||
set_remote_user=dict(type='bool', default=True),
|
set_remote_user=dict(type='bool', default=True),
|
||||||
rsync_timeout=dict(type='int', default=0),
|
rsync_timeout=dict(type='int', default=0),
|
||||||
rsync_opts=dict(type='list', default=[]),
|
rsync_opts=dict(type='list', default=[], elements='str'),
|
||||||
ssh_args=dict(type='str'),
|
ssh_args=dict(type='str'),
|
||||||
|
ssh_connection_multiplexing=dict(type='bool', default=False),
|
||||||
partial=dict(type='bool', default=False),
|
partial=dict(type='bool', default=False),
|
||||||
verify_host=dict(type='bool', default=False),
|
verify_host=dict(type='bool', default=False),
|
||||||
|
delay_updates=dict(type='bool', default=True),
|
||||||
mode=dict(type='str', default='push', choices=['pull', 'push']),
|
mode=dict(type='str', default='push', choices=['pull', 'push']),
|
||||||
link_dest=dict(type='list')
|
link_dest=dict(type='list', elements='str'),
|
||||||
),
|
),
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
)
|
)
|
||||||
@@ -432,13 +455,15 @@ def main():
|
|||||||
group = module.params['group']
|
group = module.params['group']
|
||||||
rsync_opts = module.params['rsync_opts']
|
rsync_opts = module.params['rsync_opts']
|
||||||
ssh_args = module.params['ssh_args']
|
ssh_args = module.params['ssh_args']
|
||||||
|
ssh_connection_multiplexing = module.params['ssh_connection_multiplexing']
|
||||||
verify_host = module.params['verify_host']
|
verify_host = module.params['verify_host']
|
||||||
link_dest = module.params['link_dest']
|
link_dest = module.params['link_dest']
|
||||||
|
delay_updates = module.params['delay_updates']
|
||||||
|
|
||||||
if '/' not in rsync:
|
if '/' not in rsync:
|
||||||
rsync = module.get_bin_path(rsync, required=True)
|
rsync = module.get_bin_path(rsync, required=True)
|
||||||
|
|
||||||
cmd = [rsync, '--delay-updates', '-F']
|
cmd = [rsync]
|
||||||
_sshpass_pipe = None
|
_sshpass_pipe = None
|
||||||
if rsync_password:
|
if rsync_password:
|
||||||
try:
|
try:
|
||||||
@@ -449,6 +474,9 @@ def main():
|
|||||||
)
|
)
|
||||||
_sshpass_pipe = os.pipe()
|
_sshpass_pipe = os.pipe()
|
||||||
cmd = ['sshpass', '-d' + to_native(_sshpass_pipe[0], errors='surrogate_or_strict')] + cmd
|
cmd = ['sshpass', '-d' + to_native(_sshpass_pipe[0], errors='surrogate_or_strict')] + cmd
|
||||||
|
if delay_updates:
|
||||||
|
cmd.append('--delay-updates')
|
||||||
|
cmd.append('-F')
|
||||||
if compress:
|
if compress:
|
||||||
cmd.append('--compress')
|
cmd.append('--compress')
|
||||||
if rsync_timeout:
|
if rsync_timeout:
|
||||||
@@ -507,7 +535,9 @@ def main():
|
|||||||
|
|
||||||
# if the user has not supplied an --rsh option go ahead and add ours
|
# if the user has not supplied an --rsh option go ahead and add ours
|
||||||
if not has_rsh:
|
if not has_rsh:
|
||||||
ssh_cmd = [module.get_bin_path('ssh', required=True), '-S', 'none']
|
ssh_cmd = [module.get_bin_path('ssh', required=True)]
|
||||||
|
if not ssh_connection_multiplexing:
|
||||||
|
ssh_cmd.extend(['-S', 'none'])
|
||||||
if private_key is not None:
|
if private_key is not None:
|
||||||
ssh_cmd.extend(['-i', private_key])
|
ssh_cmd.extend(['-i', private_key])
|
||||||
# If the user specified a port value
|
# If the user specified a port value
|
||||||
@@ -520,10 +550,10 @@ def main():
|
|||||||
ssh_cmd_str = ' '.join(shlex_quote(arg) for arg in ssh_cmd)
|
ssh_cmd_str = ' '.join(shlex_quote(arg) for arg in ssh_cmd)
|
||||||
if ssh_args:
|
if ssh_args:
|
||||||
ssh_cmd_str += ' %s' % ssh_args
|
ssh_cmd_str += ' %s' % ssh_args
|
||||||
cmd.append('--rsh=%s' % ssh_cmd_str)
|
cmd.append('--rsh=%s' % shlex_quote(ssh_cmd_str))
|
||||||
|
|
||||||
if rsync_path:
|
if rsync_path:
|
||||||
cmd.append('--rsync-path=%s' % rsync_path)
|
cmd.append('--rsync-path=%s' % shlex_quote(rsync_path))
|
||||||
|
|
||||||
if rsync_opts:
|
if rsync_opts:
|
||||||
if '' in rsync_opts:
|
if '' in rsync_opts:
|
||||||
@@ -549,7 +579,7 @@ def main():
|
|||||||
cmd.append('--link-dest=%s' % link_path)
|
cmd.append('--link-dest=%s' % link_path)
|
||||||
|
|
||||||
changed_marker = '<<CHANGED>>'
|
changed_marker = '<<CHANGED>>'
|
||||||
cmd.append('--out-format=' + changed_marker + '%i %n%L')
|
cmd.append('--out-format=%s' % shlex_quote(changed_marker + '%i %n%L'))
|
||||||
|
|
||||||
# expand the paths
|
# expand the paths
|
||||||
if '@' not in source:
|
if '@' not in source:
|
||||||
@@ -557,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
|
||||||
@@ -573,10 +603,10 @@ def main():
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
(rc, out, err) = module.run_command(
|
(rc, out, err) = module.run_command(
|
||||||
cmd, pass_fds=_sshpass_pipe,
|
cmdstr, pass_fds=_sshpass_pipe,
|
||||||
before_communicate_callback=_write_password_to_pipe)
|
before_communicate_callback=_write_password_to_pipe)
|
||||||
else:
|
else:
|
||||||
(rc, out, err) = module.run_command(cmd)
|
(rc, out, err) = module.run_command(cmdstr)
|
||||||
|
|
||||||
if rc:
|
if rc:
|
||||||
return module.fail_json(msg=err, rc=rc, cmd=cmdstr)
|
return module.fail_json(msg=err, rc=rc, cmd=cmdstr)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ from __future__ import absolute_import, division, print_function
|
|||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = r'''
|
||||||
---
|
---
|
||||||
module: sysctl
|
module: sysctl
|
||||||
short_description: Manage entries in sysctl.conf.
|
short_description: Manage entries in sysctl.conf.
|
||||||
@@ -19,18 +19,21 @@ version_added: "1.0.0"
|
|||||||
options:
|
options:
|
||||||
name:
|
name:
|
||||||
description:
|
description:
|
||||||
- The dot-separated path (aka I(key)) specifying the sysctl variable.
|
- The dot-separated path (also known as I(key)) specifying the sysctl variable.
|
||||||
required: true
|
required: true
|
||||||
aliases: [ 'key' ]
|
aliases: [ 'key' ]
|
||||||
|
type: str
|
||||||
value:
|
value:
|
||||||
description:
|
description:
|
||||||
- Desired value of the sysctl key.
|
- Desired value of the sysctl key.
|
||||||
aliases: [ 'val' ]
|
aliases: [ 'val' ]
|
||||||
|
type: str
|
||||||
state:
|
state:
|
||||||
description:
|
description:
|
||||||
- Whether the entry should be present or absent in the sysctl file.
|
- Whether the entry should be present or absent in the sysctl file.
|
||||||
choices: [ "present", "absent" ]
|
choices: [ "present", "absent" ]
|
||||||
default: present
|
default: present
|
||||||
|
type: str
|
||||||
ignoreerrors:
|
ignoreerrors:
|
||||||
description:
|
description:
|
||||||
- Use this option to ignore errors about unknown keys.
|
- Use this option to ignore errors about unknown keys.
|
||||||
@@ -47,12 +50,14 @@ options:
|
|||||||
description:
|
description:
|
||||||
- Specifies the absolute path to C(sysctl.conf), if not C(/etc/sysctl.conf).
|
- Specifies the absolute path to C(sysctl.conf), if not C(/etc/sysctl.conf).
|
||||||
default: /etc/sysctl.conf
|
default: /etc/sysctl.conf
|
||||||
|
type: path
|
||||||
sysctl_set:
|
sysctl_set:
|
||||||
description:
|
description:
|
||||||
- Verify token value with the sysctl command and set with -w if necessary
|
- Verify token value with the sysctl command and set with -w if necessary
|
||||||
type: bool
|
type: bool
|
||||||
default: 'no'
|
default: 'no'
|
||||||
author: "David CHANIAL (@davixx) <david.chanial@gmail.com>"
|
author:
|
||||||
|
- David CHANIAL (@davixx)
|
||||||
'''
|
'''
|
||||||
|
|
||||||
EXAMPLES = r'''
|
EXAMPLES = r'''
|
||||||
@@ -182,12 +187,12 @@ class SysctlModule(object):
|
|||||||
|
|
||||||
# Do the work
|
# Do the work
|
||||||
if not self.module.check_mode:
|
if not self.module.check_mode:
|
||||||
|
if self.set_proc:
|
||||||
|
self.set_token_value(self.args['name'], self.args['value'])
|
||||||
if self.write_file:
|
if self.write_file:
|
||||||
self.write_sysctl()
|
self.write_sysctl()
|
||||||
if self.changed and self.args['reload']:
|
if self.changed and self.args['reload']:
|
||||||
self.reload_sysctl()
|
self.reload_sysctl()
|
||||||
if self.set_proc:
|
|
||||||
self.set_token_value(self.args['name'], self.args['value'])
|
|
||||||
|
|
||||||
def _values_is_equal(self, a, b):
|
def _values_is_equal(self, a, b):
|
||||||
"""Expects two string values. It will split the string by whitespace
|
"""Expects two string values. It will split the string by whitespace
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|
||||||
@@ -26,6 +25,10 @@ class ShellModule(ShellBase):
|
|||||||
# Family of shells this has. Must match the filename without extension
|
# Family of shells this has. Must match the filename without extension
|
||||||
SHELL_FAMILY = 'csh'
|
SHELL_FAMILY = 'csh'
|
||||||
|
|
||||||
|
# commonly used
|
||||||
|
ECHO = 'echo'
|
||||||
|
COMMAND_SEP = ';'
|
||||||
|
|
||||||
# How to end lines in a python script one-liner
|
# How to end lines in a python script one-liner
|
||||||
_SHELL_EMBEDDED_PY_EOL = '\\\n'
|
_SHELL_EMBEDDED_PY_EOL = '\\\n'
|
||||||
_SHELL_REDIRECT_ALLNULL = '>& /dev/null'
|
_SHELL_REDIRECT_ALLNULL = '>& /dev/null'
|
||||||
|
|||||||
@@ -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 }}"
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# -------------------------------------------------------------
|
||||||
|
# check mode
|
||||||
|
|
||||||
|
- name: CHECK MODE | copy an existing file in place with comments
|
||||||
|
copy:
|
||||||
|
src: existing_authorized_keys
|
||||||
|
dest: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
|
||||||
|
- name: CHECK MODE | add key in check mode to validate return codes
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "{{ multiple_key_different_order_2 }}"
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
check_mode: True
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: CHECK MODE | assert that authorized_keys return values are consistent
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'result.changed == True'
|
||||||
|
- '"user" in result'
|
||||||
|
- '"key" in result'
|
||||||
|
|
||||||
|
- name: CHECK MODE | recopy authorized_keys to ensure it was not changed
|
||||||
|
copy:
|
||||||
|
src: existing_authorized_keys
|
||||||
|
dest: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: CHECK MODE | assert that the authorized_keys file was not changed
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'result.changed == False'
|
||||||
50
tests/integration/targets/authorized_key/tasks/comments.yml
Normal file
50
tests/integration/targets/authorized_key/tasks/comments.yml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
# -------------------------------------------------------------
|
||||||
|
# comments
|
||||||
|
|
||||||
|
- name: Add rsa key with existing comment
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "{{ rsa_key_basic }}"
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Change the comment on an existing key
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "{{ rsa_key_basic }}"
|
||||||
|
comment: user@acme.com
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: get the file content
|
||||||
|
shell: cat "{{ output_dir | expanduser }}/authorized_keys" | fgrep DATA_BASIC
|
||||||
|
changed_when: no
|
||||||
|
register: content
|
||||||
|
|
||||||
|
- name: Assert that comment on an existing key was changed
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- "'user@acme.com' in content.stdout"
|
||||||
|
|
||||||
|
- name: Set the same key with comment to ensure no changes are reported
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "{{ rsa_key_basic }}"
|
||||||
|
comment: user@acme.com
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Assert that no changes were made when running again
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- not result.changed
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
var: "{{ item }}"
|
||||||
|
verbosity: 1
|
||||||
|
with_items:
|
||||||
|
- result
|
||||||
|
- content
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# test code for the authorized_key module
|
# test code for the authorized_key module
|
||||||
# (c) 2014, James Cammarata <jcammarata@ansible.com>
|
# - (c) 2014, James Cammarata <jcammarata@ansible.com>
|
||||||
|
# - (c) 2021, Hideki Saito <saito@fgrep.org>
|
||||||
# This file is part of Ansible
|
# This file is part of Ansible
|
||||||
#
|
#
|
||||||
# Ansible is free software: you can redistribute it and/or modify
|
# Ansible is free software: you can redistribute it and/or modify
|
||||||
@@ -16,479 +16,17 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
- name: Setup testing environment
|
||||||
|
import_tasks: setup_steps.yml
|
||||||
|
|
||||||
# -------------------------------------------------------------
|
- name: Test for multiple keys handling
|
||||||
# Setup steps
|
import_tasks: multiple_keys.yml
|
||||||
|
|
||||||
|
- name: Test for ssh-dss key handling
|
||||||
|
import_tasks: ssh_dss.yml
|
||||||
|
|
||||||
- name: copy an existing file in place with comments
|
- name: Test for check mode
|
||||||
copy:
|
import_tasks: check_mode.yml
|
||||||
src: existing_authorized_keys
|
|
||||||
dest: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
|
|
||||||
- name: add multiple keys different order
|
- name: Test for the management of comments with key
|
||||||
authorized_key:
|
import_tasks: comments.yml
|
||||||
user: root
|
|
||||||
key: "{{ multiple_key_different_order_2 }}"
|
|
||||||
state: present
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: get the file content
|
|
||||||
shell: cat "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
changed_when: no
|
|
||||||
register: multiple_keys_existing
|
|
||||||
|
|
||||||
- name: assert that the key was added and comments and ordering preserved
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'result.changed == True'
|
|
||||||
- '"# I like candy" in multiple_keys_existing.stdout'
|
|
||||||
- '"# I like candy" in multiple_keys_existing.stdout_lines[0]'
|
|
||||||
- '"ssh-rsa DATA_BASIC 1@testing" in multiple_keys_existing.stdout'
|
|
||||||
# The specific index is a little fragile, but I want to verify the line shows up
|
|
||||||
# as the 3rd line in the new entries after the existing entries and comments are preserved
|
|
||||||
- '"ssh-rsa DATA_BASIC 1@testing" in multiple_keys_existing.stdout_lines[7]'
|
|
||||||
|
|
||||||
# start afresh
|
|
||||||
|
|
||||||
- name: remove file foo.txt
|
|
||||||
file:
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
state: absent
|
|
||||||
|
|
||||||
- name: touch the authorized_keys file
|
|
||||||
file:
|
|
||||||
dest: "{{ output_dir }}/authorized_keys"
|
|
||||||
state: touch
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: assert that the authorized_keys file was created
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'result.changed == True'
|
|
||||||
- 'result.state == "file"'
|
|
||||||
|
|
||||||
- name: add multiple keys
|
|
||||||
authorized_key:
|
|
||||||
user: root
|
|
||||||
key: "{{ multiple_key_base }}"
|
|
||||||
state: present
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: assert that the key was added
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'result.changed == True'
|
|
||||||
- 'result.key == multiple_key_base'
|
|
||||||
- 'result.key_options == None'
|
|
||||||
|
|
||||||
- name: add multiple keys different order
|
|
||||||
authorized_key:
|
|
||||||
user: root
|
|
||||||
key: "{{ multiple_key_different_order }}"
|
|
||||||
state: present
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: assert that the key was added
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'result.changed == True'
|
|
||||||
- 'result.key == multiple_key_different_order'
|
|
||||||
- 'result.key_options == None'
|
|
||||||
|
|
||||||
- name: add multiple keys exclusive
|
|
||||||
authorized_key:
|
|
||||||
user: root
|
|
||||||
key: "{{ multiple_key_exclusive }}"
|
|
||||||
state: present
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
exclusive: true
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: assert that the key was added
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'result.changed == True'
|
|
||||||
- 'result.key == multiple_key_exclusive'
|
|
||||||
- 'result.key_options == None'
|
|
||||||
|
|
||||||
- name: add multiple keys in different calls
|
|
||||||
authorized_key:
|
|
||||||
user: root
|
|
||||||
key: "ecdsa-sha2-nistp521 ECDSA_DATA 4@testing"
|
|
||||||
state: present
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: add multiple keys in different calls
|
|
||||||
authorized_key:
|
|
||||||
user: root
|
|
||||||
key: "ssh-rsa DATA_BASIC 1@testing"
|
|
||||||
state: present
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: get the file content
|
|
||||||
shell: cat "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
changed_when: no
|
|
||||||
register: multiple_keys_at_a_time
|
|
||||||
|
|
||||||
- name: assert that the key was added
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'result.changed == false'
|
|
||||||
- 'multiple_keys_at_a_time.stdout == multiple_key_exclusive.strip()'
|
|
||||||
|
|
||||||
- name: add multiple keys comment
|
|
||||||
authorized_key:
|
|
||||||
user: root
|
|
||||||
key: "{{ multiple_keys_comments }}"
|
|
||||||
state: present
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
exclusive: true
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: get the file content
|
|
||||||
shell: cat "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
changed_when: no
|
|
||||||
register: multiple_keys_comments
|
|
||||||
|
|
||||||
- name: assert that the keys exist and comment only lines were not added
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'result.changed == False'
|
|
||||||
- 'multiple_keys_comments.stdout == multiple_key_exclusive.strip()'
|
|
||||||
- 'result.key_options == None'
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# -------------------------------------------------------------
|
|
||||||
# basic ssh-dss key
|
|
||||||
|
|
||||||
- name: add basic ssh-dss key
|
|
||||||
authorized_key: user=root key="{{ dss_key_basic }}" state=present path="{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: assert that the key was added
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'result.changed == True'
|
|
||||||
- 'result.key == dss_key_basic'
|
|
||||||
- 'result.key_options == None'
|
|
||||||
|
|
||||||
- name: re-add basic ssh-dss key
|
|
||||||
authorized_key: user=root key="{{ dss_key_basic }}" state=present path="{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: assert that nothing changed
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'result.changed == False'
|
|
||||||
|
|
||||||
# -------------------------------------------------------------
|
|
||||||
# ssh-dss key with an unquoted option
|
|
||||||
|
|
||||||
- name: add ssh-dss key with an unquoted option
|
|
||||||
authorized_key:
|
|
||||||
user: root
|
|
||||||
key: "{{ dss_key_unquoted_option }}"
|
|
||||||
state: present
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: assert that the key was added
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'result.changed == True'
|
|
||||||
- 'result.key == dss_key_unquoted_option'
|
|
||||||
- 'result.key_options == None'
|
|
||||||
|
|
||||||
- name: re-add ssh-dss key with an unquoted option
|
|
||||||
authorized_key:
|
|
||||||
user: root
|
|
||||||
key: "{{ dss_key_unquoted_option }}"
|
|
||||||
state: present
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: assert that nothing changed
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'result.changed == False'
|
|
||||||
|
|
||||||
# -------------------------------------------------------------
|
|
||||||
# ssh-dss key with a leading command="/bin/foo"
|
|
||||||
|
|
||||||
- name: add ssh-dss key with a leading command
|
|
||||||
authorized_key:
|
|
||||||
user: root
|
|
||||||
key: "{{ dss_key_command }}"
|
|
||||||
state: present
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: assert that the key was added
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'result.changed == True'
|
|
||||||
- 'result.key == dss_key_command'
|
|
||||||
- 'result.key_options == None'
|
|
||||||
|
|
||||||
- name: re-add ssh-dss key with a leading command
|
|
||||||
authorized_key:
|
|
||||||
user: root
|
|
||||||
key: "{{ dss_key_command }}"
|
|
||||||
state: present
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: assert that nothing changed
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'result.changed == False'
|
|
||||||
|
|
||||||
# -------------------------------------------------------------
|
|
||||||
# ssh-dss key with a complex quoted leading command
|
|
||||||
# ie. command="/bin/echo foo 'bar baz'"
|
|
||||||
|
|
||||||
- name: add ssh-dss key with a complex quoted leading command
|
|
||||||
authorized_key:
|
|
||||||
user: root
|
|
||||||
key: "{{ dss_key_complex_command }}"
|
|
||||||
state: present
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: assert that the key was added
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'result.changed == True'
|
|
||||||
- 'result.key == dss_key_complex_command'
|
|
||||||
- 'result.key_options == None'
|
|
||||||
|
|
||||||
- name: re-add ssh-dss key with a complex quoted leading command
|
|
||||||
authorized_key:
|
|
||||||
user: root
|
|
||||||
key: "{{ dss_key_complex_command }}"
|
|
||||||
state: present
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: assert that nothing changed
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'result.changed == False'
|
|
||||||
|
|
||||||
# -------------------------------------------------------------
|
|
||||||
# ssh-dss key with a command and a single option, which are
|
|
||||||
# in a comma-separated list
|
|
||||||
|
|
||||||
- name: add ssh-dss key with a command and a single option
|
|
||||||
authorized_key:
|
|
||||||
user: root
|
|
||||||
key: "{{ dss_key_command_single_option }}"
|
|
||||||
state: present
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: assert that the key was added
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'result.changed == True'
|
|
||||||
- 'result.key == dss_key_command_single_option'
|
|
||||||
- 'result.key_options == None'
|
|
||||||
|
|
||||||
- name: re-add ssh-dss key with a command and a single option
|
|
||||||
authorized_key:
|
|
||||||
user: root
|
|
||||||
key: "{{ dss_key_command_single_option }}"
|
|
||||||
state: present
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: assert that nothing changed
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'result.changed == False'
|
|
||||||
|
|
||||||
# -------------------------------------------------------------
|
|
||||||
# ssh-dss key with a command and multiple other options
|
|
||||||
|
|
||||||
- name: add ssh-dss key with a command and multiple options
|
|
||||||
authorized_key:
|
|
||||||
user: root
|
|
||||||
key: "{{ dss_key_command_multiple_options }}"
|
|
||||||
state: present
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: assert that the key was added
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'result.changed == True'
|
|
||||||
- 'result.key == dss_key_command_multiple_options'
|
|
||||||
- 'result.key_options == None'
|
|
||||||
|
|
||||||
- name: re-add ssh-dss key with a command and multiple options
|
|
||||||
authorized_key:
|
|
||||||
user: root
|
|
||||||
key: "{{ dss_key_command_multiple_options }}"
|
|
||||||
state: present
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: assert that nothing changed
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'result.changed == False'
|
|
||||||
|
|
||||||
# -------------------------------------------------------------
|
|
||||||
# ssh-dss key with multiple trailing parts, which are space-
|
|
||||||
# separated and not quoted in any way
|
|
||||||
|
|
||||||
- name: add ssh-dss key with trailing parts
|
|
||||||
authorized_key:
|
|
||||||
user: root
|
|
||||||
key: "{{ dss_key_trailing }}"
|
|
||||||
state: present
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: assert that the key was added
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'result.changed == True'
|
|
||||||
- 'result.key == dss_key_trailing'
|
|
||||||
- 'result.key_options == None'
|
|
||||||
|
|
||||||
- name: re-add ssh-dss key with trailing parts
|
|
||||||
authorized_key:
|
|
||||||
user: root
|
|
||||||
key: "{{ dss_key_trailing }}"
|
|
||||||
state: present
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: assert that nothing changed
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'result.changed == False'
|
|
||||||
|
|
||||||
# -------------------------------------------------------------
|
|
||||||
# basic ssh-dss key with mutliple permit-open options
|
|
||||||
# https://github.com/ansible/ansible-modules-core/issues/1715
|
|
||||||
|
|
||||||
- name: add basic ssh-dss key with multi-opts
|
|
||||||
authorized_key:
|
|
||||||
user: root
|
|
||||||
key: "{{ dss_key_basic }}"
|
|
||||||
key_options: 'no-agent-forwarding,no-X11-forwarding,permitopen="10.9.8.1:8080",permitopen="10.9.8.1:9001"'
|
|
||||||
state: present
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: assert that the key with multi-opts was added
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'result.changed == True'
|
|
||||||
- 'result.key == dss_key_basic'
|
|
||||||
- 'result.key_options == "no-agent-forwarding,no-X11-forwarding,permitopen=\"10.9.8.1:8080\",permitopen=\"10.9.8.1:9001\""'
|
|
||||||
|
|
||||||
- name: get the file content
|
|
||||||
shell: cat "{{ output_dir | expanduser }}/authorized_keys" | fgrep DATA_BASIC
|
|
||||||
changed_when: no
|
|
||||||
register: content
|
|
||||||
|
|
||||||
- name: validate content
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'content.stdout == "no-agent-forwarding,no-X11-forwarding,permitopen=\"10.9.8.1:8080\",permitopen=\"10.9.8.1:9001\" ssh-dss DATA_BASIC root@testing"'
|
|
||||||
|
|
||||||
# -------------------------------------------------------------
|
|
||||||
# check mode
|
|
||||||
|
|
||||||
- name: CHECK MODE | copy an existing file in place with comments
|
|
||||||
copy:
|
|
||||||
src: existing_authorized_keys
|
|
||||||
dest: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
|
|
||||||
- name: CHECK MODE | add key in check mode to validate return codes
|
|
||||||
authorized_key:
|
|
||||||
user: root
|
|
||||||
key: "{{ multiple_key_different_order_2 }}"
|
|
||||||
state: present
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
check_mode: True
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: CHECK MODE | assert that authorized_keys return values are consistent
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'result.changed == True'
|
|
||||||
- '"user" in result'
|
|
||||||
- '"key" in result'
|
|
||||||
|
|
||||||
- name: CHECK MODE | recopy authorized_keys to ensure it was not changed
|
|
||||||
copy:
|
|
||||||
src: existing_authorized_keys
|
|
||||||
dest: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: CHECK MODE | assert that the authorized_keys file was not changed
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- 'result.changed == False'
|
|
||||||
|
|
||||||
# -------------------------------------------------------------
|
|
||||||
# comments
|
|
||||||
|
|
||||||
- name: Add rsa key with existing comment
|
|
||||||
authorized_key:
|
|
||||||
user: root
|
|
||||||
key: "{{ rsa_key_basic }}"
|
|
||||||
state: present
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: Change the comment on an existing key
|
|
||||||
authorized_key:
|
|
||||||
user: root
|
|
||||||
key: "{{ rsa_key_basic }}"
|
|
||||||
comment: user@acme.com
|
|
||||||
state: present
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: get the file content
|
|
||||||
shell: cat "{{ output_dir | expanduser }}/authorized_keys" | fgrep DATA_BASIC
|
|
||||||
changed_when: no
|
|
||||||
register: content
|
|
||||||
|
|
||||||
- name: Assert that comment on an existing key was changed
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- "'user@acme.com' in content.stdout"
|
|
||||||
|
|
||||||
- name: Set the same key with comment to ensure no changes are reported
|
|
||||||
authorized_key:
|
|
||||||
user: root
|
|
||||||
key: "{{ rsa_key_basic }}"
|
|
||||||
comment: user@acme.com
|
|
||||||
state: present
|
|
||||||
path: "{{ output_dir | expanduser }}/authorized_keys"
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- name: Assert that no changes were made when running again
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- not result.changed
|
|
||||||
|
|
||||||
- debug:
|
|
||||||
var: "{{ item }}"
|
|
||||||
verbosity: 1
|
|
||||||
with_items:
|
|
||||||
- result
|
|
||||||
- content
|
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
# -------------------------------------------------------------
|
||||||
|
# multiple keys
|
||||||
|
|
||||||
|
- name: add multiple keys
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "{{ multiple_key_base }}"
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert that the key was added
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'result.changed == True'
|
||||||
|
- 'result.key == multiple_key_base'
|
||||||
|
- 'result.key_options == None'
|
||||||
|
|
||||||
|
- name: add multiple keys different order
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "{{ multiple_key_different_order }}"
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert that the key was added
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'result.changed == True'
|
||||||
|
- 'result.key == multiple_key_different_order'
|
||||||
|
- 'result.key_options == None'
|
||||||
|
|
||||||
|
- name: add multiple keys exclusive
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "{{ multiple_key_exclusive }}"
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
exclusive: true
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert that the key was added
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'result.changed == True'
|
||||||
|
- 'result.key == multiple_key_exclusive'
|
||||||
|
- 'result.key_options == None'
|
||||||
|
|
||||||
|
- name: add multiple keys in different calls
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "ecdsa-sha2-nistp521 ECDSA_DATA 4@testing"
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: add multiple keys in different calls
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "ssh-rsa DATA_BASIC 1@testing"
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: get the file content
|
||||||
|
shell: cat "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
changed_when: no
|
||||||
|
register: multiple_keys_at_a_time
|
||||||
|
|
||||||
|
- name: assert that the key was added
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'result.changed == false'
|
||||||
|
- 'multiple_keys_at_a_time.stdout == multiple_key_exclusive.strip()'
|
||||||
|
|
||||||
|
- name: add multiple keys comment
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "{{ multiple_keys_comments }}"
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
exclusive: true
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: get the file content
|
||||||
|
shell: cat "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
changed_when: no
|
||||||
|
register: multiple_keys_comments
|
||||||
|
|
||||||
|
- name: assert that the keys exist and comment only lines were not added
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'result.changed == False'
|
||||||
|
- 'multiple_keys_comments.stdout == multiple_key_exclusive.strip()'
|
||||||
|
- 'result.key_options == None'
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
# -------------------------------------------------------------
|
||||||
|
# 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
|
||||||
|
copy:
|
||||||
|
src: existing_authorized_keys
|
||||||
|
dest: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
|
||||||
|
- name: add multiple keys different order
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "{{ multiple_key_different_order_2 }}"
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: get the file content
|
||||||
|
shell: cat "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
changed_when: no
|
||||||
|
register: multiple_keys_existing
|
||||||
|
|
||||||
|
- name: assert that the key was added and comments and ordering preserved
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'result.changed == True'
|
||||||
|
- '"# I like candy" in multiple_keys_existing.stdout'
|
||||||
|
- '"# I like candy" in multiple_keys_existing.stdout_lines[0]'
|
||||||
|
- '"ssh-rsa DATA_BASIC 1@testing" in multiple_keys_existing.stdout'
|
||||||
|
# The specific index is a little fragile, but I want to verify the line shows up
|
||||||
|
# as the 3rd line in the new entries after the existing entries and comments are preserved
|
||||||
|
- '"ssh-rsa DATA_BASIC 1@testing" in multiple_keys_existing.stdout_lines[7]'
|
||||||
|
|
||||||
|
# start afresh
|
||||||
|
|
||||||
|
- name: remove file foo.txt
|
||||||
|
file:
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: touch the authorized_keys file
|
||||||
|
file:
|
||||||
|
dest: "{{ output_dir }}/authorized_keys"
|
||||||
|
state: touch
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert that the authorized_keys file was created
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'result.changed == True'
|
||||||
|
- 'result.state == "file"'
|
||||||
241
tests/integration/targets/authorized_key/tasks/ssh_dss.yml
Normal file
241
tests/integration/targets/authorized_key/tasks/ssh_dss.yml
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
# -------------------------------------------------------------
|
||||||
|
# basic ssh-dss key
|
||||||
|
|
||||||
|
- name: add basic ssh-dss key
|
||||||
|
authorized_key: user=root key="{{ dss_key_basic }}" state=present path="{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert that the key was added
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'result.changed == True'
|
||||||
|
- 'result.key == dss_key_basic'
|
||||||
|
- 'result.key_options == None'
|
||||||
|
|
||||||
|
- name: re-add basic ssh-dss key
|
||||||
|
authorized_key: user=root key="{{ dss_key_basic }}" state=present path="{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert that nothing changed
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'result.changed == False'
|
||||||
|
|
||||||
|
# -------------------------------------------------------------
|
||||||
|
# ssh-dss key with an unquoted option
|
||||||
|
|
||||||
|
- name: add ssh-dss key with an unquoted option
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "{{ dss_key_unquoted_option }}"
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert that the key was added
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'result.changed == True'
|
||||||
|
- 'result.key == dss_key_unquoted_option'
|
||||||
|
- 'result.key_options == None'
|
||||||
|
|
||||||
|
- name: re-add ssh-dss key with an unquoted option
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "{{ dss_key_unquoted_option }}"
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert that nothing changed
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'result.changed == False'
|
||||||
|
|
||||||
|
# -------------------------------------------------------------
|
||||||
|
# ssh-dss key with a leading command="/bin/foo"
|
||||||
|
|
||||||
|
- name: add ssh-dss key with a leading command
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "{{ dss_key_command }}"
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert that the key was added
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'result.changed == True'
|
||||||
|
- 'result.key == dss_key_command'
|
||||||
|
- 'result.key_options == None'
|
||||||
|
|
||||||
|
- name: re-add ssh-dss key with a leading command
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "{{ dss_key_command }}"
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert that nothing changed
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'result.changed == False'
|
||||||
|
|
||||||
|
# -------------------------------------------------------------
|
||||||
|
# ssh-dss key with a complex quoted leading command
|
||||||
|
# ie. command="/bin/echo foo 'bar baz'"
|
||||||
|
|
||||||
|
- name: add ssh-dss key with a complex quoted leading command
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "{{ dss_key_complex_command }}"
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert that the key was added
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'result.changed == True'
|
||||||
|
- 'result.key == dss_key_complex_command'
|
||||||
|
- 'result.key_options == None'
|
||||||
|
|
||||||
|
- name: re-add ssh-dss key with a complex quoted leading command
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "{{ dss_key_complex_command }}"
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert that nothing changed
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'result.changed == False'
|
||||||
|
|
||||||
|
# -------------------------------------------------------------
|
||||||
|
# ssh-dss key with a command and a single option, which are
|
||||||
|
# in a comma-separated list
|
||||||
|
|
||||||
|
- name: add ssh-dss key with a command and a single option
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "{{ dss_key_command_single_option }}"
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert that the key was added
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'result.changed == True'
|
||||||
|
- 'result.key == dss_key_command_single_option'
|
||||||
|
- 'result.key_options == None'
|
||||||
|
|
||||||
|
- name: re-add ssh-dss key with a command and a single option
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "{{ dss_key_command_single_option }}"
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert that nothing changed
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'result.changed == False'
|
||||||
|
|
||||||
|
# -------------------------------------------------------------
|
||||||
|
# ssh-dss key with a command and multiple other options
|
||||||
|
|
||||||
|
- name: add ssh-dss key with a command and multiple options
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "{{ dss_key_command_multiple_options }}"
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert that the key was added
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'result.changed == True'
|
||||||
|
- 'result.key == dss_key_command_multiple_options'
|
||||||
|
- 'result.key_options == None'
|
||||||
|
|
||||||
|
- name: re-add ssh-dss key with a command and multiple options
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "{{ dss_key_command_multiple_options }}"
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert that nothing changed
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'result.changed == False'
|
||||||
|
|
||||||
|
# -------------------------------------------------------------
|
||||||
|
# ssh-dss key with multiple trailing parts, which are space-
|
||||||
|
# separated and not quoted in any way
|
||||||
|
|
||||||
|
- name: add ssh-dss key with trailing parts
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "{{ dss_key_trailing }}"
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert that the key was added
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'result.changed == True'
|
||||||
|
- 'result.key == dss_key_trailing'
|
||||||
|
- 'result.key_options == None'
|
||||||
|
|
||||||
|
- name: re-add ssh-dss key with trailing parts
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "{{ dss_key_trailing }}"
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert that nothing changed
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'result.changed == False'
|
||||||
|
|
||||||
|
# -------------------------------------------------------------
|
||||||
|
# basic ssh-dss key with mutliple permit-open options
|
||||||
|
# https://github.com/ansible/ansible-modules-core/issues/1715
|
||||||
|
|
||||||
|
- name: add basic ssh-dss key with multi-opts
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "{{ dss_key_basic }}"
|
||||||
|
key_options: 'no-agent-forwarding,no-X11-forwarding,permitopen="10.9.8.1:8080",permitopen="10.9.8.1:9001"'
|
||||||
|
state: present
|
||||||
|
path: "{{ output_dir | expanduser }}/authorized_keys"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert that the key with multi-opts was added
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'result.changed == True'
|
||||||
|
- 'result.key == dss_key_basic'
|
||||||
|
- 'result.key_options == "no-agent-forwarding,no-X11-forwarding,permitopen=\"10.9.8.1:8080\",permitopen=\"10.9.8.1:9001\""'
|
||||||
|
|
||||||
|
- name: get the file content
|
||||||
|
shell: cat "{{ output_dir | expanduser }}/authorized_keys" | fgrep DATA_BASIC
|
||||||
|
changed_when: no
|
||||||
|
register: content
|
||||||
|
|
||||||
|
- name: validate content
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- 'content.stdout == "no-agent-forwarding,no-X11-forwarding,permitopen=\"10.9.8.1:8080\",permitopen=\"10.9.8.1:9001\" ssh-dss DATA_BASIC root@testing"'
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
destructive
|
destructive
|
||||||
shippable/posix/group3
|
shippable/posix/group1
|
||||||
skip/aix
|
skip/aix
|
||||||
skip/freebsd
|
skip/freebsd
|
||||||
skip/osx
|
skip/osx
|
||||||
disabled # fixme
|
|
||||||
|
|||||||
@@ -1,20 +1,6 @@
|
|||||||
# Test playbook for the firewalld module
|
# Test playbook for the firewalld module
|
||||||
# (c) 2017, Adam Miller <admiller@redhat.com>
|
# (c) 2017, Adam Miller <admiller@redhat.com>
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
# This file is part of Ansible
|
|
||||||
#
|
|
||||||
# Ansible is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Ansible is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
- name: Run firewalld tests
|
- name: Run firewalld tests
|
||||||
block:
|
block:
|
||||||
@@ -29,6 +15,13 @@
|
|||||||
register: check_output
|
register: check_output
|
||||||
ignore_errors: true
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Enable dbus-broker daemon
|
||||||
|
service:
|
||||||
|
name: dbus-broker
|
||||||
|
enabled: true
|
||||||
|
state: started
|
||||||
|
when: (ansible_distribution == 'Fedora' and ansible_distribution_major_version is version('34', '=='))
|
||||||
|
|
||||||
- name: Test Online Operations
|
- name: Test Online Operations
|
||||||
block:
|
block:
|
||||||
- name: start firewalld
|
- name: start firewalld
|
||||||
@@ -54,3 +47,4 @@
|
|||||||
- not (ansible_distribution == "Ubuntu" and ansible_distribution_version is version('14.04', '=='))
|
- not (ansible_distribution == "Ubuntu" and ansible_distribution_version is version('14.04', '=='))
|
||||||
# Firewalld package on OpenSUSE (15+) require Python 3, so we skip on OpenSUSE running py2 on these newer distros
|
# Firewalld package on OpenSUSE (15+) require Python 3, so we skip on OpenSUSE running py2 on these newer distros
|
||||||
- not (ansible_os_family == "Suse" and ansible_distribution_major_version|int != 42 and ansible_python.version.major != 3)
|
- not (ansible_os_family == "Suse" and ansible_distribution_major_version|int != 42 and ansible_python.version.major != 3)
|
||||||
|
- not (ansible_facts.distribution == "CentOS" and ansible_distribution_major_version is version('7', '==')) # FIXME
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
# Test playbook for the firewalld module - port operations
|
||||||
|
# (c) 2017, Adam Miller <admiller@redhat.com>
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
- name: firewalld port forward test permanent enabled
|
||||||
|
firewalld:
|
||||||
|
port_forward:
|
||||||
|
- port: 8080
|
||||||
|
proto: tcp
|
||||||
|
toport: 8081
|
||||||
|
permanent: true
|
||||||
|
state: enabled
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert firewalld port test permanent enabled worked
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
|
||||||
|
- name: firewalld port test permanent enabled rerun (verify not changed)
|
||||||
|
firewalld:
|
||||||
|
port_forward:
|
||||||
|
- port: 8080
|
||||||
|
proto: tcp
|
||||||
|
toport: 8081
|
||||||
|
permanent: true
|
||||||
|
state: enabled
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert firewalld port test permanent enabled rerun worked (verify not changed)
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is not changed
|
||||||
|
|
||||||
|
- name: firewalld port test permanent disabled
|
||||||
|
firewalld:
|
||||||
|
port_forward:
|
||||||
|
- port: 8080
|
||||||
|
proto: tcp
|
||||||
|
toport: 8081
|
||||||
|
permanent: true
|
||||||
|
state: disabled
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert firewalld port test permanent disabled worked
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
|
||||||
|
- name: firewalld port test permanent disabled rerun (verify not changed)
|
||||||
|
firewalld:
|
||||||
|
port_forward:
|
||||||
|
- port: 8080
|
||||||
|
proto: tcp
|
||||||
|
toport: 8081
|
||||||
|
permanent: true
|
||||||
|
state: disabled
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert firewalld port test permanent disabled rerun worked (verify not changed)
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is not changed
|
||||||
@@ -1,20 +1,63 @@
|
|||||||
# Test playbook for the firewalld module - port operations
|
# Test playbook for the firewalld module - port operations
|
||||||
# (c) 2017, Adam Miller <admiller@redhat.com>
|
# (c) 2017, Adam Miller <admiller@redhat.com>
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
# This file is part of Ansible
|
- name: firewalld port range test permanent enabled
|
||||||
#
|
firewalld:
|
||||||
# Ansible is free software: you can redistribute it and/or modify
|
port: 5500-6950/tcp
|
||||||
# it under the terms of the GNU General Public License as published by
|
permanent: true
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
state: enabled
|
||||||
# (at your option) any later version.
|
register: result
|
||||||
#
|
|
||||||
# Ansible is distributed in the hope that it will be useful,
|
- name: assert firewalld port range test permanent enabled worked
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
assert:
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
that:
|
||||||
# GNU General Public License for more details.
|
- result is changed
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
- name: firewalld port range test permanent enabled rerun (verify not changed)
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
firewalld:
|
||||||
|
port: 5500-6950/tcp
|
||||||
|
permanent: true
|
||||||
|
state: enabled
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert firewalld port range test permanent enabled rerun worked (verify not changed)
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is not changed
|
||||||
|
|
||||||
|
- name: firewalld port test permanent enabled
|
||||||
|
firewalld:
|
||||||
|
port: 6900/tcp
|
||||||
|
permanent: true
|
||||||
|
state: enabled
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert firewalld port test permanent enabled worked
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
|
||||||
|
- name: firewalld port test permanent enabled
|
||||||
|
firewalld:
|
||||||
|
port: 6900/tcp
|
||||||
|
permanent: true
|
||||||
|
state: enabled
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: assert firewalld port test permanent enabled worked
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is not changed
|
||||||
|
|
||||||
|
- name: firewalld port test disabled
|
||||||
|
firewalld:
|
||||||
|
port: "{{ item }}"
|
||||||
|
permanent: true
|
||||||
|
state: disabled
|
||||||
|
loop:
|
||||||
|
- 6900/tcp
|
||||||
|
- 5500-6950/tcp
|
||||||
|
|
||||||
- name: firewalld port test permanent enabled
|
- name: firewalld port test permanent enabled
|
||||||
firewalld:
|
firewalld:
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user