mirror of
https://github.com/ansible-collections/ansible.posix.git
synced 2026-05-11 12:02:06 +00:00
Compare commits
78 Commits
2.0.0
...
fe77b17251
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe77b17251 | ||
|
|
28a09cd805 | ||
|
|
853a333142 | ||
|
|
2022c1bd86 | ||
|
|
42d76de1cf | ||
|
|
fb2bc7b4b5 | ||
|
|
9603ef890f | ||
|
|
513d50192d | ||
|
|
5cbe684b48 | ||
|
|
17dd3b2e01 | ||
|
|
35bcea6ec9 | ||
|
|
065af18c26 | ||
|
|
a2fa110036 | ||
|
|
935a644f3c | ||
|
|
37e46324f5 | ||
|
|
1aa2f974e9 | ||
|
|
7c9c261faf | ||
|
|
bfe81d4388 | ||
|
|
ba58f22d2e | ||
|
|
23a8948110 | ||
|
|
4f43537804 | ||
|
|
e5f6e0be0c | ||
|
|
25f4419e19 | ||
|
|
f31b7a380b | ||
|
|
1f0844bf98 | ||
|
|
6462116447 | ||
|
|
28b6db7845 | ||
|
|
7709fbe168 | ||
|
|
692b906b82 | ||
|
|
aece4a9632 | ||
|
|
2cd1a6e4ab | ||
|
|
8af0b227cc | ||
|
|
5f44339fa5 | ||
|
|
7d5aef07e2 | ||
|
|
b39ee97ccc | ||
|
|
72a6eb9729 | ||
|
|
9651a19805 | ||
|
|
413ab782a8 | ||
|
|
9343c6f56f | ||
|
|
9dc73a686a | ||
|
|
6da1331018 | ||
|
|
cda2e0657f | ||
|
|
ab8dfefd90 | ||
|
|
b96fad5e5b | ||
|
|
2d350e6073 | ||
|
|
ea6ef5c775 | ||
|
|
9007e20b2f | ||
|
|
508e3d920f | ||
|
|
18e023dd77 | ||
|
|
d3204df536 | ||
|
|
162e72182f | ||
|
|
1c1dd005c8 | ||
|
|
40c27e2bee | ||
|
|
c273ac2a01 | ||
|
|
f978998521 | ||
|
|
c319c856ed | ||
|
|
cdb442ea48 | ||
|
|
f977bffff2 | ||
|
|
dabaca4b70 | ||
|
|
26b9b1438d | ||
|
|
1994b2cf1c | ||
|
|
2f224e6a6a | ||
|
|
96ec2097cc | ||
|
|
7b9b1f4957 | ||
|
|
f0b5f039d3 | ||
|
|
5ceb40b600 | ||
|
|
2cec8cbed5 | ||
|
|
1b8aeb03cb | ||
|
|
eead50b287 | ||
|
|
4ff0e3aa13 | ||
|
|
979f00ce75 | ||
|
|
ed3d322fd5 | ||
|
|
d9f54eb9d4 | ||
|
|
7d8da00f79 | ||
|
|
f087d58cbe | ||
|
|
eb740e97d4 | ||
|
|
44a2151dbf | ||
|
|
83288b9020 |
@@ -4,7 +4,12 @@
|
|||||||
# SPDX-FileCopyrightText: 2024, Ansible Project
|
# SPDX-FileCopyrightText: 2024, Ansible Project
|
||||||
|
|
||||||
skip_list:
|
skip_list:
|
||||||
- meta-runtime[unsupported-version] # Tis rule doesn't make any sense
|
- meta-runtime[unsupported-version] # This rule doesn't make any sense
|
||||||
- fqcn[deep] # This rule produces false positives for files in tests/unit/plugins/action/fixtures/
|
- fqcn[deep] # This rule produces false positives for files in tests/unit/plugins/action/fixtures/
|
||||||
|
- sanity[cannot-ignore] # This rule is skipped to keep backward compatibility with Python 2
|
||||||
|
|
||||||
exclude_paths:
|
exclude_paths:
|
||||||
- changelogs/
|
- changelogs/
|
||||||
|
- .github/
|
||||||
|
- tests/
|
||||||
|
- meta/
|
||||||
|
|||||||
@@ -37,13 +37,13 @@ variables:
|
|||||||
resources:
|
resources:
|
||||||
containers:
|
containers:
|
||||||
- container: default
|
- container: default
|
||||||
image: quay.io/ansible/azure-pipelines-test-container:6.0.0
|
image: quay.io/ansible/azure-pipelines-test-container:7.0.0
|
||||||
|
|
||||||
pool: Standard
|
pool: Standard
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- stage: Sanity_devel
|
- stage: Sanity_devel
|
||||||
displayName: Ansible devel sanity
|
displayName: Ansible devel Sanity & Units & Lint
|
||||||
dependsOn: []
|
dependsOn: []
|
||||||
jobs:
|
jobs:
|
||||||
- template: templates/matrix.yml
|
- template: templates/matrix.yml
|
||||||
@@ -57,8 +57,57 @@ stages:
|
|||||||
test: units
|
test: units
|
||||||
- name: Lint
|
- name: Lint
|
||||||
test: lint
|
test: lint
|
||||||
|
|
||||||
|
- stage: Sanity_2_21
|
||||||
|
displayName: Ansible 2.21 Sanity & Units & Lint
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
nameFormat: "{0}"
|
||||||
|
testFormat: 2.21/{0}
|
||||||
|
targets:
|
||||||
|
- name: Sanity
|
||||||
|
test: sanity
|
||||||
|
- name: Units
|
||||||
|
test: units
|
||||||
|
- name: Lint
|
||||||
|
test: lint
|
||||||
|
|
||||||
|
- stage: Sanity_2_20
|
||||||
|
displayName: Ansible 2.20 Sanity & Units & Lint
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
nameFormat: "{0}"
|
||||||
|
testFormat: 2.20/{0}
|
||||||
|
targets:
|
||||||
|
- name: Sanity
|
||||||
|
test: sanity
|
||||||
|
- name: Units
|
||||||
|
test: units
|
||||||
|
- name: Lint
|
||||||
|
test: lint
|
||||||
|
|
||||||
|
- stage: Sanity_2_19
|
||||||
|
displayName: Ansible 2.19 Sanity & Units & Lint
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
nameFormat: "{0}"
|
||||||
|
testFormat: 2.19/{0}
|
||||||
|
targets:
|
||||||
|
- name: Sanity
|
||||||
|
test: sanity
|
||||||
|
- name: Units
|
||||||
|
test: units
|
||||||
|
- name: Lint
|
||||||
|
test: lint
|
||||||
|
|
||||||
- stage: Sanity_2_18
|
- stage: Sanity_2_18
|
||||||
displayName: Ansible 2.18 sanity
|
displayName: Ansible 2.18 Sanity & Units & Lint
|
||||||
dependsOn: []
|
dependsOn: []
|
||||||
jobs:
|
jobs:
|
||||||
- template: templates/matrix.yml
|
- template: templates/matrix.yml
|
||||||
@@ -72,47 +121,7 @@ stages:
|
|||||||
test: units
|
test: units
|
||||||
- name: Lint
|
- name: Lint
|
||||||
test: lint
|
test: lint
|
||||||
- stage: Sanity_2_17
|
|
||||||
displayName: Ansible 2.17 sanity
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
nameFormat: "{0}"
|
|
||||||
testFormat: 2.17/{0}
|
|
||||||
targets:
|
|
||||||
- name: Sanity
|
|
||||||
test: sanity
|
|
||||||
- name: Units
|
|
||||||
test: units
|
|
||||||
- name: Lint
|
|
||||||
test: lint
|
|
||||||
- stage: Sanity_2_16
|
|
||||||
displayName: Ansible 2.16 sanity
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
nameFormat: "{0}"
|
|
||||||
testFormat: 2.16/{0}
|
|
||||||
targets:
|
|
||||||
- name: Sanity
|
|
||||||
test: sanity
|
|
||||||
- name: Units
|
|
||||||
test: units
|
|
||||||
- stage: Sanity_2_15
|
|
||||||
displayName: Ansible 2.15 sanity
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
nameFormat: "{0}"
|
|
||||||
testFormat: 2.15/{0}
|
|
||||||
targets:
|
|
||||||
- name: Sanity
|
|
||||||
test: sanity
|
|
||||||
- name: Units
|
|
||||||
test: units
|
|
||||||
## Docker
|
## Docker
|
||||||
- stage: Docker_devel
|
- stage: Docker_devel
|
||||||
displayName: Docker devel
|
displayName: Docker devel
|
||||||
@@ -122,14 +131,60 @@ stages:
|
|||||||
parameters:
|
parameters:
|
||||||
testFormat: devel/linux/{0}/1
|
testFormat: devel/linux/{0}/1
|
||||||
targets:
|
targets:
|
||||||
- name: Fedora 40
|
- name: Fedora 44
|
||||||
test: fedora40
|
test: fedora44
|
||||||
- name: Ubuntu 22.04
|
- name: Ubuntu 22.04
|
||||||
test: ubuntu2204
|
test: ubuntu2204
|
||||||
- name: Ubuntu 24.04
|
- name: Ubuntu 24.04
|
||||||
test: ubuntu2404
|
test: ubuntu2404
|
||||||
|
|
||||||
|
- stage: Docker_2_21
|
||||||
|
displayName: Docker 2.21
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
testFormat: devel/linux/{0}/1
|
||||||
|
targets:
|
||||||
|
- name: Fedora 44
|
||||||
|
test: fedora44
|
||||||
|
- name: Ubuntu 22.04
|
||||||
|
test: ubuntu2204
|
||||||
|
- name: Ubuntu 24.04
|
||||||
|
test: ubuntu2404
|
||||||
|
|
||||||
|
- stage: Docker_2_20
|
||||||
|
displayName: Docker 2.20
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
testFormat: 2.20/linux/{0}/1
|
||||||
|
targets:
|
||||||
|
- name: Fedora 42
|
||||||
|
test: fedora42
|
||||||
|
- name: Ubuntu 22.04
|
||||||
|
test: ubuntu2204
|
||||||
|
- name: Ubuntu 24.04
|
||||||
|
test: ubuntu2404
|
||||||
|
|
||||||
|
- stage: Docker_2_19
|
||||||
|
displayName: Docker 2.19
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
testFormat: 2.19/linux/{0}/1
|
||||||
|
targets:
|
||||||
|
- name: Fedora 41
|
||||||
|
test: fedora41
|
||||||
|
- name: Ubuntu 22.04
|
||||||
|
test: ubuntu2204
|
||||||
|
- name: Ubuntu 24.04
|
||||||
|
test: ubuntu2404
|
||||||
|
|
||||||
- stage: Docker_2_18
|
- stage: Docker_2_18
|
||||||
displayName: Docker devel
|
displayName: Docker 2.18
|
||||||
dependsOn: []
|
dependsOn: []
|
||||||
jobs:
|
jobs:
|
||||||
- template: templates/matrix.yml
|
- template: templates/matrix.yml
|
||||||
@@ -142,55 +197,6 @@ stages:
|
|||||||
test: ubuntu2204
|
test: ubuntu2204
|
||||||
- name: Ubuntu 24.04
|
- name: Ubuntu 24.04
|
||||||
test: ubuntu2404
|
test: ubuntu2404
|
||||||
- stage: Docker_2_17
|
|
||||||
displayName: Docker 2.17
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
testFormat: 2.17/linux/{0}/1
|
|
||||||
targets:
|
|
||||||
- name: Fedora 39
|
|
||||||
test: fedora39
|
|
||||||
- name: Ubuntu 20.04
|
|
||||||
test: ubuntu2004
|
|
||||||
- name: Ubuntu 22.04
|
|
||||||
test: ubuntu2204
|
|
||||||
- stage: Docker_2_16
|
|
||||||
displayName: Docker 2.16
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
testFormat: 2.16/linux/{0}/1
|
|
||||||
targets:
|
|
||||||
- name: CentOS 7
|
|
||||||
test: centos7
|
|
||||||
- name: Fedora 38
|
|
||||||
test: fedora38
|
|
||||||
- name: Ubuntu 20.04
|
|
||||||
test: ubuntu2004
|
|
||||||
- name: Ubuntu 22.04
|
|
||||||
test: ubuntu2204
|
|
||||||
|
|
||||||
- stage: Docker_2_15
|
|
||||||
displayName: Docker 2.15
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
testFormat: 2.15/linux/{0}/1
|
|
||||||
targets:
|
|
||||||
- name: CentOS 7
|
|
||||||
test: centos7
|
|
||||||
- name: Fedora 37
|
|
||||||
test: fedora37
|
|
||||||
- name: openSUSE 15 py3
|
|
||||||
test: opensuse15
|
|
||||||
- name: Ubuntu 20.04
|
|
||||||
test: ubuntu2004
|
|
||||||
- name: Ubuntu 22.04
|
|
||||||
test: ubuntu2204
|
|
||||||
|
|
||||||
## Remote
|
## Remote
|
||||||
- stage: Remote_devel
|
- stage: Remote_devel
|
||||||
@@ -201,85 +207,98 @@ stages:
|
|||||||
parameters:
|
parameters:
|
||||||
testFormat: devel/{0}/1
|
testFormat: devel/{0}/1
|
||||||
targets:
|
targets:
|
||||||
- name: RHEL 9.4
|
- name: RHEL 10.1
|
||||||
test: rhel/9.4
|
test: rhel/10.1
|
||||||
- name: FreeBSD 14.1
|
- name: RHEL 9.7
|
||||||
test: freebsd/14.1
|
test: rhel/9.7
|
||||||
- name: FreeBSD 13.4
|
- name: FreeBSD 14.4
|
||||||
test: freebsd/13.4
|
test: freebsd/14.4
|
||||||
|
- name: FreeBSD 15.0
|
||||||
|
test: freebsd/15.0
|
||||||
|
|
||||||
|
- stage: Remote_2_21
|
||||||
|
displayName: Remote 2.21
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
testFormat: devel/{0}/1
|
||||||
|
targets:
|
||||||
|
- name: RHEL 10.1
|
||||||
|
test: rhel/10.1
|
||||||
|
- name: RHEL 9.7
|
||||||
|
test: rhel/9.7
|
||||||
|
- name: FreeBSD 14.4
|
||||||
|
test: freebsd/14.4
|
||||||
|
- name: FreeBSD 15.0
|
||||||
|
test: freebsd/15.0
|
||||||
|
|
||||||
|
- stage: Remote_2_20
|
||||||
|
displayName: Remote 2.20
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
testFormat: 2.20/{0}/1
|
||||||
|
targets:
|
||||||
|
- name: RHEL 10.1
|
||||||
|
test: rhel/10.1
|
||||||
|
- name: RHEL 9.7
|
||||||
|
test: rhel/9.7
|
||||||
|
- name: FreeBSD 14.3
|
||||||
|
test: freebsd/14.3
|
||||||
|
- name: FreeBSD 13.5
|
||||||
|
test: freebsd/13.5
|
||||||
|
|
||||||
|
- stage: Remote_2_19
|
||||||
|
displayName: Remote 2.19
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
testFormat: 2.19/{0}/1
|
||||||
|
targets:
|
||||||
|
- name: RHEL 10.1
|
||||||
|
test: rhel/10.1
|
||||||
|
- name: RHEL 9.7
|
||||||
|
test: rhel/9.7
|
||||||
|
- name: FreeBSD 14.2
|
||||||
|
test: freebsd/14.2
|
||||||
|
- name: FreeBSD 13.5
|
||||||
|
test: freebsd/13.5
|
||||||
|
|
||||||
- stage: Remote_2_18
|
- stage: Remote_2_18
|
||||||
displayName: Remote devel
|
displayName: Remote 2.18
|
||||||
dependsOn: []
|
dependsOn: []
|
||||||
jobs:
|
jobs:
|
||||||
- template: templates/matrix.yml
|
- template: templates/matrix.yml
|
||||||
parameters:
|
parameters:
|
||||||
testFormat: 2.18/{0}/1
|
testFormat: 2.18/{0}/1
|
||||||
targets:
|
targets:
|
||||||
- name: RHEL 9.4
|
- name: RHEL 10.1
|
||||||
test: rhel/9.4
|
test: rhel/10.1
|
||||||
- name: FreeBSD 13.3
|
- name: RHEL 9.7
|
||||||
test: freebsd/13.3
|
test: rhel/9.7
|
||||||
- stage: Remote_2_17
|
- name: FreeBSD 13.5
|
||||||
displayName: Remote 2.17
|
test: freebsd/13.5
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
testFormat: 2.17/{0}/1
|
|
||||||
targets:
|
|
||||||
- name: RHEL 9.3
|
|
||||||
test: rhel/9.3
|
|
||||||
- name: FreeBSD 13.3
|
|
||||||
test: freebsd/13.3
|
|
||||||
- stage: Remote_2_16
|
|
||||||
displayName: Remote 2.16
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
testFormat: 2.16/{0}/1
|
|
||||||
targets:
|
|
||||||
- name: RHEL 8.8
|
|
||||||
test: rhel/8.8
|
|
||||||
- name: RHEL 9.2
|
|
||||||
test: rhel/9.2
|
|
||||||
- name: FreeBSD 13.2
|
|
||||||
test: freebsd/13.2
|
|
||||||
|
|
||||||
- stage: Remote_2_15
|
|
||||||
displayName: Remote 2.15
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
testFormat: 2.15/{0}/1
|
|
||||||
targets:
|
|
||||||
- name: RHEL 7.9
|
|
||||||
test: rhel/7.9
|
|
||||||
- name: RHEL 8.7
|
|
||||||
test: rhel/8.7
|
|
||||||
- name: RHEL 9.1
|
|
||||||
test: rhel/9.1
|
|
||||||
- name: FreeBSD 13.2
|
|
||||||
test: freebsd/13.2
|
|
||||||
|
|
||||||
## Finally
|
## Finally
|
||||||
|
|
||||||
- stage: Summary
|
- stage: Summary
|
||||||
condition: succeededOrFailed()
|
condition: succeededOrFailed()
|
||||||
dependsOn:
|
dependsOn:
|
||||||
- Sanity_2_15
|
|
||||||
- Remote_2_15
|
|
||||||
- Docker_2_15
|
|
||||||
- Sanity_2_16
|
|
||||||
- Remote_2_16
|
|
||||||
- Docker_2_16
|
|
||||||
- Sanity_2_17
|
|
||||||
- Remote_2_17
|
|
||||||
- Docker_2_17
|
|
||||||
- Sanity_2_18
|
- Sanity_2_18
|
||||||
- Remote_2_18
|
- Remote_2_18
|
||||||
- Docker_2_18
|
- Docker_2_18
|
||||||
|
- Sanity_2_19
|
||||||
|
- Remote_2_19
|
||||||
|
- Docker_2_19
|
||||||
|
- Sanity_2_20
|
||||||
|
- Remote_2_20
|
||||||
|
- Docker_2_20
|
||||||
|
- Sanity_2_21
|
||||||
|
- Remote_2_21
|
||||||
|
- Docker_2_21
|
||||||
- Sanity_devel
|
- Sanity_devel
|
||||||
- Remote_devel
|
- Remote_devel
|
||||||
- Docker_devel
|
- Docker_devel
|
||||||
|
|||||||
52
.github/BOTMETA.yml
vendored
52
.github/BOTMETA.yml
vendored
@@ -1,52 +0,0 @@
|
|||||||
---
|
|
||||||
automerge: false
|
|
||||||
files:
|
|
||||||
$module_utils/mount.py:
|
|
||||||
labels: mount
|
|
||||||
$modules/acl.py:
|
|
||||||
authors: astorije bcoca
|
|
||||||
labels: acl
|
|
||||||
ignore: astorije
|
|
||||||
$modules/at.py:
|
|
||||||
authors: risaacson
|
|
||||||
labels: at
|
|
||||||
$modules/authorized_key.py:
|
|
||||||
authors: ansible
|
|
||||||
labels: authorized_key
|
|
||||||
$modules/mount.py:
|
|
||||||
authors: ansible skvidal
|
|
||||||
maintainers: jtyr
|
|
||||||
labels: mount
|
|
||||||
ignore: skvidal
|
|
||||||
$modules/patch.py:
|
|
||||||
authors: jirutka luisperlaz
|
|
||||||
$modules/seboolean.py:
|
|
||||||
authors: sfromm
|
|
||||||
labels: seboolean
|
|
||||||
$modules/selinux.py:
|
|
||||||
authors: goozbach
|
|
||||||
maintainers: samdoran
|
|
||||||
labels: selinux
|
|
||||||
$modules/synchronize.py:
|
|
||||||
authors: tima
|
|
||||||
labels: synchronize
|
|
||||||
$modules/sysctl.py:
|
|
||||||
authors: davixx
|
|
||||||
maintainers: Akasurde
|
|
||||||
labels: sysctl
|
|
||||||
$plugins/:
|
|
||||||
labels: profile
|
|
||||||
$plugins/debug.py:
|
|
||||||
labels: debug
|
|
||||||
$plugins/patch.py:
|
|
||||||
labels: patch
|
|
||||||
$plugins/synchronize.py:
|
|
||||||
labels: synchronize
|
|
||||||
$plugins/timer.py:
|
|
||||||
macros:
|
|
||||||
actions: plugins/action
|
|
||||||
callbacks: plugins/callback
|
|
||||||
module_utils: plugins/module_utils
|
|
||||||
modules: plugins/modules
|
|
||||||
plugins: plugins/plugins
|
|
||||||
shells: plugins/shell
|
|
||||||
35
.github/workflows/certification.yml
vendored
Normal file
35
.github/workflows/certification.yml
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
# This workflow calls the latest version of the
|
||||||
|
# reusable workflow.
|
||||||
|
# You can copy this file into your respository if
|
||||||
|
# you want to check against pinned versions of
|
||||||
|
# Automation Hub tests.
|
||||||
|
name: Run collection certification checks
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 6 * * *'
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: cert-ver-${{ github.head_ref || github.run_id }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
|
||||||
|
# Files that are not related to the core functionality
|
||||||
|
# of your collection can cause Ansible Lint to fail.
|
||||||
|
# If this happens, add an .ansible-lint file that includes
|
||||||
|
# those files and directories to the root of your
|
||||||
|
# repository; for example:
|
||||||
|
# https://github.com/ansible-collections/partner-certification-checker/blob/main/.ansible-lint
|
||||||
|
# https://github.com/ansible-collections/partner-certification-checker/blob/main/.ansible-lint
|
||||||
|
|
||||||
|
# If there are sanity test failures that cannot be fixed and are allowed to ignore
|
||||||
|
# https://docs.ansible.com/projects/lint/rules/sanity/, create a sanity ignore file
|
||||||
|
# https://docs.ansible.com/projects/ansible/devel/dev_guide/testing/sanity/ignores.html#ignore-file-location
|
||||||
|
# for each affected version of ansible-core (for example, `tests/sanity/ignore-2.18.txt`) and add corresponding entries.
|
||||||
|
jobs:
|
||||||
|
call:
|
||||||
|
uses: ansible-collections/partner-certification-checker/.github/workflows/certification-reusable.yml@v0.1
|
||||||
15
README.md
15
README.md
@@ -2,7 +2,7 @@
|
|||||||
<!-- 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://dev.azure.com/ansible/ansible.posix/_apis/build/status/CI?branchName=main)](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)
|
||||||
|
|
||||||
## Communication
|
## Communication
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ An Ansible Collection of modules and plugins that target POSIX UNIX/Linux and de
|
|||||||
* Python:
|
* Python:
|
||||||
* The Python interpreter version must meet Ansible Core's requirements.
|
* The Python interpreter version must meet Ansible Core's requirements.
|
||||||
* Ansible Core:
|
* Ansible Core:
|
||||||
- ansible-core 2.15 or later
|
- ansible-core 2.16 or later
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@@ -46,10 +46,10 @@ To upgrade the collection to the latest available version, run the following com
|
|||||||
ansible-galaxy collection install ansible.posix --upgrade
|
ansible-galaxy collection install ansible.posix --upgrade
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also install a specific version of the collection, for example, if you need to downgrade when something is broken in the latest version (please report an issue in this repository). Use the following syntax to install version 1.0.0:
|
You can also install a specific version of the collection, for example, if you need to downgrade when something is broken in the latest version (please report an issue in this repository). Use the following syntax to install version 2.0.0:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
ansible-galaxy collection install ansible.posix:==1.0.0
|
ansible-galaxy collection install ansible.posix:==2.0.0
|
||||||
```
|
```
|
||||||
|
|
||||||
See [using Ansible collections](https://docs.ansible.com/ansible/devel/user_guide/collections_using.html) for more details.
|
See [using Ansible collections](https://docs.ansible.com/ansible/devel/user_guide/collections_using.html) for more details.
|
||||||
@@ -78,11 +78,10 @@ ansible-doc -t callback ansible.posix.profile_tasks
|
|||||||
|
|
||||||
The following ansible-core versions have been tested with this collection:
|
The following ansible-core versions have been tested with this collection:
|
||||||
|
|
||||||
- ansible-core 2.19 (devel)
|
- ansible-core 2.20 (devel)
|
||||||
- ansible-core 2.18 (stable) *
|
- ansible-core 2.19 (stable) *
|
||||||
|
- ansible-core 2.18 (stable)
|
||||||
- ansible-core 2.17 (stable)
|
- ansible-core 2.17 (stable)
|
||||||
- ansible-core 2.16 (stable)
|
|
||||||
- ansible-core 2.15 (stable)
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
|||||||
2
changelogs/fragments/603_bump_version_3.yml
Normal file
2
changelogs/fragments/603_bump_version_3.yml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
trivial:
|
||||||
|
- Bump version to 3.0.0 for the next release (https://github.com/ansible-collections/ansible.posix/issues/603).
|
||||||
2
changelogs/fragments/618_ci_remove_ubuntu2004.yml
Normal file
2
changelogs/fragments/618_ci_remove_ubuntu2004.yml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
trivial:
|
||||||
|
- Remove ubuntu20.04 from CI tests (https://github.com/ansible-collections/ansible.posix/issues/612).
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
minor_changes:
|
||||||
|
- profile_tasks - Add option to provide a different date/time format (https://github.com/ansible-collections/ansible.posix/issues/279).
|
||||||
6
changelogs/fragments/631_fixes_module_path.yml
Normal file
6
changelogs/fragments/631_fixes_module_path.yml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
bugfixes:
|
||||||
|
- ansible.posix.cgroup_perf_recap - fixes json module load path (https://github.com/ansible-collections/ansible.posix/issues/630).
|
||||||
|
trivial:
|
||||||
|
- ansible.posix.seboolean - remove unnecessary condition from seboolean integration tests (https://github.com/ansible-collections/ansible.posix/issues/630).
|
||||||
|
- ansible.posix.selinux - optimize conditions for selinux integration tests (https://github.com/ansible-collections/ansible.posix/issues/630).
|
||||||
3
changelogs/fragments/639_fix_authorized_key.yml
Normal file
3
changelogs/fragments/639_fix_authorized_key.yml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
bugfixes:
|
||||||
|
- ansible.posix.authorized_key - fixes error on permission denied in authorized_key module (https://github.com/ansible-collections/ansible.posix/issues/462).
|
||||||
2
changelogs/fragments/642_ci_add_rhel10.yml
Normal file
2
changelogs/fragments/642_ci_add_rhel10.yml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
trivial:
|
||||||
|
- Add Red Hat Enterprise Linux 10.0 to the CI matrix (https://github.com/ansible-collections/ansible.posix/issues/642).
|
||||||
2
changelogs/fragments/650-profile_tasks_roles.yml
Normal file
2
changelogs/fragments/650-profile_tasks_roles.yml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
minor_changes:
|
||||||
|
- "profile_tasks and profile_roles callback plugins - avoid deleted/deprecated callback functions, instead use modern interface that was introduced a longer time ago (https://github.com/ansible-collections/ansible.posix/issues/650)."
|
||||||
3
changelogs/fragments/654_ci_bump_core_version.yml
Normal file
3
changelogs/fragments/654_ci_bump_core_version.yml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
trivial:
|
||||||
|
- Bump ansible-core version to 2.20 of devel branch and add 2.19 to CI
|
||||||
2
changelogs/fragments/660_ci_azp_syntax.yml
Normal file
2
changelogs/fragments/660_ci_azp_syntax.yml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
trivial:
|
||||||
|
- AZP - fixed syntax error in CI test.
|
||||||
3
changelogs/fragments/665_update_readme_20250728.yml
Normal file
3
changelogs/fragments/665_update_readme_20250728.yml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
trivial:
|
||||||
|
- README - Update README to reflect Ansible Core 2.19 release.
|
||||||
3
changelogs/fragments/666_azp_update_20250728.yml
Normal file
3
changelogs/fragments/666_azp_update_20250728.yml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
trivial:
|
||||||
|
- AZP - Update AZP matrix to follow ansible-test changes.
|
||||||
3
changelogs/fragments/670-deprecations.yml
Normal file
3
changelogs/fragments/670-deprecations.yml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
bugfixes:
|
||||||
|
- "firewalld_info - stop returning warnings as return values; this has been deprecated by ansible-core (https://github.com/ansible-collections/ansible.posix/pull/670)."
|
||||||
|
- "mount - stop returning warnings as return values; this has been deprecated by ansible-core (https://github.com/ansible-collections/ansible.posix/pull/670)."
|
||||||
2
changelogs/fragments/673_update_ci_20250805.yml
Normal file
2
changelogs/fragments/673_update_ci_20250805.yml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
trivial:
|
||||||
|
- Update AZP CI matrix (https://github.com/ansible-collections/ansible.posix/issues/673).
|
||||||
4
changelogs/fragments/682_update_ci_20250929.yml
Normal file
4
changelogs/fragments/682_update_ci_20250929.yml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
trivial:
|
||||||
|
- Updatng AZP CI matrix to ignore ansible-bad-import-from on six(https://github.com/ansible-collections/ansible.posix/pull/682).
|
||||||
|
- Skipped sanity[cannot-ignore] to keep backward compatibility with Python2.
|
||||||
|
- Consolidate all ansible-lint option locations into .ansible-lint file.
|
||||||
19
changelogs/fragments/686_fix_deprecated_imports.yml
Normal file
19
changelogs/fragments/686_fix_deprecated_imports.yml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
minor_changes:
|
||||||
|
- acl - fix deprecated ``ansible.module_utils._text`` import (https://github.com/ansible-collections/ansible.posix/issues/686).
|
||||||
|
- authorized_key - fix deprecated ``ansible.module_utils._text`` and ``ansible.module_utils.six`` imports (https://github.com/ansible-collections/ansible.posix/issues/686).
|
||||||
|
- cgroup_perf_recap callback - fix deprecated ``ansible.module_utils._text`` and ``ansible.module_utils.six`` imports (https://github.com/ansible-collections/ansible.posix/issues/686).
|
||||||
|
- csh shell plugin - fix deprecated ``ansible.module_utils.six`` imports (https://github.com/ansible-collections/ansible.posix/issues/686).
|
||||||
|
- firewalld_info - fix deprecated ``ansible.module_utils._text`` import (https://github.com/ansible-collections/ansible.posix/issues/686).
|
||||||
|
- fish shell plugin - fix deprecated ``ansible.module_utils.six`` imports (https://github.com/ansible-collections/ansible.posix/issues/686).
|
||||||
|
- json callback - fix deprecated ``ansible.module_utils._text`` import (https://github.com/ansible-collections/ansible.posix/issues/686).
|
||||||
|
- jsonl callback - fix deprecated ``ansible.module_utils._text`` import (https://github.com/ansible-collections/ansible.posix/issues/686).
|
||||||
|
- mount - fix deprecated ``ansible.module_utils._text`` and ``ansible.module_utils.six`` imports (https://github.com/ansible-collections/ansible.posix/issues/686).
|
||||||
|
- patch - fix deprecated ``ansible.module_utils._text`` import (https://github.com/ansible-collections/ansible.posix/issues/686).
|
||||||
|
- profile_roles callback - fix deprecated ``ansible.module_utils.six`` import (https://github.com/ansible-collections/ansible.posix/issues/686).
|
||||||
|
- profile_tasks callback - fix deprecated ``ansible.module_utils.six`` import (https://github.com/ansible-collections/ansible.posix/issues/686).
|
||||||
|
- rhel_rpm_ostree - fix deprecated ``ansible.module_utils._text`` import (https://github.com/ansible-collections/ansible.posix/issues/686).
|
||||||
|
- rpm_ostree_upgrade - fix deprecated ``ansible.module_utils._text`` import (https://github.com/ansible-collections/ansible.posix/issues/686).
|
||||||
|
- seboolean - fix deprecated ``ansible.module_utils._text`` import (https://github.com/ansible-collections/ansible.posix/issues/686).
|
||||||
|
- synchronize - fix deprecated ``ansible.module_utils._text``, ``ansible.module_utils.common._collections_compat``, and ``ansible.module_utils.six`` imports (https://github.com/ansible-collections/ansible.posix/issues/686).
|
||||||
|
- sysctl - fix deprecated ``ansible.module_utils._text`` and ``ansible.module_utils.six`` imports (https://github.com/ansible-collections/ansible.posix/issues/686).
|
||||||
5
changelogs/fragments/693_azp_update_20251205.yml
Normal file
5
changelogs/fragments/693_azp_update_20251205.yml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
trivial:
|
||||||
|
- AZP - Update AZP matrix to follow ansible-test changes.
|
||||||
|
- Add ignore file for Ansible Core 2.21.
|
||||||
|
- Remove ignore lines for ansible-bad-import-from in 2.20 sanity tests.
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
namespace: ansible
|
namespace: ansible
|
||||||
name: posix
|
name: posix
|
||||||
version: 2.0.0
|
version: 3.0.0
|
||||||
readme: README.md
|
readme: README.md
|
||||||
authors:
|
authors:
|
||||||
- Ansible (github.com/ansible)
|
- Ansible (github.com/ansible)
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
---
|
---
|
||||||
requires_ansible: ">=2.15.0"
|
requires_ansible: ">=2.16.0"
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ __metaclass__ = type
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from ansible.errors import AnsibleError, AnsibleAction, _AnsibleActionDone, AnsibleActionFail
|
from ansible.errors import AnsibleError, AnsibleAction, _AnsibleActionDone, AnsibleActionFail
|
||||||
from ansible.module_utils._text import to_native
|
from ansible.module_utils.common.text.converters import to_native
|
||||||
from ansible.module_utils.parsing.convert_bool import boolean
|
from ansible.module_utils.parsing.convert_bool import boolean
|
||||||
from ansible.plugins.action import ActionBase
|
from ansible.plugins.action import ActionBase
|
||||||
|
|
||||||
|
|||||||
@@ -18,12 +18,11 @@ from __future__ import (absolute_import, division, print_function)
|
|||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
import os.path
|
import os.path
|
||||||
|
from collections.abc import MutableSequence
|
||||||
|
from shlex import quote as shlex_quote
|
||||||
|
|
||||||
from ansible import constants as C
|
from ansible import constants as C
|
||||||
from ansible.module_utils.six import string_types
|
from ansible.module_utils.common.text.converters import to_text
|
||||||
from ansible.module_utils.six.moves import shlex_quote
|
|
||||||
from ansible.module_utils._text import to_text
|
|
||||||
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
|
||||||
from ansible.plugins.action import ActionBase
|
from ansible.plugins.action import ActionBase
|
||||||
from ansible.plugins.loader import connection_loader
|
from ansible.plugins.loader import connection_loader
|
||||||
@@ -417,7 +416,7 @@ class ActionModule(ActionBase):
|
|||||||
# 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', [])
|
||||||
if isinstance(tmp_rsync_opts, string_types):
|
if isinstance(tmp_rsync_opts, str):
|
||||||
tmp_rsync_opts = tmp_rsync_opts.split(',')
|
tmp_rsync_opts = tmp_rsync_opts.split(',')
|
||||||
elif isinstance(tmp_rsync_opts, (int, float)):
|
elif isinstance(tmp_rsync_opts, (int, float)):
|
||||||
tmp_rsync_opts = [to_text(tmp_rsync_opts)]
|
tmp_rsync_opts = [to_text(tmp_rsync_opts)]
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ DOCUMENTATION = '''
|
|||||||
|
|
||||||
import csv
|
import csv
|
||||||
import datetime
|
import datetime
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import threading
|
import threading
|
||||||
@@ -140,9 +141,8 @@ from abc import ABCMeta, abstractmethod
|
|||||||
|
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from ansible.module_utils._text import to_bytes, to_text
|
from ansible.module_utils.common.text.converters import to_bytes, to_text
|
||||||
from ansible.module_utils.six import with_metaclass
|
from ansible.parsing.ajson import AnsibleJSONEncoder
|
||||||
from ansible.parsing.ajson import AnsibleJSONEncoder, json
|
|
||||||
from ansible.plugins.callback import CallbackBase
|
from ansible.plugins.callback import CallbackBase
|
||||||
|
|
||||||
|
|
||||||
@@ -157,7 +157,7 @@ def dict_fromkeys(keys, default=None):
|
|||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
class BaseProf(with_metaclass(ABCMeta, threading.Thread)):
|
class BaseProf(threading.Thread, metaclass=ABCMeta):
|
||||||
def __init__(self, path, obj=None, writer=None):
|
def __init__(self, path, obj=None, writer=None):
|
||||||
threading.Thread.__init__(self) # pylint: disable=non-parent-init-called
|
threading.Thread.__init__(self) # pylint: disable=non-parent-init-called
|
||||||
self.obj = obj
|
self.obj = obj
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ import json
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from ansible.inventory.host import Host
|
from ansible.inventory.host import Host
|
||||||
from ansible.module_utils._text import to_text
|
from ansible.module_utils.common.text.converters import to_text
|
||||||
from ansible.parsing.ajson import AnsibleJSONEncoder
|
from ansible.parsing.ajson import AnsibleJSONEncoder
|
||||||
from ansible.plugins.callback import CallbackBase
|
from ansible.plugins.callback import CallbackBase
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ import copy
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from ansible.inventory.host import Host
|
from ansible.inventory.host import Host
|
||||||
from ansible.module_utils._text import to_text
|
from ansible.module_utils.common.text.converters import to_text
|
||||||
from ansible.parsing.ajson import AnsibleJSONEncoder
|
from ansible.parsing.ajson import AnsibleJSONEncoder
|
||||||
from ansible.plugins.callback import CallbackBase
|
from ansible.plugins.callback import CallbackBase
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import collections
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
from ansible.plugins.callback import CallbackBase
|
from ansible.plugins.callback import CallbackBase
|
||||||
from ansible.module_utils.six.moves import reduce
|
from functools import reduce
|
||||||
|
|
||||||
# define start time
|
# define start time
|
||||||
t0 = tn = time.time()
|
t0 = tn = time.time()
|
||||||
@@ -124,10 +124,7 @@ class CallbackModule(CallbackBase):
|
|||||||
def v2_playbook_on_handler_task_start(self, task):
|
def v2_playbook_on_handler_task_start(self, task):
|
||||||
self._record_task(task)
|
self._record_task(task)
|
||||||
|
|
||||||
def playbook_on_setup(self):
|
def v2_playbook_on_stats(self, stats):
|
||||||
self._display_tasktime()
|
|
||||||
|
|
||||||
def playbook_on_stats(self, stats):
|
|
||||||
# Align summary report header with other callback plugin summary
|
# Align summary report header with other callback plugin summary
|
||||||
self._display.banner("ROLES RECAP")
|
self._display.banner("ROLES RECAP")
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,17 @@ DOCUMENTATION = '''
|
|||||||
- section: callback_profile_tasks
|
- section: callback_profile_tasks
|
||||||
key: summary_only
|
key: summary_only
|
||||||
version_added: 1.5.0
|
version_added: 1.5.0
|
||||||
|
datetime_format:
|
||||||
|
description:
|
||||||
|
- Datetime format, as expected by the C(strftime) and C(strptime) methods.
|
||||||
|
An C(iso8601) alias will be translated to C('%Y-%m-%dT%H:%M:%S.%f') if that datetime standard wants to be used.
|
||||||
|
default: '%A %d %B %Y %H:%M:%S %z'
|
||||||
|
env:
|
||||||
|
- name: PROFILE_TASKS_DATETIME_FORMAT
|
||||||
|
ini:
|
||||||
|
- section: callback_profile_tasks
|
||||||
|
key: datetime_format
|
||||||
|
version_added: 3.0.0
|
||||||
'''
|
'''
|
||||||
|
|
||||||
EXAMPLES = '''
|
EXAMPLES = '''
|
||||||
@@ -72,14 +83,15 @@ sample output: >
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
import time
|
|
||||||
|
|
||||||
from ansible.module_utils.six.moves import reduce
|
from datetime import datetime
|
||||||
|
|
||||||
|
from functools import reduce
|
||||||
from ansible.plugins.callback import CallbackBase
|
from ansible.plugins.callback import CallbackBase
|
||||||
|
|
||||||
|
|
||||||
# define start time
|
# define start time
|
||||||
t0 = tn = time.time()
|
dt0 = dtn = datetime.now().astimezone()
|
||||||
|
|
||||||
|
|
||||||
def secondsToStr(t):
|
def secondsToStr(t):
|
||||||
@@ -104,17 +116,18 @@ def filled(msg, fchar="*"):
|
|||||||
|
|
||||||
def timestamp(self):
|
def timestamp(self):
|
||||||
if self.current is not None:
|
if self.current is not None:
|
||||||
elapsed = time.time() - self.stats[self.current]['started']
|
elapsed = (datetime.now().astimezone() - self.stats[self.current]['started']).total_seconds()
|
||||||
self.stats[self.current]['elapsed'] += elapsed
|
self.stats[self.current]['elapsed'] += elapsed
|
||||||
|
|
||||||
|
|
||||||
def tasktime():
|
def tasktime(self):
|
||||||
global tn
|
global dtn
|
||||||
time_current = time.strftime('%A %d %B %Y %H:%M:%S %z')
|
cdtn = datetime.now().astimezone()
|
||||||
time_elapsed = secondsToStr(time.time() - tn)
|
datetime_current = cdtn.strftime(self.datetime_format)
|
||||||
time_total_elapsed = secondsToStr(time.time() - t0)
|
time_elapsed = secondsToStr((cdtn - dtn).total_seconds())
|
||||||
tn = time.time()
|
time_total_elapsed = secondsToStr((cdtn - dt0).total_seconds())
|
||||||
return filled('%s (%s)%s%s' % (time_current, time_elapsed, ' ' * 7, time_total_elapsed))
|
dtn = cdtn
|
||||||
|
return filled('%s (%s)%s%s' % (datetime_current, time_elapsed, ' ' * 7, time_total_elapsed))
|
||||||
|
|
||||||
|
|
||||||
class CallbackModule(CallbackBase):
|
class CallbackModule(CallbackBase):
|
||||||
@@ -134,6 +147,7 @@ class CallbackModule(CallbackBase):
|
|||||||
self.sort_order = None
|
self.sort_order = None
|
||||||
self.summary_only = None
|
self.summary_only = None
|
||||||
self.task_output_limit = None
|
self.task_output_limit = None
|
||||||
|
self.datetime_format = None
|
||||||
|
|
||||||
super(CallbackModule, self).__init__()
|
super(CallbackModule, self).__init__()
|
||||||
|
|
||||||
@@ -159,9 +173,14 @@ class CallbackModule(CallbackBase):
|
|||||||
else:
|
else:
|
||||||
self.task_output_limit = int(self.task_output_limit)
|
self.task_output_limit = int(self.task_output_limit)
|
||||||
|
|
||||||
|
self.datetime_format = self.get_option('datetime_format')
|
||||||
|
if self.datetime_format is not None:
|
||||||
|
if self.datetime_format == 'iso8601':
|
||||||
|
self.datetime_format = '%Y-%m-%dT%H:%M:%S.%f'
|
||||||
|
|
||||||
def _display_tasktime(self):
|
def _display_tasktime(self):
|
||||||
if not self.summary_only:
|
if not self.summary_only:
|
||||||
self._display.display(tasktime())
|
self._display.display(tasktime(self))
|
||||||
|
|
||||||
def _record_task(self, task):
|
def _record_task(self, task):
|
||||||
"""
|
"""
|
||||||
@@ -176,10 +195,11 @@ class CallbackModule(CallbackBase):
|
|||||||
# with the same UUID is executed when `serial` is specified in a playbook.
|
# with the same UUID is executed when `serial` is specified in a playbook.
|
||||||
# elapsed: Elapsed time since the first serialized task was started
|
# elapsed: Elapsed time since the first serialized task was started
|
||||||
self.current = task._uuid
|
self.current = task._uuid
|
||||||
|
dtn = datetime.now().astimezone()
|
||||||
if self.current not in self.stats:
|
if self.current not in self.stats:
|
||||||
self.stats[self.current] = {'started': time.time(), 'elapsed': 0.0, 'name': task.get_name()}
|
self.stats[self.current] = {'started': dtn, 'elapsed': 0.0, 'name': task.get_name()}
|
||||||
else:
|
else:
|
||||||
self.stats[self.current]['started'] = time.time()
|
self.stats[self.current]['started'] = dtn
|
||||||
if self._display.verbosity >= 2:
|
if self._display.verbosity >= 2:
|
||||||
self.stats[self.current]['path'] = task.get_path()
|
self.stats[self.current]['path'] = task.get_path()
|
||||||
|
|
||||||
@@ -189,14 +209,11 @@ class CallbackModule(CallbackBase):
|
|||||||
def v2_playbook_on_handler_task_start(self, task):
|
def v2_playbook_on_handler_task_start(self, task):
|
||||||
self._record_task(task)
|
self._record_task(task)
|
||||||
|
|
||||||
def playbook_on_setup(self):
|
def v2_playbook_on_stats(self, stats):
|
||||||
self._display_tasktime()
|
|
||||||
|
|
||||||
def playbook_on_stats(self, stats):
|
|
||||||
# Align summary report header with other callback plugin summary
|
# Align summary report header with other callback plugin summary
|
||||||
self._display.banner("TASKS RECAP")
|
self._display.banner("TASKS RECAP")
|
||||||
|
|
||||||
self._display.display(tasktime())
|
self._display.display(tasktime(self))
|
||||||
self._display.display(filled("", fchar="="))
|
self._display.display(filled("", fchar="="))
|
||||||
|
|
||||||
timestamp(self)
|
timestamp(self)
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ import os
|
|||||||
import platform
|
import platform
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible.module_utils._text import to_native
|
from ansible.module_utils.common.text.converters import to_native
|
||||||
|
|
||||||
|
|
||||||
def split_entry(entry):
|
def split_entry(entry):
|
||||||
|
|||||||
@@ -225,12 +225,21 @@ import os.path
|
|||||||
import tempfile
|
import tempfile
|
||||||
import re
|
import re
|
||||||
import shlex
|
import shlex
|
||||||
|
import errno
|
||||||
|
import traceback
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
|
|
||||||
from ansible.module_utils._text import to_native
|
# TODO(Python2): urllib.parse is available in Python 3. This module may run on
|
||||||
|
# target hosts with Python 2.7 (e.g., older RHEL systems in CI integration tests).
|
||||||
|
# Remove the try/except fallback to urlparse when Python 2 support is dropped.
|
||||||
|
try:
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
except ImportError:
|
||||||
|
from urlparse import urlparse
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
from ansible.module_utils.common.text.converters import to_native
|
||||||
from ansible.module_utils.urls import fetch_url
|
from ansible.module_utils.urls import fetch_url
|
||||||
from ansible.module_utils.six.moves.urllib.parse import urlparse
|
|
||||||
|
|
||||||
|
|
||||||
class keydict(dict):
|
class keydict(dict):
|
||||||
@@ -475,16 +484,18 @@ def parsekey(module, raw_key, rank=None):
|
|||||||
return (key, key_type, options, comment, rank)
|
return (key, key_type, options, comment, rank)
|
||||||
|
|
||||||
|
|
||||||
def readfile(filename):
|
def readfile(module, filename):
|
||||||
|
|
||||||
if not os.path.isfile(filename):
|
|
||||||
return ''
|
|
||||||
|
|
||||||
f = open(filename)
|
|
||||||
try:
|
try:
|
||||||
|
with open(filename, 'r') as f:
|
||||||
return f.read()
|
return f.read()
|
||||||
finally:
|
except IOError as e:
|
||||||
f.close()
|
if e.errno == errno.EACCES:
|
||||||
|
module.fail_json(msg="Permission denied on file or path for authorized keys file: %s" % filename,
|
||||||
|
exception=traceback.format_exc())
|
||||||
|
elif e.errno == errno.ENOENT:
|
||||||
|
return ''
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
def parsekeys(module, lines):
|
def parsekeys(module, lines):
|
||||||
@@ -597,7 +608,7 @@ def enforce_state(module, params):
|
|||||||
# check current state -- just get the filename, don't create file
|
# check current state -- just get the filename, don't create file
|
||||||
do_write = False
|
do_write = False
|
||||||
params["keyfile"] = keyfile(module, user, do_write, path, manage_dir)
|
params["keyfile"] = keyfile(module, user, do_write, path, manage_dir)
|
||||||
existing_content = readfile(params["keyfile"])
|
existing_content = readfile(module, params["keyfile"])
|
||||||
existing_keys = parsekeys(module, existing_content)
|
existing_keys = parsekeys(module, existing_content)
|
||||||
|
|
||||||
# Add a place holder for keys that should exist in the state=present and
|
# Add a place holder for keys that should exist in the state=present and
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ firewalld_info:
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||||
from ansible.module_utils._text import to_native
|
from ansible.module_utils.common.text.converters import to_native
|
||||||
from ansible_collections.ansible.posix.plugins.module_utils._respawn import respawn_module, HAS_RESPAWN_UTIL
|
from ansible_collections.ansible.posix.plugins.module_utils._respawn import respawn_module, HAS_RESPAWN_UTIL
|
||||||
from ansible_collections.ansible.posix.plugins.module_utils.version import StrictVersion
|
from ansible_collections.ansible.posix.plugins.module_utils.version import StrictVersion
|
||||||
|
|
||||||
@@ -319,7 +319,6 @@ def main():
|
|||||||
active_zones=module.params['active_zones'],
|
active_zones=module.params['active_zones'],
|
||||||
collected_zones=list(),
|
collected_zones=list(),
|
||||||
undefined_zones=list(),
|
undefined_zones=list(),
|
||||||
warnings=list(),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Exit with failure message if requirements modules are not installed.
|
# Exit with failure message if requirements modules are not installed.
|
||||||
|
|||||||
@@ -225,8 +225,7 @@ import platform
|
|||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
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.common.text.converters import to_bytes, to_native
|
||||||
from ansible.module_utils._text import to_bytes, to_native
|
|
||||||
from ansible.module_utils.parsing.convert_bool import boolean
|
from ansible.module_utils.parsing.convert_bool import boolean
|
||||||
|
|
||||||
|
|
||||||
@@ -279,7 +278,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) if k != 'warnings'])
|
escaped_args = dict([(k, _escape_fstab(v)) for k, v in args.items()])
|
||||||
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':
|
||||||
@@ -804,7 +803,6 @@ def main():
|
|||||||
passno='-',
|
passno='-',
|
||||||
fstab=module.params['fstab'],
|
fstab=module.params['fstab'],
|
||||||
boot='yes' if module.params['boot'] else 'no',
|
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'
|
||||||
@@ -816,7 +814,6 @@ def main():
|
|||||||
passno='0',
|
passno='0',
|
||||||
fstab=module.params['fstab'],
|
fstab=module.params['fstab'],
|
||||||
boot='yes',
|
boot='yes',
|
||||||
warnings=[]
|
|
||||||
)
|
)
|
||||||
if args['fstab'] is None:
|
if args['fstab'] is None:
|
||||||
args['fstab'] = '/etc/fstab'
|
args['fstab'] = '/etc/fstab'
|
||||||
@@ -834,8 +831,7 @@ 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'].append('Cannot open file /proc/self/mountinfo.'
|
module.warn('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'):
|
||||||
@@ -847,7 +843,7 @@ def main():
|
|||||||
# specified in 'opts', mount module will ignore 'boot'.
|
# specified in 'opts', mount module will ignore 'boot'.
|
||||||
opts = args['opts'].split(',')
|
opts = args['opts'].split(',')
|
||||||
if module.params['boot'] and 'noauto' in opts:
|
if module.params['boot'] and 'noauto' in opts:
|
||||||
args['warnings'].append("Ignore the 'boot' due to 'opts' contains 'noauto'.")
|
module.warn("Ignore the 'boot' due to 'opts' contains 'noauto'.")
|
||||||
elif not module.params['boot']:
|
elif not module.params['boot']:
|
||||||
args['boot'] = 'no'
|
args['boot'] = 'no'
|
||||||
opts.append('noauto')
|
opts.append('noauto')
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ import os
|
|||||||
import platform
|
import platform
|
||||||
from traceback import format_exc
|
from traceback import format_exc
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible.module_utils._text import to_native
|
from ansible.module_utils.common.text.converters import to_native
|
||||||
|
|
||||||
|
|
||||||
class PatchError(Exception):
|
class PatchError(Exception):
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ import os
|
|||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible.module_utils._text import to_text
|
from ansible.module_utils.common.text.converters import to_text
|
||||||
|
|
||||||
|
|
||||||
def locally_installed(module, pkgname):
|
def locally_installed(module, pkgname):
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ import os
|
|||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible.module_utils._text import to_native, to_text
|
from ansible.module_utils.common.text.converters import to_native, to_text
|
||||||
|
|
||||||
|
|
||||||
def rpm_ostree_transaction(module):
|
def rpm_ostree_transaction(module):
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ except ImportError:
|
|||||||
HAVE_SEMANAGE = False
|
HAVE_SEMANAGE = 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._text import to_text
|
from ansible.module_utils.common.text.converters import to_text
|
||||||
from ansible_collections.ansible.posix.plugins.module_utils._respawn import respawn_module, HAS_RESPAWN_UTIL
|
from ansible_collections.ansible.posix.plugins.module_utils._respawn import respawn_module, HAS_RESPAWN_UTIL
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -367,9 +367,16 @@ EXAMPLES = r'''
|
|||||||
import os
|
import os
|
||||||
import errno
|
import errno
|
||||||
|
|
||||||
|
# TODO(Python2): shlex.quote was added in Python 3.3. This module may run on
|
||||||
|
# target hosts with Python 2.7 (e.g., older RHEL systems in CI integration tests).
|
||||||
|
# Remove the try/except fallback to pipes.quote when Python 2 support is dropped.
|
||||||
|
try:
|
||||||
|
from shlex import quote as shlex_quote
|
||||||
|
except ImportError:
|
||||||
|
from pipes import quote as shlex_quote
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible.module_utils._text import to_bytes, to_native
|
from ansible.module_utils.common.text.converters import to_bytes, to_native
|
||||||
from ansible.module_utils.six.moves import shlex_quote
|
|
||||||
|
|
||||||
|
|
||||||
client_addr = None
|
client_addr = None
|
||||||
|
|||||||
@@ -80,6 +80,13 @@ EXAMPLES = r'''
|
|||||||
sysctl_file: /tmp/test_sysctl.conf
|
sysctl_file: /tmp/test_sysctl.conf
|
||||||
reload: false
|
reload: false
|
||||||
|
|
||||||
|
# Enable resource limits management in FreeBSD
|
||||||
|
- ansible.posix.sysctl:
|
||||||
|
name: kern.racct.enable
|
||||||
|
value: '1'
|
||||||
|
sysctl_file: /boot/loader.conf
|
||||||
|
reload: false
|
||||||
|
|
||||||
# Set ip forwarding on in /proc and verify token value with the sysctl command
|
# Set ip forwarding on in /proc and verify token value with the sysctl command
|
||||||
- ansible.posix.sysctl:
|
- ansible.posix.sysctl:
|
||||||
name: net.ipv4.ip_forward
|
name: net.ipv4.ip_forward
|
||||||
@@ -100,12 +107,20 @@ EXAMPLES = r'''
|
|||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import re
|
import re
|
||||||
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
|
# TODO(Python2): On Python 2, string_types is basestring (str + unicode).
|
||||||
|
# This module may run on target hosts with Python 2.7.
|
||||||
|
# Remove the Python 2 branch when Python 2 support is dropped.
|
||||||
|
if sys.version_info >= (3, 0):
|
||||||
|
string_types = str
|
||||||
|
else:
|
||||||
|
string_types = basestring # pylint: disable=undefined-variable
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible.module_utils.six import string_types
|
from ansible.module_utils.common.text.converters import to_native
|
||||||
from ansible.module_utils.parsing.convert_bool import BOOLEANS_FALSE, BOOLEANS_TRUE
|
from ansible.module_utils.parsing.convert_bool import BOOLEANS_FALSE, BOOLEANS_TRUE
|
||||||
from ansible.module_utils._text import to_native
|
|
||||||
|
|
||||||
|
|
||||||
class SysctlModule(object):
|
class SysctlModule(object):
|
||||||
|
|||||||
@@ -13,8 +13,7 @@ DOCUMENTATION = '''
|
|||||||
- shell_common
|
- shell_common
|
||||||
'''
|
'''
|
||||||
|
|
||||||
from ansible.module_utils.six import text_type
|
from shlex import quote as shlex_quote
|
||||||
from ansible.module_utils.six.moves import shlex_quote
|
|
||||||
from ansible.plugins.shell import ShellBase
|
from ansible.plugins.shell import ShellBase
|
||||||
|
|
||||||
|
|
||||||
@@ -43,5 +42,5 @@ class ShellModule(ShellBase):
|
|||||||
ret = []
|
ret = []
|
||||||
# All the -u options must be first, so we process them first
|
# All the -u options must be first, so we process them first
|
||||||
ret += ['-u %s' % k for k, v in kwargs.items() if v is None]
|
ret += ['-u %s' % k for k, v in kwargs.items() if v is None]
|
||||||
ret += ['%s=%s' % (k, shlex_quote(text_type(v))) for k, v in kwargs.items() if v is not None]
|
ret += ['%s=%s' % (k, shlex_quote(str(v))) for k, v in kwargs.items() if v is not None]
|
||||||
return 'env %s' % ' '.join(ret)
|
return 'env %s' % ' '.join(ret)
|
||||||
|
|||||||
@@ -13,8 +13,7 @@ DOCUMENTATION = '''
|
|||||||
- shell_common
|
- shell_common
|
||||||
'''
|
'''
|
||||||
|
|
||||||
from ansible.module_utils.six import text_type
|
from shlex import quote as shlex_quote
|
||||||
from ansible.module_utils.six.moves import shlex_quote
|
|
||||||
from ansible.plugins.shell.sh import ShellModule as ShModule
|
from ansible.plugins.shell.sh import ShellModule as ShModule
|
||||||
|
|
||||||
|
|
||||||
@@ -42,7 +41,7 @@ class ShellModule(ShModule):
|
|||||||
if v is None:
|
if v is None:
|
||||||
ret.append('set -e %s;' % k)
|
ret.append('set -e %s;' % k)
|
||||||
else:
|
else:
|
||||||
ret.append('set -lx %s %s;' % (k, shlex_quote(text_type(v))))
|
ret.append('set -lx %s %s;' % (k, shlex_quote(str(v))))
|
||||||
return ' '.join(ret)
|
return ' '.join(ret)
|
||||||
|
|
||||||
def build_module_command(self, env_string, shebang, cmd, arg_path=None):
|
def build_module_command(self, env_string, shebang, cmd, arg_path=None):
|
||||||
|
|||||||
@@ -46,6 +46,12 @@
|
|||||||
path: "{{ test_dir }}"
|
path: "{{ test_dir }}"
|
||||||
state: directory
|
state: directory
|
||||||
mode: "0755"
|
mode: "0755"
|
||||||
|
|
||||||
|
- name: Install acl package
|
||||||
|
ansible.builtin.package:
|
||||||
|
name: acl
|
||||||
|
state: present
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
- name: Grant ansible user read access to a file
|
- name: Grant ansible user read access to a file
|
||||||
ansible.posix.acl:
|
ansible.posix.acl:
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
---
|
||||||
|
# -------------------------------------------------------------
|
||||||
|
# check permissions
|
||||||
|
|
||||||
|
- name: Create a file that is not accessible
|
||||||
|
ansible.builtin.file:
|
||||||
|
state: touch
|
||||||
|
path: "{{ output_dir | expanduser }}/file_permissions"
|
||||||
|
owner: root
|
||||||
|
mode: '0000'
|
||||||
|
|
||||||
|
- name: Create unprivileged user
|
||||||
|
ansible.builtin.user:
|
||||||
|
name: nopriv
|
||||||
|
create_home: true
|
||||||
|
|
||||||
|
- name: Try to delete a key from an unreadable file
|
||||||
|
become: true
|
||||||
|
become_user: nopriv
|
||||||
|
ansible.posix.authorized_key:
|
||||||
|
user: root
|
||||||
|
key: "{{ dss_key_basic }}"
|
||||||
|
state: absent
|
||||||
|
path: "{{ output_dir | expanduser }}/file_permissions"
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Assert that the key deletion has failed
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- result is failed
|
||||||
|
|
||||||
|
- name: Remove the file
|
||||||
|
ansible.builtin.file:
|
||||||
|
state: absent
|
||||||
|
path: "{{ output_dir | expanduser }}/file_permissions"
|
||||||
|
|
||||||
|
- name: Remove the user
|
||||||
|
ansible.builtin.user:
|
||||||
|
name: nopriv
|
||||||
|
state: absent
|
||||||
@@ -34,3 +34,6 @@
|
|||||||
|
|
||||||
- name: Test for specifying key as a path
|
- name: Test for specifying key as a path
|
||||||
ansible.builtin.import_tasks: check_path.yml
|
ansible.builtin.import_tasks: check_path.yml
|
||||||
|
|
||||||
|
- name: Test for permission denied files
|
||||||
|
ansible.builtin.import_tasks: check_permissions.yml
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
needs/privileged
|
||||||
|
needs/root
|
||||||
destructive
|
destructive
|
||||||
shippable/posix/group1
|
shippable/posix/group1
|
||||||
skip/aix
|
skip/aix
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# SETUP ################################################################################
|
||||||
- name: Install dependencies (Linux)
|
- name: Install dependencies (Linux)
|
||||||
ansible.builtin.package:
|
ansible.builtin.package:
|
||||||
name: e2fsprogs
|
name: e2fsprogs
|
||||||
@@ -110,6 +111,42 @@
|
|||||||
mode: '0644'
|
mode: '0644'
|
||||||
register: orig_info
|
register: orig_info
|
||||||
|
|
||||||
|
# BIND MOUNT ################################################################################
|
||||||
|
# bind mount check mode
|
||||||
|
- name: Bind mount a filesystem (Linux) (check mode)
|
||||||
|
ansible.posix.mount:
|
||||||
|
src: '{{ output_dir }}/mount_source'
|
||||||
|
name: '{{ output_dir }}/mount_dest'
|
||||||
|
state: mounted
|
||||||
|
fstype: None
|
||||||
|
opts: bind
|
||||||
|
when: ansible_system == 'Linux'
|
||||||
|
register: bind_result_linux_dry_run
|
||||||
|
check_mode: true
|
||||||
|
|
||||||
|
- name: Bind mount a filesystem (FreeBSD) (check mode)
|
||||||
|
ansible.posix.mount:
|
||||||
|
src: '{{ output_dir }}/mount_source'
|
||||||
|
name: '{{ output_dir }}/mount_dest'
|
||||||
|
state: mounted
|
||||||
|
fstype: nullfs
|
||||||
|
when: ansible_system == 'FreeBSD'
|
||||||
|
register: bind_result_freebsd_dry_run
|
||||||
|
check_mode: true
|
||||||
|
|
||||||
|
- name: Attempt to stat bind mounted file
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: '{{ output_dir }}/mount_dest/test_file'
|
||||||
|
when: ansible_system in ('FreeBSD', 'Linux')
|
||||||
|
register: dest_stat
|
||||||
|
|
||||||
|
- name: Assert the bind mount did not take place
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- not dest_stat['stat']['exists']
|
||||||
|
when: ansible_system in ('FreeBSD', 'Linux')
|
||||||
|
|
||||||
|
# bind mount
|
||||||
- name: Bind mount a filesystem (Linux)
|
- name: Bind mount a filesystem (Linux)
|
||||||
ansible.posix.mount:
|
ansible.posix.mount:
|
||||||
src: '{{ output_dir }}/mount_source'
|
src: '{{ output_dir }}/mount_source'
|
||||||
@@ -168,6 +205,48 @@
|
|||||||
- (ansible_system == 'Linux' and not bind_result_linux['changed']) or (ansible_system == 'FreeBSD' and not bind_result_freebsd['changed'])
|
- (ansible_system == 'Linux' and not bind_result_linux['changed']) or (ansible_system == 'FreeBSD' and not bind_result_freebsd['changed'])
|
||||||
when: ansible_system in ('FreeBSD', 'Linux')
|
when: ansible_system in ('FreeBSD', 'Linux')
|
||||||
|
|
||||||
|
# remount check mode
|
||||||
|
- name: Remount filesystem with different opts (Linux) (check mode)
|
||||||
|
ansible.posix.mount:
|
||||||
|
src: '{{ output_dir }}/mount_source'
|
||||||
|
name: '{{ output_dir }}/mount_dest'
|
||||||
|
state: mounted
|
||||||
|
fstype: None
|
||||||
|
opts: bind,ro
|
||||||
|
when: ansible_system == 'Linux'
|
||||||
|
register: bind_result_linux
|
||||||
|
check_mode: true
|
||||||
|
|
||||||
|
- name: Remount filesystem with different opts (FreeBSD) (check mode)
|
||||||
|
ansible.posix.mount:
|
||||||
|
src: '{{ output_dir }}/mount_source'
|
||||||
|
name: '{{ output_dir }}/mount_dest'
|
||||||
|
state: mounted
|
||||||
|
fstype: nullfs
|
||||||
|
opts: ro
|
||||||
|
when: ansible_system == 'FreeBSD'
|
||||||
|
register: bind_result_freebsd
|
||||||
|
check_mode: true
|
||||||
|
|
||||||
|
- name: Get mount options
|
||||||
|
ansible.builtin.shell:
|
||||||
|
cmd: set -o pipefail && mount | grep mount_dest | grep -c -E -w '(ro|read-only)'
|
||||||
|
executable: "{{ shell_executable }}"
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
register: new_options_count
|
||||||
|
|
||||||
|
- name: Make sure the filesystem does not have the new opts
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- linux_and_changed or freebsd_and_changed
|
||||||
|
- new_options_count.stdout | int == 0
|
||||||
|
vars:
|
||||||
|
linux_and_changed: "{{ ansible_system == 'Linux' and bind_result_linux_dry_run['changed'] }}"
|
||||||
|
freebsd_and_changed: "{{ ansible_system == 'FreeBSD' and bind_result_freebsd['changed'] }}"
|
||||||
|
when: ansible_system in ('FreeBSD', 'Linux')
|
||||||
|
|
||||||
|
# remount
|
||||||
- name: Remount filesystem with different opts (Linux)
|
- name: Remount filesystem with different opts (Linux)
|
||||||
ansible.posix.mount:
|
ansible.posix.mount:
|
||||||
src: '{{ output_dir }}/mount_source'
|
src: '{{ output_dir }}/mount_source'
|
||||||
@@ -203,6 +282,29 @@
|
|||||||
- 1 == remount_options.stdout_lines | length
|
- 1 == remount_options.stdout_lines | length
|
||||||
when: ansible_system in ('FreeBSD', 'Linux')
|
when: ansible_system in ('FreeBSD', 'Linux')
|
||||||
|
|
||||||
|
# unmount check mode
|
||||||
|
- name: Unmount the bind mount (check mode)
|
||||||
|
ansible.posix.mount:
|
||||||
|
name: '{{ output_dir }}/mount_dest'
|
||||||
|
state: absent
|
||||||
|
when: ansible_system in ('Linux', 'FreeBSD')
|
||||||
|
register: unmount_result
|
||||||
|
check_mode: true
|
||||||
|
|
||||||
|
- name: Make sure the file still exists in dest
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: '{{ output_dir }}/mount_dest/test_file'
|
||||||
|
when: ansible_system in ('FreeBSD', 'Linux')
|
||||||
|
register: dest_stat
|
||||||
|
|
||||||
|
- name: Check that we did not unmount
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- unmount_result['changed']
|
||||||
|
- dest_stat['stat']['exists']
|
||||||
|
when: ansible_system in ('FreeBSD', 'Linux')
|
||||||
|
|
||||||
|
# unmount
|
||||||
- name: Unmount the bind mount
|
- name: Unmount the bind mount
|
||||||
ansible.posix.mount:
|
ansible.posix.mount:
|
||||||
name: '{{ output_dir }}/mount_dest'
|
name: '{{ output_dir }}/mount_dest'
|
||||||
@@ -223,9 +325,36 @@
|
|||||||
- not dest_stat['stat']['exists']
|
- not dest_stat['stat']['exists']
|
||||||
when: ansible_system in ('FreeBSD', 'Linux')
|
when: ansible_system in ('FreeBSD', 'Linux')
|
||||||
|
|
||||||
- name: Block to test remounted option
|
# SWAP #############################################################
|
||||||
|
- name: Swap
|
||||||
when: ansible_system in ('Linux')
|
when: ansible_system in ('Linux')
|
||||||
block:
|
block:
|
||||||
|
# mount swap check mode
|
||||||
|
- name: Stat /etc/fstab
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: /etc/fstab
|
||||||
|
register: stat_fstab_before
|
||||||
|
|
||||||
|
- name: Create fstab record for the first swap file (check mode)
|
||||||
|
ansible.posix.mount:
|
||||||
|
name: none
|
||||||
|
src: /tmp/swap1
|
||||||
|
opts: sw
|
||||||
|
fstype: swap
|
||||||
|
state: present
|
||||||
|
check_mode: true
|
||||||
|
|
||||||
|
- name: Stat /etc/fstab
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: /etc/fstab
|
||||||
|
register: stat_fstab_after
|
||||||
|
|
||||||
|
- name: Assert that fstab checksum did not change
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- stat_fstab_before.stat.checksum == stat_fstab_after.stat.checksum
|
||||||
|
|
||||||
|
# mount swap1
|
||||||
- name: Create fstab record for the first swap file
|
- name: Create fstab record for the first swap file
|
||||||
ansible.posix.mount:
|
ansible.posix.mount:
|
||||||
name: none
|
name: none
|
||||||
@@ -250,6 +379,7 @@
|
|||||||
- swap1_created['changed']
|
- swap1_created['changed']
|
||||||
- not swap1_created_again['changed']
|
- not swap1_created_again['changed']
|
||||||
|
|
||||||
|
# mount swap2
|
||||||
- name: Create fstab record for the second swap file
|
- name: Create fstab record for the second swap file
|
||||||
ansible.posix.mount:
|
ansible.posix.mount:
|
||||||
name: none
|
name: none
|
||||||
@@ -274,6 +404,30 @@
|
|||||||
- swap2_created['changed']
|
- swap2_created['changed']
|
||||||
- not swap2_created_again['changed']
|
- not swap2_created_again['changed']
|
||||||
|
|
||||||
|
# remove swap check mode
|
||||||
|
- name: Stat /etc/fstab
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: /etc/fstab
|
||||||
|
register: stat_fstab_before
|
||||||
|
|
||||||
|
- name: Remove the fstab record for the first swap file (check mode)
|
||||||
|
ansible.posix.mount:
|
||||||
|
name: none
|
||||||
|
src: /tmp/swap1
|
||||||
|
state: absent
|
||||||
|
check_mode: true
|
||||||
|
|
||||||
|
- name: Stat /etc/fstab
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: /etc/fstab
|
||||||
|
register: stat_fstab_after
|
||||||
|
|
||||||
|
- name: Assert that fstab checksum did not change
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- stat_fstab_before.stat.checksum == stat_fstab_after.stat.checksum
|
||||||
|
|
||||||
|
# remove swap1
|
||||||
- name: Remove the fstab record for the first swap file
|
- name: Remove the fstab record for the first swap file
|
||||||
ansible.posix.mount:
|
ansible.posix.mount:
|
||||||
name: none
|
name: none
|
||||||
@@ -294,6 +448,7 @@
|
|||||||
- swap1_removed['changed']
|
- swap1_removed['changed']
|
||||||
- not swap1_removed_again['changed']
|
- not swap1_removed_again['changed']
|
||||||
|
|
||||||
|
# remove swap2
|
||||||
- name: Remove the fstab record for the second swap file
|
- name: Remove the fstab record for the second swap file
|
||||||
ansible.posix.mount:
|
ansible.posix.mount:
|
||||||
name: none
|
name: none
|
||||||
@@ -314,6 +469,10 @@
|
|||||||
- swap2_removed['changed']
|
- swap2_removed['changed']
|
||||||
- not swap2_removed_again['changed']
|
- not swap2_removed_again['changed']
|
||||||
|
|
||||||
|
# FIXUP #############################################################
|
||||||
|
- name: Fix incomplete entry already present in fstab
|
||||||
|
when: ansible_system == 'Linux'
|
||||||
|
block:
|
||||||
- name: Create fstab record with missing last two fields
|
- name: Create fstab record with missing last two fields
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
dest: /etc/fstab
|
dest: /etc/fstab
|
||||||
@@ -343,6 +502,11 @@
|
|||||||
- ''' 0 0'' in optional_fields_content.stdout'
|
- ''' 0 0'' in optional_fields_content.stdout'
|
||||||
- 1 == optional_fields_content.stdout_lines | length
|
- 1 == optional_fields_content.stdout_lines | length
|
||||||
|
|
||||||
|
# REMOUNTED #############################################################
|
||||||
|
- name: Block to test remounted option
|
||||||
|
when: ansible_system in ('Linux')
|
||||||
|
block:
|
||||||
|
# setup
|
||||||
- name: Create empty file
|
- name: Create empty file
|
||||||
community.general.filesize:
|
community.general.filesize:
|
||||||
path: /tmp/myfs.img
|
path: /tmp/myfs.img
|
||||||
@@ -372,6 +536,26 @@
|
|||||||
ansible.builtin.pause:
|
ansible.builtin.pause:
|
||||||
seconds: 2
|
seconds: 2
|
||||||
|
|
||||||
|
# remount check mode
|
||||||
|
- name: Remount (check mode)
|
||||||
|
ansible.posix.mount:
|
||||||
|
path: /tmp/myfs
|
||||||
|
state: remounted
|
||||||
|
|
||||||
|
- name: Get again the last write time
|
||||||
|
ansible.builtin.shell:
|
||||||
|
cmd: >-
|
||||||
|
set -o pipefail && dumpe2fs /tmp/myfs.img 2>/dev/null | grep -i "last write time:" |cut -d: -f2-
|
||||||
|
executable: "{{ shell_executable }}"
|
||||||
|
changed_when: false
|
||||||
|
register: last_write_time_check
|
||||||
|
|
||||||
|
- name: Fail if they are different
|
||||||
|
ansible.builtin.fail:
|
||||||
|
msg: Filesytem was remounted, testing of the module failed!
|
||||||
|
when: last_write_time.stdout != last_write_time_check.stdout
|
||||||
|
|
||||||
|
# remount
|
||||||
- name: Test if the FS is remounted
|
- name: Test if the FS is remounted
|
||||||
ansible.posix.mount:
|
ansible.posix.mount:
|
||||||
path: /tmp/myfs
|
path: /tmp/myfs
|
||||||
@@ -390,6 +574,29 @@
|
|||||||
msg: Filesytem was not remounted, testing of the module failed!
|
msg: Filesytem was not remounted, testing of the module failed!
|
||||||
when: last_write is defined and last_write_time2 is defined and last_write_time.stdout == last_write_time2.stdout
|
when: last_write is defined and last_write_time2 is defined and last_write_time.stdout == last_write_time2.stdout
|
||||||
|
|
||||||
|
# remount different options check mode
|
||||||
|
- name: Remount filesystem with different opts using remounted option (Linux only)
|
||||||
|
ansible.posix.mount:
|
||||||
|
path: /tmp/myfs
|
||||||
|
state: remounted
|
||||||
|
opts: rw,noexec
|
||||||
|
check_mode: true
|
||||||
|
|
||||||
|
- name: Get remounted options (Linux only)
|
||||||
|
ansible.builtin.shell:
|
||||||
|
cmd: set -o pipefail && mount | grep myfs | grep -E -w 'noexec' | wc -l
|
||||||
|
executable: "{{ shell_executable }}"
|
||||||
|
failed_when: false
|
||||||
|
changed_when: false
|
||||||
|
register: remounted_options
|
||||||
|
|
||||||
|
- name: Make sure the filesystem now has the new opts after using remounted (Linux only)
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- "'0' in remounted_options.stdout"
|
||||||
|
- "1 == remounted_options.stdout_lines | length"
|
||||||
|
|
||||||
|
# remount different options
|
||||||
- name: Remount filesystem with different opts using remounted option (Linux only)
|
- name: Remount filesystem with different opts using remounted option (Linux only)
|
||||||
ansible.posix.mount:
|
ansible.posix.mount:
|
||||||
path: /tmp/myfs
|
path: /tmp/myfs
|
||||||
@@ -409,6 +616,7 @@
|
|||||||
- "'1' in remounted_options.stdout"
|
- "'1' in remounted_options.stdout"
|
||||||
- "1 == remounted_options.stdout_lines | length"
|
- "1 == remounted_options.stdout_lines | length"
|
||||||
|
|
||||||
|
# backup
|
||||||
- name: Mount the FS again to test backup
|
- name: Mount the FS again to test backup
|
||||||
ansible.posix.mount:
|
ansible.posix.mount:
|
||||||
path: /tmp/myfs
|
path: /tmp/myfs
|
||||||
@@ -439,9 +647,11 @@
|
|||||||
- /tmp/myfs.img
|
- /tmp/myfs.img
|
||||||
- /tmp/myfs
|
- /tmp/myfs
|
||||||
|
|
||||||
|
# BOOT #############################################################
|
||||||
- name: Block to test boot option for Linux
|
- name: Block to test boot option for Linux
|
||||||
when: ansible_system in ('Linux')
|
when: ansible_system in ('Linux')
|
||||||
block:
|
block:
|
||||||
|
# setup
|
||||||
- name: Create empty file
|
- name: Create empty file
|
||||||
community.general.filesize:
|
community.general.filesize:
|
||||||
path: /tmp/myfs.img
|
path: /tmp/myfs.img
|
||||||
@@ -452,6 +662,7 @@
|
|||||||
fstype: ext3
|
fstype: ext3
|
||||||
dev: /tmp/myfs.img
|
dev: /tmp/myfs.img
|
||||||
|
|
||||||
|
# noauto
|
||||||
- name: Mount the FS with noauto option
|
- name: Mount the FS with noauto option
|
||||||
ansible.posix.mount:
|
ansible.posix.mount:
|
||||||
path: /tmp/myfs
|
path: /tmp/myfs
|
||||||
@@ -472,6 +683,7 @@
|
|||||||
path: /tmp/myfs
|
path: /tmp/myfs
|
||||||
state: absent
|
state: absent
|
||||||
|
|
||||||
|
# noauto + defaults
|
||||||
- name: Mount the FS with noauto option and defaults
|
- name: Mount the FS with noauto option and defaults
|
||||||
ansible.posix.mount:
|
ansible.posix.mount:
|
||||||
path: /tmp/myfs
|
path: /tmp/myfs
|
||||||
@@ -499,6 +711,7 @@
|
|||||||
- /tmp/myfs.img
|
- /tmp/myfs.img
|
||||||
- /tmp/myfs
|
- /tmp/myfs
|
||||||
|
|
||||||
|
# NEWLINE END OF FILE ############################################
|
||||||
- name: Block to test missing newline at the EOF of fstab
|
- name: Block to test missing newline at the EOF of fstab
|
||||||
when: ansible_system in ('Linux')
|
when: ansible_system in ('Linux')
|
||||||
block:
|
block:
|
||||||
@@ -537,6 +750,7 @@
|
|||||||
- /tmp/myfs1
|
- /tmp/myfs1
|
||||||
- /tmp/test_fstab
|
- /tmp/test_fstab
|
||||||
|
|
||||||
|
# EPHEMERAL ################################################
|
||||||
- name: Block to test ephemeral option
|
- name: Block to test ephemeral option
|
||||||
environment:
|
environment:
|
||||||
PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||||
@@ -553,7 +767,6 @@
|
|||||||
size: 20M
|
size: 20M
|
||||||
|
|
||||||
##### FORMAT FS ON LINUX
|
##### FORMAT FS ON LINUX
|
||||||
|
|
||||||
- name: Block to format FS on Linux
|
- name: Block to format FS on Linux
|
||||||
when: ansible_system == 'Linux'
|
when: ansible_system == 'Linux'
|
||||||
block:
|
block:
|
||||||
@@ -568,7 +781,6 @@
|
|||||||
dev: /tmp/myfs_B.img
|
dev: /tmp/myfs_B.img
|
||||||
|
|
||||||
##### FORMAT FS ON SOLARIS AND BSD
|
##### FORMAT FS ON SOLARIS AND BSD
|
||||||
|
|
||||||
- name: Create loop devices on Solaris and BSD
|
- name: Create loop devices on Solaris and BSD
|
||||||
ansible.builtin.shell:
|
ansible.builtin.shell:
|
||||||
cmd: "set -o pipefail && {{ ephemeral_create_loop_dev_cmd }}"
|
cmd: "set -o pipefail && {{ ephemeral_create_loop_dev_cmd }}"
|
||||||
@@ -583,14 +795,49 @@
|
|||||||
changed_when: true
|
changed_when: true
|
||||||
when: ephemeral_format_fs_cmd is defined
|
when: ephemeral_format_fs_cmd is defined
|
||||||
|
|
||||||
##### TESTS
|
|
||||||
|
|
||||||
- name: Create fstab if it does not exist
|
- name: Create fstab if it does not exist
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
path: "{{ ephemeral_fstab }}"
|
path: "{{ ephemeral_fstab }}"
|
||||||
state: touch
|
state: touch
|
||||||
mode: '0644'
|
mode: '0644'
|
||||||
|
|
||||||
|
# normal ephemeral mount check mode
|
||||||
|
- name: Get checksum of /etc/fstab before mounting anything
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: '{{ ephemeral_fstab }}'
|
||||||
|
register: fstab_stat_before_mount
|
||||||
|
|
||||||
|
- name: Mount the FS A with ephemeral state (check mode)
|
||||||
|
ansible.posix.mount:
|
||||||
|
path: /tmp/myfs
|
||||||
|
src: '{{ ephemeral_device_a }}'
|
||||||
|
fstype: '{{ ephemeral_fstype }}'
|
||||||
|
opts: rw
|
||||||
|
state: ephemeral
|
||||||
|
register: ephemeral_mount_info
|
||||||
|
check_mode: true
|
||||||
|
|
||||||
|
- name: Get checksum of /etc/fstab after an ephemeral mount
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: '{{ ephemeral_fstab }}'
|
||||||
|
register: fstab_stat_after_mount
|
||||||
|
|
||||||
|
- name: Get mountinfo
|
||||||
|
ansible.builtin.shell:
|
||||||
|
cmd: grep -c '/tmp/myfs' <(mount -v)
|
||||||
|
executable: "{{ shell_executable }}"
|
||||||
|
register: check_mountinfo
|
||||||
|
failed_when: false
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Assert the mount occurred and the fstab is unchanged
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- check_mountinfo.stdout|int == 0
|
||||||
|
- ephemeral_mount_info['changed']
|
||||||
|
- fstab_stat_before_mount['stat']['checksum'] == fstab_stat_after_mount['stat']['checksum']
|
||||||
|
|
||||||
|
# normal ephemeral mount
|
||||||
- name: Get checksum of /etc/fstab before mounting anything
|
- name: Get checksum of /etc/fstab before mounting anything
|
||||||
ansible.builtin.stat:
|
ansible.builtin.stat:
|
||||||
path: '{{ ephemeral_fstab }}'
|
path: '{{ ephemeral_fstab }}'
|
||||||
@@ -631,6 +878,48 @@
|
|||||||
- ephemeral_mount_info['changed']
|
- ephemeral_mount_info['changed']
|
||||||
- fstab_stat_before_mount['stat']['checksum'] == fstab_stat_after_mount['stat']['checksum']
|
- fstab_stat_before_mount['stat']['checksum'] == fstab_stat_after_mount['stat']['checksum']
|
||||||
|
|
||||||
|
# remount different options check mode
|
||||||
|
- name: Get first mount record
|
||||||
|
ansible.builtin.shell:
|
||||||
|
cmd: grep '/tmp/myfs' <(mount -v)
|
||||||
|
executable: "{{ shell_executable }}"
|
||||||
|
register: ephemeral_mount_record_1
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Try to mount FS A where FS A is already mounted (should trigger remount and changed)
|
||||||
|
ansible.posix.mount:
|
||||||
|
path: /tmp/myfs
|
||||||
|
src: '{{ ephemeral_device_a }}'
|
||||||
|
fstype: '{{ ephemeral_fstype }}'
|
||||||
|
opts: ro
|
||||||
|
state: ephemeral
|
||||||
|
register: ephemeral_mount_info
|
||||||
|
check_mode: true
|
||||||
|
|
||||||
|
- name: Get second mount record (should be different than the first)
|
||||||
|
ansible.builtin.shell:
|
||||||
|
cmd: grep '/tmp/myfs' <(mount -v)
|
||||||
|
executable: "{{ shell_executable }}"
|
||||||
|
register: ephemeral_mount_record_2
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Get mountinfo
|
||||||
|
ansible.builtin.shell:
|
||||||
|
cmd: grep -c '/tmp/myfs' <(mount -v)
|
||||||
|
executable: "{{ shell_executable }}"
|
||||||
|
failed_when: false
|
||||||
|
register: check_mountinfo
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Assert the FS A is still mounted, the options unchanged and the fstab unchanged
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- check_mountinfo.stdout|int == 1
|
||||||
|
- ephemeral_mount_record_1.stdout == ephemeral_mount_record_2.stdout
|
||||||
|
- ephemeral_mount_info['changed']
|
||||||
|
- fstab_stat_before_mount['stat']['checksum'] == fstab_stat_after_mount['stat']['checksum']
|
||||||
|
|
||||||
|
# remount different options
|
||||||
- name: Get first mount record
|
- name: Get first mount record
|
||||||
ansible.builtin.shell:
|
ansible.builtin.shell:
|
||||||
cmd: grep '/tmp/myfs' <(mount -v)
|
cmd: grep '/tmp/myfs' <(mount -v)
|
||||||
@@ -670,6 +959,7 @@
|
|||||||
- ephemeral_mount_info['changed']
|
- ephemeral_mount_info['changed']
|
||||||
- fstab_stat_before_mount['stat']['checksum'] == fstab_stat_after_mount['stat']['checksum']
|
- fstab_stat_before_mount['stat']['checksum'] == fstab_stat_after_mount['stat']['checksum']
|
||||||
|
|
||||||
|
# conflicting mount
|
||||||
- name: Try to mount file B on file A mountpoint (should fail)
|
- name: Try to mount file B on file A mountpoint (should fail)
|
||||||
ansible.posix.mount:
|
ansible.posix.mount:
|
||||||
path: /tmp/myfs
|
path: /tmp/myfs
|
||||||
@@ -707,6 +997,39 @@
|
|||||||
- test_file_stat['stat']['exists']
|
- test_file_stat['stat']['exists']
|
||||||
- ephemeral_mount_b_info is failed
|
- ephemeral_mount_b_info is failed
|
||||||
|
|
||||||
|
# unmount check mode
|
||||||
|
- name: Unmount FS with state = unmounted
|
||||||
|
ansible.posix.mount:
|
||||||
|
path: /tmp/myfs
|
||||||
|
state: unmounted
|
||||||
|
check_mode: true
|
||||||
|
|
||||||
|
- name: Get fstab checksum after unmounting an ephemeral mount with state = unmounted
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: '{{ ephemeral_fstab }}'
|
||||||
|
register: fstab_stat_after_unmount
|
||||||
|
|
||||||
|
- name: Get mountinfo
|
||||||
|
ansible.builtin.shell:
|
||||||
|
cmd: grep -c '/tmp/myfs' <(mount -v)
|
||||||
|
executable: "{{ shell_executable }}"
|
||||||
|
register: check_mountinfo
|
||||||
|
failed_when: false
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Try to stat our test file
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: /tmp/myfs/test_file
|
||||||
|
register: test_file_stat
|
||||||
|
|
||||||
|
- name: Assert that unmount did not take place and fstab unchanged
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- check_mountinfo.stdout|int == 1
|
||||||
|
- test_file_stat['stat']['exists']
|
||||||
|
- fstab_stat_before_mount['stat']['checksum'] == fstab_stat_after_unmount['stat']['checksum']
|
||||||
|
|
||||||
|
# unmount
|
||||||
- name: Unmount FS with state = unmounted
|
- name: Unmount FS with state = unmounted
|
||||||
ansible.posix.mount:
|
ansible.posix.mount:
|
||||||
path: /tmp/myfs
|
path: /tmp/myfs
|
||||||
@@ -759,6 +1082,7 @@
|
|||||||
- /tmp/myfs_B.img
|
- /tmp/myfs_B.img
|
||||||
- /tmp/myfs
|
- /tmp/myfs
|
||||||
|
|
||||||
|
# OPTS_NO_LOG ######################################
|
||||||
- name: Block to test opts_no_log option
|
- name: Block to test opts_no_log option
|
||||||
when: ansible_system == 'Linux'
|
when: ansible_system == 'Linux'
|
||||||
block:
|
block:
|
||||||
|
|||||||
@@ -20,5 +20,4 @@
|
|||||||
ansible.builtin.include_tasks: seboolean.yml
|
ansible.builtin.include_tasks: seboolean.yml
|
||||||
when:
|
when:
|
||||||
- ansible_selinux is defined
|
- ansible_selinux is defined
|
||||||
- ansible_selinux
|
|
||||||
- ansible_selinux.status == 'enabled'
|
- ansible_selinux.status == 'enabled'
|
||||||
|
|||||||
@@ -19,23 +19,21 @@
|
|||||||
- name: Debug message for when SELinux is disabled
|
- name: Debug message for when SELinux is disabled
|
||||||
ansible.builtin.debug:
|
ansible.builtin.debug:
|
||||||
msg: SELinux is disabled
|
msg: SELinux is disabled
|
||||||
when: ansible_selinux is defined and not ansible_selinux
|
when: ansible_selinux is defined and ansible_selinux.status == 'disabled'
|
||||||
|
|
||||||
- name: Debug message for when SELinux is enabled and not disabled
|
- name: Debug message for when SELinux is enabled and not disabled
|
||||||
ansible.builtin.debug:
|
ansible.builtin.debug:
|
||||||
msg: SELinux is {{ ansible_selinux.status }}
|
msg: SELinux is {{ ansible_selinux.status }}
|
||||||
when: ansible_selinux is defined and ansible_selinux
|
when: ansible_selinux is defined
|
||||||
|
|
||||||
- name: Include_tasks for when SELinux is enabled
|
- name: Include_tasks for when SELinux is enabled
|
||||||
ansible.builtin.include_tasks: selinux.yml
|
ansible.builtin.include_tasks: selinux.yml
|
||||||
when:
|
when:
|
||||||
- ansible_selinux is defined
|
- ansible_selinux is defined
|
||||||
- ansible_selinux
|
|
||||||
- ansible_selinux.status == 'enabled'
|
- ansible_selinux.status == 'enabled'
|
||||||
|
|
||||||
- name: Include tasks for selogin when SELinux is enabled
|
- name: Include tasks for selogin when SELinux is enabled
|
||||||
ansible.builtin.include_tasks: selogin.yml
|
ansible.builtin.include_tasks: selogin.yml
|
||||||
when:
|
when:
|
||||||
- ansible_selinux is defined
|
- ansible_selinux is defined
|
||||||
- ansible_selinux
|
|
||||||
- ansible_selinux.status == 'enabled'
|
- ansible_selinux.status == 'enabled'
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
tests/utils/shippable/check_matrix.py replace-urlopen
|
|
||||||
tests/utils/shippable/timing.py shebang
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
tests/utils/shippable/check_matrix.py replace-urlopen
|
|
||||||
tests/utils/shippable/timing.py shebang
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
tests/utils/shippable/timing.py shebang
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
tests/utils/shippable/timing.py shebang
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
tests/utils/shippable/timing.py shebang
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
tests/utils/shippable/timing.py shebang
|
|
||||||
|
|||||||
0
tests/sanity/ignore-2.20.txt
Normal file
0
tests/sanity/ignore-2.20.txt
Normal file
0
tests/sanity/ignore-2.21.txt
Normal file
0
tests/sanity/ignore-2.21.txt
Normal file
0
tests/sanity/ignore-2.22.txt
Normal file
0
tests/sanity/ignore-2.22.txt
Normal file
@@ -1,34 +0,0 @@
|
|||||||
# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com>
|
|
||||||
#
|
|
||||||
# This file is part of Ansible
|
|
||||||
#
|
|
||||||
# Ansible is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Ansible is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
# Make coding more python3-ish
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
#
|
|
||||||
# Compat for python2.7
|
|
||||||
#
|
|
||||||
|
|
||||||
# One unittest needs to import builtins via __import__() so we need to have
|
|
||||||
# the string that represents it
|
|
||||||
try:
|
|
||||||
import __builtin__
|
|
||||||
except ImportError:
|
|
||||||
BUILTINS = 'builtins'
|
|
||||||
else:
|
|
||||||
BUILTINS = '__builtin__'
|
|
||||||
__all__ = ['__builtin__']
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
|
|
||||||
#
|
|
||||||
# This file is part of Ansible
|
|
||||||
#
|
|
||||||
# Ansible is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Ansible is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
# Make coding more python3-ish
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
from ansible.errors import AnsibleParserError
|
|
||||||
from ansible.parsing.dataloader import DataLoader
|
|
||||||
from ansible.module_utils._text import to_bytes, to_text
|
|
||||||
|
|
||||||
|
|
||||||
class DictDataLoader(DataLoader):
|
|
||||||
|
|
||||||
def __init__(self, file_mapping=None):
|
|
||||||
file_mapping = {} if file_mapping is None else file_mapping
|
|
||||||
assert isinstance(file_mapping, dict)
|
|
||||||
|
|
||||||
super(DictDataLoader, self).__init__()
|
|
||||||
|
|
||||||
self._file_mapping = file_mapping
|
|
||||||
self._build_known_directories()
|
|
||||||
self._vault_secrets = None
|
|
||||||
|
|
||||||
def load_from_file(self, path, cache=True, unsafe=False):
|
|
||||||
path = to_text(path)
|
|
||||||
if path in self._file_mapping:
|
|
||||||
return self.load(self._file_mapping[path], path)
|
|
||||||
return None
|
|
||||||
|
|
||||||
# TODO: the real _get_file_contents returns a bytestring, so we actually convert the
|
|
||||||
# unicode/text it's created with to utf-8
|
|
||||||
def _get_file_contents(self, file_name):
|
|
||||||
path = to_text(file_name)
|
|
||||||
if path in self._file_mapping:
|
|
||||||
return (to_bytes(self._file_mapping[path]), False)
|
|
||||||
else:
|
|
||||||
raise AnsibleParserError("file not found: %s" % path)
|
|
||||||
|
|
||||||
def path_exists(self, path):
|
|
||||||
path = to_text(path)
|
|
||||||
return path in self._file_mapping or path in self._known_directories
|
|
||||||
|
|
||||||
def is_file(self, path):
|
|
||||||
path = to_text(path)
|
|
||||||
return path in self._file_mapping
|
|
||||||
|
|
||||||
def is_directory(self, path):
|
|
||||||
path = to_text(path)
|
|
||||||
return path in self._known_directories
|
|
||||||
|
|
||||||
def list_directory(self, path):
|
|
||||||
ret = []
|
|
||||||
path = to_text(path)
|
|
||||||
for x in (list(self._file_mapping.keys()) + self._known_directories):
|
|
||||||
if x.startswith(path):
|
|
||||||
if os.path.dirname(x) == path:
|
|
||||||
ret.append(os.path.basename(x))
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def is_executable(self, path):
|
|
||||||
# FIXME: figure out a way to make paths return true for this
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _add_known_directory(self, directory):
|
|
||||||
if directory not in self._known_directories:
|
|
||||||
self._known_directories.append(directory)
|
|
||||||
|
|
||||||
def _build_known_directories(self):
|
|
||||||
self._known_directories = []
|
|
||||||
for path in self._file_mapping:
|
|
||||||
dirname = os.path.dirname(path)
|
|
||||||
while dirname not in ('/', ''):
|
|
||||||
self._add_known_directory(dirname)
|
|
||||||
dirname = os.path.dirname(dirname)
|
|
||||||
|
|
||||||
def push(self, path, content):
|
|
||||||
rebuild_dirs = False
|
|
||||||
if path not in self._file_mapping:
|
|
||||||
rebuild_dirs = True
|
|
||||||
|
|
||||||
self._file_mapping[path] = content
|
|
||||||
|
|
||||||
if rebuild_dirs:
|
|
||||||
self._build_known_directories()
|
|
||||||
|
|
||||||
def pop(self, path):
|
|
||||||
if path in self._file_mapping:
|
|
||||||
del self._file_mapping[path]
|
|
||||||
self._build_known_directories()
|
|
||||||
|
|
||||||
def clear(self):
|
|
||||||
self._file_mapping = dict()
|
|
||||||
self._known_directories = []
|
|
||||||
|
|
||||||
def get_basedir(self):
|
|
||||||
return os.getcwd()
|
|
||||||
|
|
||||||
def set_vault_secrets(self, vault_secrets):
|
|
||||||
self._vault_secrets = vault_secrets
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
from __future__ import absolute_import, division, print_function
|
|
||||||
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
from ansible_collections.ansible.posix.tests.unit.compat.mock import MagicMock
|
|
||||||
from ansible.utils.path import unfrackpath
|
|
||||||
|
|
||||||
|
|
||||||
mock_unfrackpath_noop = MagicMock(spec_set=unfrackpath, side_effect=lambda x, *args, **kwargs: x)
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
# (c) 2016, Matt Davis <mdavis@ansible.com>
|
|
||||||
# (c) 2016, Toshio Kuratomi <tkuratomi@ansible.com>
|
|
||||||
#
|
|
||||||
# This file is part of Ansible
|
|
||||||
#
|
|
||||||
# Ansible is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Ansible is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
# Make coding more python3-ish
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import json
|
|
||||||
|
|
||||||
from contextlib import contextmanager
|
|
||||||
from io import BytesIO, StringIO
|
|
||||||
from ansible_collections.ansible.posix.tests.unit.compat import unittest
|
|
||||||
from ansible.module_utils.six import PY3
|
|
||||||
from ansible.module_utils._text import to_bytes
|
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
|
||||||
def swap_stdin_and_argv(stdin_data='', argv_data=tuple()):
|
|
||||||
"""
|
|
||||||
context manager that temporarily masks the test runner's values for stdin and argv
|
|
||||||
"""
|
|
||||||
real_stdin = sys.stdin
|
|
||||||
real_argv = sys.argv
|
|
||||||
|
|
||||||
if PY3:
|
|
||||||
fake_stream = StringIO(stdin_data)
|
|
||||||
fake_stream.buffer = BytesIO(to_bytes(stdin_data))
|
|
||||||
else:
|
|
||||||
fake_stream = BytesIO(to_bytes(stdin_data))
|
|
||||||
|
|
||||||
try:
|
|
||||||
sys.stdin = fake_stream
|
|
||||||
sys.argv = argv_data
|
|
||||||
|
|
||||||
yield
|
|
||||||
finally:
|
|
||||||
sys.stdin = real_stdin
|
|
||||||
sys.argv = real_argv
|
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
|
||||||
def swap_stdout():
|
|
||||||
"""
|
|
||||||
context manager that temporarily replaces stdout for tests that need to verify output
|
|
||||||
"""
|
|
||||||
old_stdout = sys.stdout
|
|
||||||
|
|
||||||
if PY3:
|
|
||||||
fake_stream = StringIO()
|
|
||||||
else:
|
|
||||||
fake_stream = BytesIO()
|
|
||||||
|
|
||||||
try:
|
|
||||||
sys.stdout = fake_stream
|
|
||||||
|
|
||||||
yield fake_stream
|
|
||||||
finally:
|
|
||||||
sys.stdout = old_stdout
|
|
||||||
|
|
||||||
|
|
||||||
class ModuleTestCase(unittest.TestCase):
|
|
||||||
def setUp(self, module_args=None):
|
|
||||||
if module_args is None:
|
|
||||||
module_args = {'_ansible_remote_tmp': '/tmp', '_ansible_keep_remote_files': False}
|
|
||||||
|
|
||||||
args = json.dumps(dict(ANSIBLE_MODULE_ARGS=module_args))
|
|
||||||
|
|
||||||
# unittest doesn't have a clean place to use a context manager, so we have to enter/exit manually
|
|
||||||
self.stdin_swap = swap_stdin_and_argv(stdin_data=args)
|
|
||||||
self.stdin_swap.__enter__()
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
# unittest doesn't have a clean place to use a context manager, so we have to enter/exit manually
|
|
||||||
self.stdin_swap.__exit__(None, None, None)
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
# Ansible is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Ansible is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
# Make coding more python3-ish
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
from ansible.module_utils._text import to_bytes
|
|
||||||
|
|
||||||
from ansible.parsing.vault import VaultSecret
|
|
||||||
|
|
||||||
|
|
||||||
class TextVaultSecret(VaultSecret):
|
|
||||||
'''A secret piece of text. ie, a password. Tracks text encoding.
|
|
||||||
|
|
||||||
The text encoding of the text may not be the default text encoding so
|
|
||||||
we keep track of the encoding so we encode it to the same bytes.'''
|
|
||||||
|
|
||||||
def __init__(self, text, encoding=None, errors=None, _bytes=None):
|
|
||||||
super(TextVaultSecret, self).__init__()
|
|
||||||
self.text = text
|
|
||||||
self.encoding = encoding or 'utf-8'
|
|
||||||
self._bytes = _bytes
|
|
||||||
self.errors = errors or 'strict'
|
|
||||||
|
|
||||||
@property
|
|
||||||
def bytes(self):
|
|
||||||
'''The text encoded with encoding, unless we specifically set _bytes.'''
|
|
||||||
return self._bytes or to_bytes(self.text, encoding=self.encoding, errors=self.errors)
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
from __future__ import absolute_import, division, print_function
|
|
||||||
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
import io
|
|
||||||
import yaml
|
|
||||||
|
|
||||||
from ansible.module_utils.six import PY3
|
|
||||||
from ansible.parsing.yaml.loader import AnsibleLoader
|
|
||||||
from ansible.parsing.yaml.dumper import AnsibleDumper
|
|
||||||
|
|
||||||
|
|
||||||
class YamlTestUtils(object):
|
|
||||||
"""Mixin class to combine with a unittest.TestCase subclass."""
|
|
||||||
def _loader(self, stream):
|
|
||||||
"""Vault related tests will want to override this.
|
|
||||||
|
|
||||||
Vault cases should setup a AnsibleLoader that has the vault password."""
|
|
||||||
return AnsibleLoader(stream)
|
|
||||||
|
|
||||||
def _dump_stream(self, obj, stream, dumper=None):
|
|
||||||
"""Dump to a py2-unicode or py3-string stream."""
|
|
||||||
if PY3:
|
|
||||||
return yaml.dump(obj, stream, Dumper=dumper)
|
|
||||||
else:
|
|
||||||
return yaml.dump(obj, stream, Dumper=dumper, encoding=None)
|
|
||||||
|
|
||||||
def _dump_string(self, obj, dumper=None):
|
|
||||||
"""Dump to a py2-unicode or py3-string"""
|
|
||||||
if PY3:
|
|
||||||
return yaml.dump(obj, Dumper=dumper)
|
|
||||||
else:
|
|
||||||
return yaml.dump(obj, Dumper=dumper, encoding=None)
|
|
||||||
|
|
||||||
def _dump_load_cycle(self, obj):
|
|
||||||
# Each pass though a dump or load revs the 'generation'
|
|
||||||
# obj to yaml string
|
|
||||||
string_from_object_dump = self._dump_string(obj, dumper=AnsibleDumper)
|
|
||||||
|
|
||||||
# wrap a stream/file like StringIO around that yaml
|
|
||||||
stream_from_object_dump = io.StringIO(string_from_object_dump)
|
|
||||||
loader = self._loader(stream_from_object_dump)
|
|
||||||
# load the yaml stream to create a new instance of the object (gen 2)
|
|
||||||
obj_2 = loader.get_data()
|
|
||||||
|
|
||||||
# dump the gen 2 objects directory to strings
|
|
||||||
string_from_object_dump_2 = self._dump_string(obj_2,
|
|
||||||
dumper=AnsibleDumper)
|
|
||||||
|
|
||||||
# The gen 1 and gen 2 yaml strings
|
|
||||||
self.assertEqual(string_from_object_dump, string_from_object_dump_2)
|
|
||||||
# the gen 1 (orig) and gen 2 py object
|
|
||||||
self.assertEqual(obj, obj_2)
|
|
||||||
|
|
||||||
# again! gen 3... load strings into py objects
|
|
||||||
stream_3 = io.StringIO(string_from_object_dump_2)
|
|
||||||
loader_3 = self._loader(stream_3)
|
|
||||||
obj_3 = loader_3.get_data()
|
|
||||||
|
|
||||||
string_from_object_dump_3 = self._dump_string(obj_3, dumper=AnsibleDumper)
|
|
||||||
|
|
||||||
self.assertEqual(obj, obj_3)
|
|
||||||
# should be transitive, but...
|
|
||||||
self.assertEqual(obj_2, obj_3)
|
|
||||||
self.assertEqual(string_from_object_dump, string_from_object_dump_3)
|
|
||||||
|
|
||||||
def _old_dump_load_cycle(self, obj):
|
|
||||||
'''Dump the passed in object to yaml, load it back up, dump again, compare.'''
|
|
||||||
stream = io.StringIO()
|
|
||||||
|
|
||||||
yaml_string = self._dump_string(obj, dumper=AnsibleDumper)
|
|
||||||
self._dump_stream(obj, stream, dumper=AnsibleDumper)
|
|
||||||
|
|
||||||
yaml_string_from_stream = stream.getvalue()
|
|
||||||
|
|
||||||
# reset stream
|
|
||||||
stream.seek(0)
|
|
||||||
|
|
||||||
loader = self._loader(stream)
|
|
||||||
# loader = AnsibleLoader(stream, vault_password=self.vault_password)
|
|
||||||
obj_from_stream = loader.get_data()
|
|
||||||
|
|
||||||
stream_from_string = io.StringIO(yaml_string)
|
|
||||||
loader2 = self._loader(stream_from_string)
|
|
||||||
# loader2 = AnsibleLoader(stream_from_string, vault_password=self.vault_password)
|
|
||||||
obj_from_string = loader2.get_data()
|
|
||||||
|
|
||||||
stream_obj_from_stream = io.StringIO()
|
|
||||||
stream_obj_from_string = io.StringIO()
|
|
||||||
|
|
||||||
if PY3:
|
|
||||||
yaml.dump(obj_from_stream, stream_obj_from_stream, Dumper=AnsibleDumper)
|
|
||||||
yaml.dump(obj_from_stream, stream_obj_from_string, Dumper=AnsibleDumper)
|
|
||||||
else:
|
|
||||||
yaml.dump(obj_from_stream, stream_obj_from_stream, Dumper=AnsibleDumper, encoding=None)
|
|
||||||
yaml.dump(obj_from_stream, stream_obj_from_string, Dumper=AnsibleDumper, encoding=None)
|
|
||||||
|
|
||||||
yaml_string_stream_obj_from_stream = stream_obj_from_stream.getvalue()
|
|
||||||
yaml_string_stream_obj_from_string = stream_obj_from_string.getvalue()
|
|
||||||
|
|
||||||
stream_obj_from_stream.seek(0)
|
|
||||||
stream_obj_from_string.seek(0)
|
|
||||||
|
|
||||||
if PY3:
|
|
||||||
yaml_string_obj_from_stream = yaml.dump(obj_from_stream, Dumper=AnsibleDumper)
|
|
||||||
yaml_string_obj_from_string = yaml.dump(obj_from_string, Dumper=AnsibleDumper)
|
|
||||||
else:
|
|
||||||
yaml_string_obj_from_stream = yaml.dump(obj_from_stream, Dumper=AnsibleDumper, encoding=None)
|
|
||||||
yaml_string_obj_from_string = yaml.dump(obj_from_string, Dumper=AnsibleDumper, encoding=None)
|
|
||||||
|
|
||||||
assert yaml_string == yaml_string_obj_from_stream
|
|
||||||
assert yaml_string == yaml_string_obj_from_stream == yaml_string_obj_from_string
|
|
||||||
assert (yaml_string == yaml_string_obj_from_stream == yaml_string_obj_from_string == yaml_string_stream_obj_from_stream ==
|
|
||||||
yaml_string_stream_obj_from_string)
|
|
||||||
assert obj == obj_from_stream
|
|
||||||
assert obj == obj_from_string
|
|
||||||
assert obj == yaml_string_obj_from_stream
|
|
||||||
assert obj == yaml_string_obj_from_string
|
|
||||||
assert obj == obj_from_stream == obj_from_string == yaml_string_obj_from_stream == yaml_string_obj_from_string
|
|
||||||
return {'obj': obj,
|
|
||||||
'yaml_string': yaml_string,
|
|
||||||
'yaml_string_from_stream': yaml_string_from_stream,
|
|
||||||
'obj_from_stream': obj_from_stream,
|
|
||||||
'obj_from_string': obj_from_string,
|
|
||||||
'yaml_string_obj_from_string': yaml_string_obj_from_string}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
# Copyright (c) 2017 Ansible Project
|
|
||||||
# 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
|
|
||||||
|
|
||||||
import json
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
from ansible.module_utils.six import string_types
|
|
||||||
from ansible.module_utils._text import to_bytes
|
|
||||||
from ansible.module_utils.common._collections_compat import MutableMapping
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def patch_ansible_module(request, mocker):
|
|
||||||
if isinstance(request.param, string_types):
|
|
||||||
args = request.param
|
|
||||||
elif isinstance(request.param, MutableMapping):
|
|
||||||
if 'ANSIBLE_MODULE_ARGS' not in request.param:
|
|
||||||
request.param = {'ANSIBLE_MODULE_ARGS': request.param}
|
|
||||||
if '_ansible_remote_tmp' not in request.param['ANSIBLE_MODULE_ARGS']:
|
|
||||||
request.param['ANSIBLE_MODULE_ARGS']['_ansible_remote_tmp'] = '/tmp'
|
|
||||||
if '_ansible_keep_remote_files' not in request.param['ANSIBLE_MODULE_ARGS']:
|
|
||||||
request.param['ANSIBLE_MODULE_ARGS']['_ansible_keep_remote_files'] = False
|
|
||||||
args = json.dumps(request.param)
|
|
||||||
else:
|
|
||||||
raise Exception('Malformed data to the patch_ansible_module pytest fixture')
|
|
||||||
|
|
||||||
mocker.patch('ansible.module_utils.basic._ANSIBLE_ARGS', to_bytes(args))
|
|
||||||
@@ -7,7 +7,7 @@ import tempfile
|
|||||||
|
|
||||||
from ansible_collections.ansible.posix.tests.unit.compat import unittest
|
from ansible_collections.ansible.posix.tests.unit.compat import unittest
|
||||||
from ansible_collections.ansible.posix.tests.unit.compat.mock import MagicMock
|
from ansible_collections.ansible.posix.tests.unit.compat.mock import MagicMock
|
||||||
from ansible.module_utils._text import to_bytes
|
from ansible.module_utils.common.text.converters import to_bytes
|
||||||
|
|
||||||
from ansible_collections.ansible.posix.plugins.modules.mount import (
|
from ansible_collections.ansible.posix.plugins.modules.mount import (
|
||||||
get_linux_mounts,
|
get_linux_mounts,
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
from __future__ import absolute_import, division, print_function
|
|
||||||
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
import json
|
|
||||||
|
|
||||||
from ansible_collections.ansible.posix.tests.unit.compat import unittest
|
|
||||||
from ansible_collections.ansible.posix.tests.unit.compat.mock import patch
|
|
||||||
from ansible.module_utils import basic
|
|
||||||
from ansible.module_utils._text import to_bytes
|
|
||||||
|
|
||||||
|
|
||||||
def set_module_args(args):
|
|
||||||
if '_ansible_remote_tmp' not in args:
|
|
||||||
args['_ansible_remote_tmp'] = '/tmp'
|
|
||||||
if '_ansible_keep_remote_files' not in args:
|
|
||||||
args['_ansible_keep_remote_files'] = False
|
|
||||||
|
|
||||||
args = json.dumps({'ANSIBLE_MODULE_ARGS': args})
|
|
||||||
basic._ANSIBLE_ARGS = to_bytes(args)
|
|
||||||
|
|
||||||
|
|
||||||
class AnsibleExitJson(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class AnsibleFailJson(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def exit_json(*args, **kwargs):
|
|
||||||
if 'changed' not in kwargs:
|
|
||||||
kwargs['changed'] = False
|
|
||||||
raise AnsibleExitJson(kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def fail_json(*args, **kwargs):
|
|
||||||
kwargs['failed'] = True
|
|
||||||
raise AnsibleFailJson(kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class ModuleTestCase(unittest.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.mock_module = patch.multiple(basic.AnsibleModule, exit_json=exit_json, fail_json=fail_json)
|
|
||||||
self.mock_module.start()
|
|
||||||
self.mock_sleep = patch('time.sleep')
|
|
||||||
self.mock_sleep.start()
|
|
||||||
set_module_args({})
|
|
||||||
self.addCleanup(self.mock_module.stop)
|
|
||||||
self.addCleanup(self.mock_sleep.stop)
|
|
||||||
@@ -9,6 +9,5 @@ command -v ansible
|
|||||||
pip install --upgrade --user pip
|
pip install --upgrade --user pip
|
||||||
pip install --upgrade --user ansible-lint
|
pip install --upgrade --user ansible-lint
|
||||||
|
|
||||||
PATH="${PATH/\~/${HOME}}" ansible-lint \
|
# To specify additional options, you can specify them into .ansible-lint file.
|
||||||
--exclude changelogs/ \
|
PATH="${PATH/\~/${HOME}}" ansible-lint
|
||||||
--profile=production
|
|
||||||
|
|||||||
@@ -62,15 +62,15 @@ else
|
|||||||
retry pip install "https://github.com/ansible/ansible/archive/stable-${ansible_version}.tar.gz" --disable-pip-version-check
|
retry pip install "https://github.com/ansible/ansible/archive/stable-${ansible_version}.tar.gz" --disable-pip-version-check
|
||||||
fi
|
fi
|
||||||
|
|
||||||
export ANSIBLE_COLLECTIONS_PATHS="${PWD}/../../../"
|
export ANSIBLE_COLLECTIONS_PATH="${PWD}/../../../"
|
||||||
|
|
||||||
# START: HACK install dependencies
|
# START: HACK install dependencies
|
||||||
if [ "${ansible_version}" == "2.9" ] || [ "${ansible_version}" == "2.10" ]; then
|
if [ "${ansible_version}" == "2.9" ] || [ "${ansible_version}" == "2.10" ]; then
|
||||||
# Note: Since community.general 5.x, Ansible Core versions prior to 2.11 are not supported.
|
# Note: Since community.general 5.x, Ansible Core versions prior to 2.11 are not supported.
|
||||||
# So we need to use 4.8.1 for Ansible 2.9 and Ansible Engine 2.10.
|
# So we need to use 4.8.1 for Ansible 2.9 and Ansible Engine 2.10.
|
||||||
retry git clone --depth=1 --single-branch -b 4.8.1 https://github.com/ansible-collections/community.general.git "${ANSIBLE_COLLECTIONS_PATHS}/ansible_collections/community/general"
|
retry git clone --depth=1 --single-branch -b 4.8.1 https://github.com/ansible-collections/community.general.git "${ANSIBLE_COLLECTIONS_PATH}/ansible_collections/community/general"
|
||||||
else
|
else
|
||||||
retry git clone --depth=1 --single-branch https://github.com/ansible-collections/community.general.git "${ANSIBLE_COLLECTIONS_PATHS}/ansible_collections/community/general"
|
retry git clone --depth=1 --single-branch https://github.com/ansible-collections/community.general.git "${ANSIBLE_COLLECTIONS_PATH}/ansible_collections/community/general"
|
||||||
fi
|
fi
|
||||||
# Note: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429)
|
# Note: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429)
|
||||||
# END: HACK
|
# END: HACK
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user