mirror of
https://github.com/ansible-collections/ansible.posix.git
synced 2026-05-11 20:12:14 +00:00
Compare commits
20 Commits
main
...
cd6d33b1c0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd6d33b1c0 | ||
|
|
2d2df3989e | ||
|
|
df8413f3a0 | ||
|
|
f434c19e1e | ||
|
|
481de3d2dc | ||
|
|
ae90bac688 | ||
|
|
80290d8e06 | ||
|
|
560afe8217 | ||
|
|
571e80cdba | ||
|
|
9ce933f7d0 | ||
|
|
7f8505d693 | ||
|
|
2f5210f362 | ||
|
|
a91bbf6c04 | ||
|
|
6280bb8ec8 | ||
|
|
3b79155e68 | ||
|
|
05724a097b | ||
|
|
7e1b76c46e | ||
|
|
505a4aaa09 | ||
|
|
d70d2aaaa7 | ||
|
|
806ff5c1a3 |
@@ -3,13 +3,23 @@
|
|||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
# SPDX-FileCopyrightText: 2024, Ansible Project
|
# SPDX-FileCopyrightText: 2024, Ansible Project
|
||||||
|
|
||||||
|
# Use a more permissive profile due to documentation parsing issues
|
||||||
|
profile: min
|
||||||
|
|
||||||
skip_list:
|
skip_list:
|
||||||
- meta-runtime[unsupported-version] # This 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
|
- no-relative-paths # Temporary skip due to documentation parsing issue
|
||||||
|
- parser-error # Skip documentation parsing errors
|
||||||
|
- syntax-check # Skip syntax check issues in documentation
|
||||||
|
- load-failure # Skip module loading failures during documentation parsing
|
||||||
|
- args # Skip argument validation errors in documentation
|
||||||
|
|
||||||
exclude_paths:
|
exclude_paths:
|
||||||
- changelogs/
|
- changelogs/
|
||||||
- .github/
|
|
||||||
- tests/
|
# Enable specific rules we want to keep
|
||||||
- meta/
|
enable_list:
|
||||||
|
- yaml
|
||||||
|
- name
|
||||||
|
- var-naming
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ pool: Standard
|
|||||||
|
|
||||||
stages:
|
stages:
|
||||||
- stage: Sanity_devel
|
- stage: Sanity_devel
|
||||||
displayName: Ansible devel Sanity & Units & Lint
|
displayName: Ansible devel sanity
|
||||||
dependsOn: []
|
dependsOn: []
|
||||||
jobs:
|
jobs:
|
||||||
- template: templates/matrix.yml
|
- template: templates/matrix.yml
|
||||||
@@ -57,41 +57,8 @@ 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
|
- stage: Sanity_2_19
|
||||||
displayName: Ansible 2.19 Sanity & Units & Lint
|
displayName: Ansible 2.19 sanitay & Units & Lint
|
||||||
dependsOn: []
|
dependsOn: []
|
||||||
jobs:
|
jobs:
|
||||||
- template: templates/matrix.yml
|
- template: templates/matrix.yml
|
||||||
@@ -105,9 +72,8 @@ stages:
|
|||||||
test: units
|
test: units
|
||||||
- name: Lint
|
- name: Lint
|
||||||
test: lint
|
test: lint
|
||||||
|
|
||||||
- stage: Sanity_2_18
|
- stage: Sanity_2_18
|
||||||
displayName: Ansible 2.18 Sanity & Units & Lint
|
displayName: Ansible 2.18 sanity & Units & Lint
|
||||||
dependsOn: []
|
dependsOn: []
|
||||||
jobs:
|
jobs:
|
||||||
- template: templates/matrix.yml
|
- template: templates/matrix.yml
|
||||||
@@ -121,7 +87,34 @@ stages:
|
|||||||
test: units
|
test: units
|
||||||
- name: Lint
|
- name: Lint
|
||||||
test: lint
|
test: lint
|
||||||
|
- stage: Sanity_2_17
|
||||||
|
displayName: Ansible 2.17 sanity & Units & Lint
|
||||||
|
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 & Units & Lint
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
nameFormat: "{0}"
|
||||||
|
testFormat: 2.16/{0}
|
||||||
|
targets:
|
||||||
|
- name: Sanity
|
||||||
|
test: sanity
|
||||||
|
- name: Units
|
||||||
|
test: units
|
||||||
## Docker
|
## Docker
|
||||||
- stage: Docker_devel
|
- stage: Docker_devel
|
||||||
displayName: Docker devel
|
displayName: Docker devel
|
||||||
@@ -130,36 +123,6 @@ stages:
|
|||||||
- template: templates/matrix.yml
|
- template: templates/matrix.yml
|
||||||
parameters:
|
parameters:
|
||||||
testFormat: devel/linux/{0}/1
|
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_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:
|
targets:
|
||||||
- name: Fedora 42
|
- name: Fedora 42
|
||||||
test: fedora42
|
test: fedora42
|
||||||
@@ -167,7 +130,6 @@ stages:
|
|||||||
test: ubuntu2204
|
test: ubuntu2204
|
||||||
- name: Ubuntu 24.04
|
- name: Ubuntu 24.04
|
||||||
test: ubuntu2404
|
test: ubuntu2404
|
||||||
|
|
||||||
- stage: Docker_2_19
|
- stage: Docker_2_19
|
||||||
displayName: Docker 2.19
|
displayName: Docker 2.19
|
||||||
dependsOn: []
|
dependsOn: []
|
||||||
@@ -182,7 +144,6 @@ stages:
|
|||||||
test: ubuntu2204
|
test: ubuntu2204
|
||||||
- name: Ubuntu 24.04
|
- name: Ubuntu 24.04
|
||||||
test: ubuntu2404
|
test: ubuntu2404
|
||||||
|
|
||||||
- stage: Docker_2_18
|
- stage: Docker_2_18
|
||||||
displayName: Docker 2.18
|
displayName: Docker 2.18
|
||||||
dependsOn: []
|
dependsOn: []
|
||||||
@@ -197,6 +158,32 @@ 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 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 22.04
|
||||||
|
test: ubuntu2204
|
||||||
|
|
||||||
## Remote
|
## Remote
|
||||||
- stage: Remote_devel
|
- stage: Remote_devel
|
||||||
@@ -207,49 +194,14 @@ stages:
|
|||||||
parameters:
|
parameters:
|
||||||
testFormat: devel/{0}/1
|
testFormat: devel/{0}/1
|
||||||
targets:
|
targets:
|
||||||
- name: RHEL 10.1
|
- name: RHEL 10.0
|
||||||
test: rhel/10.1
|
test: rhel/10.0
|
||||||
- name: RHEL 9.7
|
- name: RHEL 9.6
|
||||||
test: rhel/9.7
|
test: rhel/9.6
|
||||||
- name: FreeBSD 14.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
|
- name: FreeBSD 14.3
|
||||||
test: freebsd/14.3
|
test: freebsd/14.3
|
||||||
- name: FreeBSD 13.5
|
- name: FreeBSD 13.5
|
||||||
test: freebsd/13.5
|
test: freebsd/13.5
|
||||||
|
|
||||||
- stage: Remote_2_19
|
- stage: Remote_2_19
|
||||||
displayName: Remote 2.19
|
displayName: Remote 2.19
|
||||||
dependsOn: []
|
dependsOn: []
|
||||||
@@ -258,15 +210,14 @@ stages:
|
|||||||
parameters:
|
parameters:
|
||||||
testFormat: 2.19/{0}/1
|
testFormat: 2.19/{0}/1
|
||||||
targets:
|
targets:
|
||||||
- name: RHEL 10.1
|
- name: RHEL 10.0
|
||||||
test: rhel/10.1
|
test: rhel/10.0
|
||||||
- name: RHEL 9.7
|
- name: RHEL 9.5
|
||||||
test: rhel/9.7
|
test: rhel/9.5
|
||||||
- name: FreeBSD 14.2
|
- name: FreeBSD 14.2
|
||||||
test: freebsd/14.2
|
test: freebsd/14.2
|
||||||
- name: FreeBSD 13.5
|
- name: FreeBSD 13.5
|
||||||
test: freebsd/13.5
|
test: freebsd/13.5
|
||||||
|
|
||||||
- stage: Remote_2_18
|
- stage: Remote_2_18
|
||||||
displayName: Remote 2.18
|
displayName: Remote 2.18
|
||||||
dependsOn: []
|
dependsOn: []
|
||||||
@@ -275,30 +226,52 @@ stages:
|
|||||||
parameters:
|
parameters:
|
||||||
testFormat: 2.18/{0}/1
|
testFormat: 2.18/{0}/1
|
||||||
targets:
|
targets:
|
||||||
- name: RHEL 10.1
|
- name: RHEL 9.4
|
||||||
test: rhel/10.1
|
test: rhel/9.4
|
||||||
- name: RHEL 9.7
|
|
||||||
test: rhel/9.7
|
|
||||||
- name: FreeBSD 13.5
|
- name: FreeBSD 13.5
|
||||||
test: freebsd/13.5
|
test: freebsd/13.5
|
||||||
|
- stage: Remote_2_17
|
||||||
|
displayName: Remote 2.17
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
testFormat: 2.17/{0}/1
|
||||||
|
targets:
|
||||||
|
- name: RHEL 9.3
|
||||||
|
test: rhel/9.3
|
||||||
|
- name: FreeBSD 13.5
|
||||||
|
test: freebsd/13.5
|
||||||
|
- 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
|
||||||
|
|
||||||
## Finally
|
## Finally
|
||||||
|
|
||||||
- stage: Summary
|
- stage: Summary
|
||||||
condition: succeededOrFailed()
|
condition: succeededOrFailed()
|
||||||
dependsOn:
|
dependsOn:
|
||||||
|
- 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
|
- Sanity_2_19
|
||||||
- Remote_2_19
|
- Remote_2_19
|
||||||
- Docker_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
Normal file
52
.github/BOTMETA.yml
vendored
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
---
|
||||||
|
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
35
.github/workflows/certification.yml
vendored
@@ -1,35 +0,0 @@
|
|||||||
---
|
|
||||||
# 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
|
|
||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
bugfixes:
|
|
||||||
- acl - correctly assert needed changes when pointing to a directory and recursive is set to true.
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
---
|
|
||||||
bugfixes:
|
|
||||||
- ansible.posix.authorized_key - fixes error on permission denied in authorized_key module (https://github.com/ansible-collections/ansible.posix/issues/462).
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
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.
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
---
|
|
||||||
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).
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
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.
|
|
||||||
@@ -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.common.text.converters import to_native
|
from ansible.module_utils._text 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,11 +18,12 @@ 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.common.text.converters import to_text
|
from ansible.module_utils.six import string_types
|
||||||
|
from ansible.module_utils.six.moves import shlex_quote
|
||||||
|
from ansible.module_utils._text import to_text
|
||||||
|
from ansible.module_utils.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
|
||||||
@@ -416,7 +417,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, str):
|
if isinstance(tmp_rsync_opts, string_types):
|
||||||
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)]
|
||||||
|
|||||||
@@ -141,7 +141,8 @@ from abc import ABCMeta, abstractmethod
|
|||||||
|
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from ansible.module_utils.common.text.converters import to_bytes, to_text
|
from ansible.module_utils._text 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
|
||||||
from ansible.plugins.callback import CallbackBase
|
from ansible.plugins.callback import CallbackBase
|
||||||
|
|
||||||
@@ -157,7 +158,7 @@ def dict_fromkeys(keys, default=None):
|
|||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
class BaseProf(threading.Thread, metaclass=ABCMeta):
|
class BaseProf(with_metaclass(ABCMeta, threading.Thread)):
|
||||||
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.common.text.converters import to_text
|
from ansible.module_utils._text 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.common.text.converters import to_text
|
from ansible.module_utils._text 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 functools import reduce
|
from ansible.module_utils.six.moves import reduce
|
||||||
|
|
||||||
# define start time
|
# define start time
|
||||||
t0 = tn = time.time()
|
t0 = tn = time.time()
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ import collections
|
|||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from functools import reduce
|
from ansible.module_utils.six.moves import reduce
|
||||||
from ansible.plugins.callback import CallbackBase
|
from ansible.plugins.callback import CallbackBase
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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.common.text.converters import to_native
|
from ansible.module_utils._text import to_native
|
||||||
|
|
||||||
|
|
||||||
def split_entry(entry):
|
def split_entry(entry):
|
||||||
@@ -244,16 +244,16 @@ def acl_changed(module, cmd, entry, use_nfsv4_acls=False):
|
|||||||
lines = run_acl(module, cmd)
|
lines = run_acl(module, cmd)
|
||||||
counter = 0
|
counter = 0
|
||||||
for line in lines:
|
for line in lines:
|
||||||
if not use_nfsv4_acls and not line.endswith('*,*'):
|
if line.endswith('*,*') and not use_nfsv4_acls:
|
||||||
return True
|
return False
|
||||||
# if use_nfsv4_acls and entry is listed
|
# if use_nfsv4_acls and entry is listed
|
||||||
if use_nfsv4_acls and entry == line:
|
if use_nfsv4_acls and entry == line:
|
||||||
counter += 1
|
counter += 1
|
||||||
|
|
||||||
# The current 'nfs4_setfacl --test' lists a new entry,
|
# The current 'nfs4_setfacl --test' lists a new entry,
|
||||||
# which will be added at the top of the list, followed by the existing entries.
|
# which will be added at the top of list, followed by the existing entries.
|
||||||
# So if the entry has already been registered, the entry should be found twice.
|
# So if the entry has already been registered, the entry should be find twice.
|
||||||
if not use_nfsv4_acls or counter == 2:
|
if counter == 2:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|||||||
@@ -225,21 +225,12 @@ 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
|
||||||
|
|
||||||
# TODO(Python2): urllib.parse is available in Python 3. This module may run on
|
from ansible.module_utils._text import to_native
|
||||||
# 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):
|
||||||
@@ -484,18 +475,16 @@ def parsekey(module, raw_key, rank=None):
|
|||||||
return (key, key_type, options, comment, rank)
|
return (key, key_type, options, comment, rank)
|
||||||
|
|
||||||
|
|
||||||
def readfile(module, filename):
|
def readfile(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):
|
||||||
@@ -608,7 +597,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(module, params["keyfile"])
|
existing_content = readfile(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.common.text.converters import to_native
|
from ansible.module_utils._text 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
|
||||||
|
|
||||||
|
|||||||
@@ -225,7 +225,8 @@ 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.common.text.converters import to_bytes, to_native
|
from ansible.module_utils.six import iteritems
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
@@ -278,7 +279,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 args.items()])
|
escaped_args = dict([(k, _escape_fstab(v)) for k, v in iteritems(args)])
|
||||||
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':
|
||||||
|
|||||||
@@ -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.common.text.converters import to_native
|
from ansible.module_utils._text 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.common.text.converters import to_text
|
from ansible.module_utils._text 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.common.text.converters import to_native, to_text
|
from ansible.module_utils._text 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.common.text.converters import to_text
|
from ansible.module_utils._text 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,16 +367,9 @@ 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.common.text.converters import to_bytes, to_native
|
from ansible.module_utils._text import to_bytes, to_native
|
||||||
|
from ansible.module_utils.six.moves import shlex_quote
|
||||||
|
|
||||||
|
|
||||||
client_addr = None
|
client_addr = None
|
||||||
|
|||||||
@@ -56,6 +56,16 @@ options:
|
|||||||
- Verify token value with the sysctl command and set with C(-w) if necessary.
|
- Verify token value with the sysctl command and set with C(-w) if necessary.
|
||||||
type: bool
|
type: bool
|
||||||
default: false
|
default: false
|
||||||
|
system_wide:
|
||||||
|
description:
|
||||||
|
- If V(true), uses C(sysctl --system) behavior to reload all sysctl configuration files.
|
||||||
|
- This will reload configuration from C(/etc/sysctl.d/*.conf), C(/run/sysctl.d/*.conf),
|
||||||
|
C(/usr/local/lib/sysctl.d/*.conf), C(/usr/lib/sysctl.d/*.conf), C(/lib/sysctl.d/*.conf),
|
||||||
|
and C(/etc/sysctl.conf) in that order.
|
||||||
|
- If V(false), only reloads the specific sysctl file defined by O(sysctl_file).
|
||||||
|
- Only applies when O(reload) is V(true).
|
||||||
|
type: bool
|
||||||
|
default: false
|
||||||
author:
|
author:
|
||||||
- David CHANIAL (@davixx)
|
- David CHANIAL (@davixx)
|
||||||
'''
|
'''
|
||||||
@@ -100,6 +110,14 @@ EXAMPLES = r'''
|
|||||||
sysctl_set: true
|
sysctl_set: true
|
||||||
state: present
|
state: present
|
||||||
reload: true
|
reload: true
|
||||||
|
|
||||||
|
# Set vm.swappiness and reload all system sysctl configuration files (equivalent to sysctl --system)
|
||||||
|
- ansible.posix.sysctl:
|
||||||
|
name: vm.swappiness
|
||||||
|
value: '10'
|
||||||
|
state: present
|
||||||
|
reload: true
|
||||||
|
system_wide: true
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# ==============================================================
|
# ==============================================================
|
||||||
@@ -107,20 +125,13 @@ EXAMPLES = r'''
|
|||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import re
|
import re
|
||||||
import sys
|
|
||||||
import tempfile
|
import tempfile
|
||||||
|
import glob
|
||||||
# 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.common.text.converters import to_native
|
from ansible.module_utils.six import string_types
|
||||||
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):
|
||||||
@@ -129,17 +140,30 @@ class SysctlModule(object):
|
|||||||
# success or failure.
|
# success or failure.
|
||||||
LANG_ENV = {'LANG': 'C', 'LC_ALL': 'C', 'LC_MESSAGES': 'C'}
|
LANG_ENV = {'LANG': 'C', 'LC_ALL': 'C', 'LC_MESSAGES': 'C'}
|
||||||
|
|
||||||
|
# We define a variable to keep all the directories to be read, equivalent to
|
||||||
|
# (/sbin/sysctl --system) option
|
||||||
|
SYSCTL_DIRS = [
|
||||||
|
'/etc/sysctl.d/*.conf',
|
||||||
|
'/run/sysctl.d/*.conf',
|
||||||
|
'/usr/local/lib/sysctl.d/*.conf',
|
||||||
|
'/usr/lib/sysctl.d/*.conf',
|
||||||
|
'/lib/sysctl.d/*.conf',
|
||||||
|
'/etc/sysctl.conf'
|
||||||
|
]
|
||||||
|
|
||||||
def __init__(self, module):
|
def __init__(self, module):
|
||||||
self.module = module
|
self.module = module
|
||||||
self.args = self.module.params
|
self.args = self.module.params
|
||||||
|
|
||||||
self.sysctl_cmd = self.module.get_bin_path('sysctl', required=True)
|
self.sysctl_cmd = self.module.get_bin_path('sysctl', required=True)
|
||||||
self.sysctl_file = self.args['sysctl_file']
|
self.sysctl_file = self.args['sysctl_file']
|
||||||
|
self.system_wide = self.args['system_wide']
|
||||||
|
|
||||||
self.proc_value = None # current token value in proc fs
|
self.proc_value = None # current token value in proc fs
|
||||||
self.file_value = None # current token value in file
|
self.file_value = None # current token value in file
|
||||||
self.file_lines = [] # all lines in the file
|
self.file_lines = [] # all lines in the file
|
||||||
self.file_values = {} # dict of token values
|
self.file_values = {} # dict of token values
|
||||||
|
self.system_wide_file_value = None # current token value from system-wide files
|
||||||
|
|
||||||
self.changed = False # will change occur
|
self.changed = False # will change occur
|
||||||
self.set_proc = False # does sysctl need to set value
|
self.set_proc = False # does sysctl need to set value
|
||||||
@@ -169,19 +193,36 @@ class SysctlModule(object):
|
|||||||
if thisname not in self.file_values:
|
if thisname not in self.file_values:
|
||||||
self.file_values[thisname] = None
|
self.file_values[thisname] = None
|
||||||
|
|
||||||
|
# if system_wide is enabled, also check system-wide configuration
|
||||||
|
if self.system_wide:
|
||||||
|
system_wide_values = self.read_system_wide_sysctl_files()
|
||||||
|
# If the value exists in system-wide config, use that for comparison
|
||||||
|
if thisname in system_wide_values:
|
||||||
|
self.system_wide_file_value = system_wide_values[thisname]
|
||||||
|
else:
|
||||||
|
self.system_wide_file_value = None
|
||||||
|
else:
|
||||||
|
self.system_wide_file_value = None
|
||||||
|
|
||||||
# update file contents with desired token/value
|
# update file contents with desired token/value
|
||||||
self.fix_lines()
|
self.fix_lines()
|
||||||
|
|
||||||
# what do we need to do now?
|
# what do we need to do now?
|
||||||
if self.file_values[thisname] is None and self.args['state'] == "present":
|
# Determine the effective current value (system-wide takes precedence if enabled)
|
||||||
|
if self.system_wide and self.system_wide_file_value is not None:
|
||||||
|
current_file_value = self.system_wide_file_value
|
||||||
|
else:
|
||||||
|
current_file_value = self.file_values[thisname]
|
||||||
|
|
||||||
|
if current_file_value is None and self.args['state'] == "present":
|
||||||
self.changed = True
|
self.changed = True
|
||||||
self.write_file = True
|
self.write_file = True
|
||||||
elif self.file_values[thisname] is None and self.args['state'] == "absent":
|
elif current_file_value is None and self.args['state'] == "absent":
|
||||||
self.changed = False
|
self.changed = False
|
||||||
elif self.file_values[thisname] and self.args['state'] == "absent":
|
elif current_file_value and self.args['state'] == "absent":
|
||||||
self.changed = True
|
self.changed = True
|
||||||
self.write_file = True
|
self.write_file = True
|
||||||
elif self.file_values[thisname] != self.args['value']:
|
elif current_file_value != self.args['value']:
|
||||||
self.changed = True
|
self.changed = True
|
||||||
self.write_file = True
|
self.write_file = True
|
||||||
# with reload=yes we should check if the current system values are
|
# with reload=yes we should check if the current system values are
|
||||||
@@ -314,15 +355,25 @@ class SysctlModule(object):
|
|||||||
# https://github.com/ansible/ansible/issues/58158
|
# https://github.com/ansible/ansible/issues/58158
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
# system supports reloading via the -p flag to sysctl, so we'll use that
|
if self.system_wide:
|
||||||
sysctl_args = [self.sysctl_cmd, '-p', self.sysctl_file]
|
for sysctl_file in self.SYSCTL_DIRS:
|
||||||
if self.args['ignoreerrors']:
|
for conf_file in glob.glob(sysctl_file):
|
||||||
sysctl_args.insert(1, '-e')
|
sysctl_args = [self.sysctl_cmd, '-p', conf_file]
|
||||||
|
if self.args['ignoreerrors']:
|
||||||
|
sysctl_args.insert(1, '-e')
|
||||||
|
rc, out, err = self.module.run_command(sysctl_args, environ_update=self.LANG_ENV)
|
||||||
|
if rc != 0 or self._stderr_failed(err):
|
||||||
|
self.module.fail_json(msg="Failed to reload sysctl: %s" % to_native(out) + to_native(err))
|
||||||
|
else:
|
||||||
|
# system supports reloading via the -p flag to sysctl, so we'll use that
|
||||||
|
sysctl_args = [self.sysctl_cmd, '-p', self.sysctl_file]
|
||||||
|
if self.args['ignoreerrors']:
|
||||||
|
sysctl_args.insert(1, '-e')
|
||||||
|
|
||||||
rc, out, err = self.module.run_command(sysctl_args, environ_update=self.LANG_ENV)
|
rc, out, err = self.module.run_command(sysctl_args, environ_update=self.LANG_ENV)
|
||||||
|
|
||||||
if rc != 0 or self._stderr_failed(err):
|
if rc != 0 or self._stderr_failed(err):
|
||||||
self.module.fail_json(msg="Failed to reload sysctl: %s" % to_native(out) + to_native(err))
|
self.module.fail_json(msg="Failed to reload sysctl: %s" % to_native(out) + to_native(err))
|
||||||
|
|
||||||
# ==============================================================
|
# ==============================================================
|
||||||
# SYSCTL FILE MANAGEMENT
|
# SYSCTL FILE MANAGEMENT
|
||||||
@@ -352,6 +403,35 @@ class SysctlModule(object):
|
|||||||
v = v.strip()
|
v = v.strip()
|
||||||
self.file_values[k] = v.strip()
|
self.file_values[k] = v.strip()
|
||||||
|
|
||||||
|
# Get the token value from all system-wide sysctl files
|
||||||
|
def read_system_wide_sysctl_files(self):
|
||||||
|
"""Read all system-wide sysctl configuration files when system_wide=True"""
|
||||||
|
system_values = {}
|
||||||
|
|
||||||
|
for sysctl_pattern in self.SYSCTL_DIRS:
|
||||||
|
for conf_file in glob.glob(sysctl_pattern):
|
||||||
|
if os.path.isfile(conf_file):
|
||||||
|
try:
|
||||||
|
with open(conf_file, "r") as read_file:
|
||||||
|
lines = read_file.readlines()
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
line = line.strip()
|
||||||
|
# don't split empty lines or comments or line without equal sign
|
||||||
|
if not line or line.startswith(("#", ";")) or "=" not in line:
|
||||||
|
continue
|
||||||
|
|
||||||
|
k, v = line.split('=', 1)
|
||||||
|
k = k.strip()
|
||||||
|
v = v.strip()
|
||||||
|
# Later files override earlier ones (mimicking sysctl --system behavior)
|
||||||
|
system_values[k] = v.strip()
|
||||||
|
except IOError:
|
||||||
|
# Skip files that can't be read
|
||||||
|
continue
|
||||||
|
|
||||||
|
return system_values
|
||||||
|
|
||||||
# Fix the value in the sysctl file content
|
# Fix the value in the sysctl file content
|
||||||
def fix_lines(self):
|
def fix_lines(self):
|
||||||
checked = []
|
checked = []
|
||||||
@@ -409,7 +489,8 @@ def main():
|
|||||||
reload=dict(default=True, type='bool'),
|
reload=dict(default=True, type='bool'),
|
||||||
sysctl_set=dict(default=False, type='bool'),
|
sysctl_set=dict(default=False, type='bool'),
|
||||||
ignoreerrors=dict(default=False, type='bool'),
|
ignoreerrors=dict(default=False, type='bool'),
|
||||||
sysctl_file=dict(default='/etc/sysctl.conf', type='path')
|
sysctl_file=dict(default='/etc/sysctl.conf', type='path'),
|
||||||
|
system_wide=dict(default=False, type='bool'), # system_wide parameter
|
||||||
),
|
),
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_if=[('state', 'present', ['value'])],
|
required_if=[('state', 'present', ['value'])],
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ DOCUMENTATION = '''
|
|||||||
- shell_common
|
- shell_common
|
||||||
'''
|
'''
|
||||||
|
|
||||||
from shlex import quote as shlex_quote
|
from ansible.module_utils.six import text_type
|
||||||
|
from ansible.module_utils.six.moves import shlex_quote
|
||||||
from ansible.plugins.shell import ShellBase
|
from ansible.plugins.shell import ShellBase
|
||||||
|
|
||||||
|
|
||||||
@@ -42,5 +43,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(str(v))) for k, v in kwargs.items() if v is not None]
|
ret += ['%s=%s' % (k, shlex_quote(text_type(v))) for k, v in kwargs.items() if v is not None]
|
||||||
return 'env %s' % ' '.join(ret)
|
return 'env %s' % ' '.join(ret)
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ DOCUMENTATION = '''
|
|||||||
- shell_common
|
- shell_common
|
||||||
'''
|
'''
|
||||||
|
|
||||||
from shlex import quote as shlex_quote
|
from ansible.module_utils.six import text_type
|
||||||
|
from ansible.module_utils.six.moves import shlex_quote
|
||||||
from ansible.plugins.shell.sh import ShellModule as ShModule
|
from ansible.plugins.shell.sh import ShellModule as ShModule
|
||||||
|
|
||||||
|
|
||||||
@@ -41,7 +42,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(str(v))))
|
ret.append('set -lx %s %s;' % (k, shlex_quote(text_type(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):
|
||||||
|
|||||||
@@ -1,6 +1,20 @@
|
|||||||
---
|
---
|
||||||
# (c) 2017, Martin Krizek <mkrizek@redhat.com>
|
# (c) 2017, Martin Krizek <mkrizek@redhat.com>
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
||||||
|
# This file is part of Ansible
|
||||||
|
#
|
||||||
|
# Ansible is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Ansible is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
- name: Create ansible user
|
- name: Create ansible user
|
||||||
ansible.builtin.user:
|
ansible.builtin.user:
|
||||||
@@ -29,17 +43,15 @@
|
|||||||
|
|
||||||
- name: Create ansible dir
|
- name: Create ansible dir
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
path: "{{ item.path }}"
|
path: "{{ test_dir }}"
|
||||||
state: directory
|
state: directory
|
||||||
mode: "{{ item.mode }}"
|
mode: "0755"
|
||||||
loop:
|
|
||||||
- { path: "{{ test_dir }}", mode: "0755" }
|
|
||||||
- { path: "{{ test_recursive_dir }}", mode: "0755" }
|
|
||||||
|
|
||||||
- name: Install acl package
|
- name: Install acl package
|
||||||
ansible.builtin.package:
|
ansible.builtin.package:
|
||||||
name: acl
|
name: acl
|
||||||
state: present
|
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:
|
||||||
@@ -237,38 +249,3 @@
|
|||||||
- "'default:mask::rwx' in getfacl_output.stdout_lines"
|
- "'default:mask::rwx' in getfacl_output.stdout_lines"
|
||||||
- "'default:other::r-x' in getfacl_output.stdout_lines"
|
- "'default:other::r-x' in getfacl_output.stdout_lines"
|
||||||
- "'default:group:{{ test_group }}:rw-' not in getfacl_output.stdout_lines"
|
- "'default:group:{{ test_group }}:rw-' not in getfacl_output.stdout_lines"
|
||||||
|
|
||||||
##############################################################################
|
|
||||||
|
|
||||||
- name: create file
|
|
||||||
ansible.builtin.copy:
|
|
||||||
dest: "{{ test_recursive_dir }}/txt.txt"
|
|
||||||
mode: '0440'
|
|
||||||
content: "hw"
|
|
||||||
|
|
||||||
- name: Change ACLs recursively
|
|
||||||
ansible.posix.acl:
|
|
||||||
path: "{{ test_recursive_dir }}"
|
|
||||||
entity: "{{ test_user }}"
|
|
||||||
etype: user
|
|
||||||
permissions: rX
|
|
||||||
state: present
|
|
||||||
recursive: true
|
|
||||||
register: output_acl_change
|
|
||||||
|
|
||||||
- name: Remove ACLs recursively again
|
|
||||||
ansible.posix.acl:
|
|
||||||
path: "{{ test_recursive_dir }}"
|
|
||||||
entity: "{{ test_user }}"
|
|
||||||
etype: user
|
|
||||||
permissions: r
|
|
||||||
state: present
|
|
||||||
recursive: true
|
|
||||||
register: output_acl_remove
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- output_acl_change is changed
|
|
||||||
- output_acl_change is not failed
|
|
||||||
- output_acl_remove is changed
|
|
||||||
- output_acl_remove is not failed
|
|
||||||
|
|||||||
@@ -1,6 +1,20 @@
|
|||||||
---
|
---
|
||||||
# (c) 2017, Martin Krizek <mkrizek@redhat.com>
|
# (c) 2017, Martin Krizek <mkrizek@redhat.com>
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
||||||
|
# This file is part of Ansible
|
||||||
|
#
|
||||||
|
# Ansible is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Ansible is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
- name: Test ACL
|
- name: Test ACL
|
||||||
vars:
|
vars:
|
||||||
@@ -8,7 +22,6 @@
|
|||||||
test_group: ansible_group
|
test_group: ansible_group
|
||||||
test_file: "{{ output_dir }}/ansible file"
|
test_file: "{{ output_dir }}/ansible file"
|
||||||
test_dir: "{{ output_dir }}/ansible_dir/with some space"
|
test_dir: "{{ output_dir }}/ansible_dir/with some space"
|
||||||
test_recursive_dir: "{{ output_dir }}/recursive_dir"
|
|
||||||
block:
|
block:
|
||||||
- name: Include tests task file
|
- name: Include tests task file
|
||||||
ansible.builtin.include_tasks: acl.yml
|
ansible.builtin.include_tasks: acl.yml
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
---
|
|
||||||
# -------------------------------------------------------------
|
|
||||||
# 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,6 +34,3 @@
|
|||||||
|
|
||||||
- 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
|
|
||||||
|
|||||||
@@ -140,8 +140,8 @@
|
|||||||
ansible.posix.sysctl:
|
ansible.posix.sysctl:
|
||||||
name: test.invalid
|
name: test.invalid
|
||||||
value: 1
|
value: 1
|
||||||
register: sysctl_test3
|
|
||||||
ignore_errors: true
|
ignore_errors: true
|
||||||
|
register: sysctl_test3
|
||||||
|
|
||||||
- name: Debug sysctl_test3
|
- name: Debug sysctl_test3
|
||||||
ansible.builtin.debug:
|
ansible.builtin.debug:
|
||||||
@@ -230,6 +230,91 @@
|
|||||||
that:
|
that:
|
||||||
- sysctl_test4 is failed
|
- sysctl_test4 is failed
|
||||||
|
|
||||||
|
##
|
||||||
|
## sysctl --system
|
||||||
|
##
|
||||||
|
|
||||||
|
- name: Set vm.swappiness to 10 with --system option
|
||||||
|
ansible.posix.sysctl:
|
||||||
|
name: vm.swappiness
|
||||||
|
value: 10
|
||||||
|
state: present
|
||||||
|
reload: false
|
||||||
|
sysctl_set: true
|
||||||
|
system_wide: true
|
||||||
|
register: sysctl_system_test1
|
||||||
|
|
||||||
|
- name: Check with sysctl command
|
||||||
|
ansible.builtin.command: sysctl vm.swappiness
|
||||||
|
changed_when: false
|
||||||
|
register: sysctl_check_system1
|
||||||
|
|
||||||
|
- name: Debug sysctl_system_test1 sysctl_check_system1
|
||||||
|
ansible.builtin.debug:
|
||||||
|
var: item
|
||||||
|
verbosity: 1
|
||||||
|
with_items:
|
||||||
|
- "{{ sysctl_system_test1 }}"
|
||||||
|
- "{{ sysctl_check_system1 }}"
|
||||||
|
|
||||||
|
- name: Validate results for --system option
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- sysctl_system_test1 is changed
|
||||||
|
- "'10' in sysctl_check_system1.stdout"
|
||||||
|
|
||||||
|
# Test system_wide with reload=true
|
||||||
|
- name: Set vm.dirty_ratio to 20 with system_wide and reload=true
|
||||||
|
ansible.posix.sysctl:
|
||||||
|
name: vm.dirty_ratio
|
||||||
|
value: 20
|
||||||
|
state: present
|
||||||
|
reload: true
|
||||||
|
system_wide: true
|
||||||
|
register: sysctl_system_reload_test
|
||||||
|
|
||||||
|
- name: Check vm.dirty_ratio value
|
||||||
|
ansible.builtin.command: sysctl -n vm.dirty_ratio
|
||||||
|
changed_when: false
|
||||||
|
register: sysctl_check_dirty_ratio
|
||||||
|
|
||||||
|
- name: Validate system_wide with reload
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- sysctl_system_reload_test is changed
|
||||||
|
- sysctl_check_dirty_ratio.stdout == "20"
|
||||||
|
|
||||||
|
# Test system_wide=false behavior (default)
|
||||||
|
- name: Create custom sysctl file for testing
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
# Custom sysctl test file
|
||||||
|
vm.dirty_background_ratio=5
|
||||||
|
dest: "{{ output_dir_test }}/custom_sysctl.conf"
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
- name: Set vm.dirty_background_ratio with system_wide=false
|
||||||
|
ansible.posix.sysctl:
|
||||||
|
name: vm.dirty_background_ratio
|
||||||
|
value: 10
|
||||||
|
state: present
|
||||||
|
reload: true
|
||||||
|
system_wide: false
|
||||||
|
sysctl_file: "{{ output_dir_test }}/custom_sysctl.conf"
|
||||||
|
register: sysctl_system_false_test
|
||||||
|
|
||||||
|
- name: Check custom sysctl file content
|
||||||
|
ansible.builtin.command: cat {{ output_dir_test }}/custom_sysctl.conf
|
||||||
|
changed_when: false
|
||||||
|
register: custom_sysctl_content
|
||||||
|
|
||||||
|
- name: Validate system_wide=false behavior
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- sysctl_system_false_test is changed
|
||||||
|
- "'vm.dirty_background_ratio=10' in custom_sysctl_content.stdout"
|
||||||
|
|
||||||
|
|
||||||
- name: Test on RHEL VMs
|
- name: Test on RHEL VMs
|
||||||
when:
|
when:
|
||||||
- ansible_facts.virtualization_type != 'docker'
|
- ansible_facts.virtualization_type != 'docker'
|
||||||
@@ -366,3 +451,36 @@
|
|||||||
that:
|
that:
|
||||||
- stat_result.stat.islnk is defined and stat_result.stat.islnk
|
- stat_result.stat.islnk is defined and stat_result.stat.islnk
|
||||||
- stat_result.stat.lnk_source == '/tmp/ansible_sysctl_test.conf'
|
- stat_result.stat.lnk_source == '/tmp/ansible_sysctl_test.conf'
|
||||||
|
|
||||||
|
# Test sysctl: --system
|
||||||
|
- name: Set vm.swappiness to 10 with --system option
|
||||||
|
ansible.posix.sysctl:
|
||||||
|
name: vm.swappiness
|
||||||
|
value: 10
|
||||||
|
state: present
|
||||||
|
reload: false
|
||||||
|
sysctl_set: true
|
||||||
|
system_wide: true
|
||||||
|
register: sysctl_system_test1
|
||||||
|
|
||||||
|
- name: Check with sysctl command
|
||||||
|
ansible.builtin.command: sysctl vm.swappiness
|
||||||
|
changed_when: false
|
||||||
|
register: sysctl_check_system1
|
||||||
|
|
||||||
|
- name: Debug sysctl_system_test1 sysctl_check_system1
|
||||||
|
ansible.builtin.debug:
|
||||||
|
var: item
|
||||||
|
verbosity: 1
|
||||||
|
with_items:
|
||||||
|
- "{{ sysctl_system_test1 }}"
|
||||||
|
- "{{ sysctl_check_system1 }}"
|
||||||
|
|
||||||
|
- name: Validate results for --system option
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- sysctl_system_test1 is changed
|
||||||
|
- sysctl_check_system1.stdout_lines == ["vm.swappiness = 10"]
|
||||||
|
|
||||||
|
- name: Include system_wide specific tests
|
||||||
|
ansible.builtin.include_tasks: system_wide_tests.yml
|
||||||
|
|||||||
203
tests/integration/targets/sysctl/tasks/system_wide_tests.yml
Normal file
203
tests/integration/targets/sysctl/tasks/system_wide_tests.yml
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
---
|
||||||
|
# Additional tests specifically for system_wide parameter functionality
|
||||||
|
|
||||||
|
- name: Test system_wide parameter basic functionality
|
||||||
|
block:
|
||||||
|
# Test system_wide with a simple sysctl parameter
|
||||||
|
- name: Set vm.swappiness with system_wide=true (first time)
|
||||||
|
ansible.posix.sysctl:
|
||||||
|
name: vm.swappiness
|
||||||
|
value: 35
|
||||||
|
state: present
|
||||||
|
reload: false
|
||||||
|
system_wide: true
|
||||||
|
register: sysctl_system_wide_first_test
|
||||||
|
|
||||||
|
- name: Debug first test result
|
||||||
|
ansible.builtin.debug:
|
||||||
|
var: sysctl_system_wide_first_test
|
||||||
|
|
||||||
|
- name: Set vm.swappiness with system_wide=true (second time - should not change)
|
||||||
|
ansible.posix.sysctl:
|
||||||
|
name: vm.swappiness
|
||||||
|
value: 35
|
||||||
|
state: present
|
||||||
|
reload: false
|
||||||
|
system_wide: true
|
||||||
|
register: sysctl_system_wide_second_test
|
||||||
|
|
||||||
|
- name: Debug second test result
|
||||||
|
ansible.builtin.debug:
|
||||||
|
var: sysctl_system_wide_second_test
|
||||||
|
|
||||||
|
- name: Validate system_wide basic functionality
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- sysctl_system_wide_first_test is changed
|
||||||
|
- sysctl_system_wide_second_test is not changed
|
||||||
|
|
||||||
|
# Test system_wide with reload=true
|
||||||
|
- name: Set vm.dirty_expire_centisecs with system_wide=true and reload
|
||||||
|
ansible.posix.sysctl:
|
||||||
|
name: vm.dirty_expire_centisecs
|
||||||
|
value: 3000
|
||||||
|
state: present
|
||||||
|
reload: true
|
||||||
|
system_wide: true
|
||||||
|
register: sysctl_system_wide_reload_test
|
||||||
|
|
||||||
|
- name: Check vm.dirty_expire_centisecs value
|
||||||
|
ansible.builtin.command: sysctl -n vm.dirty_expire_centisecs
|
||||||
|
changed_when: false
|
||||||
|
register: sysctl_check_dirty_expire
|
||||||
|
|
||||||
|
- name: Validate system_wide with reload=true
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- sysctl_system_wide_reload_test is changed
|
||||||
|
- sysctl_check_dirty_expire.stdout == "3000"
|
||||||
|
|
||||||
|
# Test system_wide=false behavior (default)
|
||||||
|
- name: Create custom sysctl file for testing system_wide=false
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
# Custom sysctl test file
|
||||||
|
vm.dirty_background_ratio=5
|
||||||
|
dest: "{{ output_dir_test }}/custom_sysctl.conf"
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
- name: Set vm.dirty_background_ratio with system_wide=false
|
||||||
|
ansible.posix.sysctl:
|
||||||
|
name: vm.dirty_background_ratio
|
||||||
|
value: 10
|
||||||
|
state: present
|
||||||
|
reload: true
|
||||||
|
system_wide: false
|
||||||
|
sysctl_file: "{{ output_dir_test }}/custom_sysctl.conf"
|
||||||
|
register: sysctl_system_false_test
|
||||||
|
|
||||||
|
- name: Check custom sysctl file content
|
||||||
|
ansible.builtin.command: cat {{ output_dir_test }}/custom_sysctl.conf
|
||||||
|
changed_when: false
|
||||||
|
register: custom_sysctl_content
|
||||||
|
|
||||||
|
- name: Validate system_wide=false behavior
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- sysctl_system_false_test is changed
|
||||||
|
- "'vm.dirty_background_ratio=10' in custom_sysctl_content.stdout"
|
||||||
|
|
||||||
|
# Test system_wide with check mode
|
||||||
|
- name: Test system_wide in check mode
|
||||||
|
ansible.posix.sysctl:
|
||||||
|
name: vm.swappiness
|
||||||
|
value: 25
|
||||||
|
state: present
|
||||||
|
reload: true
|
||||||
|
system_wide: true
|
||||||
|
check_mode: true
|
||||||
|
register: sysctl_system_wide_check_mode
|
||||||
|
|
||||||
|
- name: Validate check mode works with system_wide
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- sysctl_system_wide_check_mode is changed
|
||||||
|
|
||||||
|
# Test system_wide with missing directories (should not fail)
|
||||||
|
- name: Test system_wide with potentially missing directories
|
||||||
|
ansible.posix.sysctl:
|
||||||
|
name: vm.overcommit_memory
|
||||||
|
value: 1
|
||||||
|
state: present
|
||||||
|
reload: true
|
||||||
|
system_wide: true
|
||||||
|
ignoreerrors: true
|
||||||
|
register: sysctl_system_wide_missing_dirs
|
||||||
|
|
||||||
|
- name: Validate system_wide handles missing directories
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- sysctl_system_wide_missing_dirs is not failed
|
||||||
|
|
||||||
|
- name: Test system_wide with multiple configuration files (RHEL/CentOS only)
|
||||||
|
when:
|
||||||
|
- ansible_facts.os_family == 'RedHat'
|
||||||
|
- ansible_facts.virtualization_type != 'docker'
|
||||||
|
block:
|
||||||
|
# Test that system_wide processes multiple configuration files
|
||||||
|
- name: Create test sysctl.d file
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: |
|
||||||
|
# Test system-wide sysctl reload
|
||||||
|
vm.dirty_writeback_centisecs=500
|
||||||
|
dest: /etc/sysctl.d/99-ansible-test.conf
|
||||||
|
mode: "0644"
|
||||||
|
backup: true
|
||||||
|
register: test_sysctl_file
|
||||||
|
|
||||||
|
- name: Apply setting with system_wide to test multiple file processing
|
||||||
|
ansible.posix.sysctl:
|
||||||
|
name: vm.overcommit_memory
|
||||||
|
value: 1
|
||||||
|
state: present
|
||||||
|
reload: true
|
||||||
|
system_wide: true
|
||||||
|
register: sysctl_multifile_test
|
||||||
|
|
||||||
|
- name: Verify both settings are applied
|
||||||
|
ansible.builtin.shell: |
|
||||||
|
sysctl -n vm.dirty_writeback_centisecs
|
||||||
|
sysctl -n vm.overcommit_memory
|
||||||
|
changed_when: false
|
||||||
|
register: sysctl_multifile_check
|
||||||
|
|
||||||
|
- name: Validate multiple file processing
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- sysctl_multifile_test is changed
|
||||||
|
- "'500' in sysctl_multifile_check.stdout"
|
||||||
|
- "'1' in sysctl_multifile_check.stdout"
|
||||||
|
|
||||||
|
- name: Cleanup test sysctl.d file
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /etc/sysctl.d/99-ansible-test.conf
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Test system_wide parameter combinations
|
||||||
|
block:
|
||||||
|
# Test system_wide with sysctl_set
|
||||||
|
- name: Test system_wide with sysctl_set=true
|
||||||
|
ansible.posix.sysctl:
|
||||||
|
name: vm.swappiness
|
||||||
|
value: 15
|
||||||
|
state: present
|
||||||
|
reload: true
|
||||||
|
system_wide: true
|
||||||
|
sysctl_set: true
|
||||||
|
register: sysctl_system_wide_set_test
|
||||||
|
|
||||||
|
- name: Check vm.swappiness value after system_wide + sysctl_set
|
||||||
|
ansible.builtin.command: sysctl -n vm.swappiness
|
||||||
|
changed_when: false
|
||||||
|
register: sysctl_check_swappiness_set
|
||||||
|
|
||||||
|
- name: Validate system_wide with sysctl_set
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- sysctl_system_wide_set_test is changed
|
||||||
|
- sysctl_check_swappiness_set.stdout == "15"
|
||||||
|
|
||||||
|
# Test system_wide with reload=false (should not trigger system reload)
|
||||||
|
- name: Test system_wide with reload=false
|
||||||
|
ansible.posix.sysctl:
|
||||||
|
name: vm.dirty_ratio
|
||||||
|
value: 25
|
||||||
|
state: present
|
||||||
|
reload: false
|
||||||
|
system_wide: true
|
||||||
|
register: sysctl_system_wide_no_reload
|
||||||
|
|
||||||
|
- name: Validate system_wide with reload=false
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- sysctl_system_wide_no_reload is changed
|
||||||
2
tests/sanity/ignore-2.14.txt
Normal file
2
tests/sanity/ignore-2.14.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
tests/utils/shippable/check_matrix.py replace-urlopen
|
||||||
|
tests/utils/shippable/timing.py shebang
|
||||||
2
tests/sanity/ignore-2.15.txt
Normal file
2
tests/sanity/ignore-2.15.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
tests/utils/shippable/check_matrix.py replace-urlopen
|
||||||
|
tests/utils/shippable/timing.py shebang
|
||||||
1
tests/sanity/ignore-2.16.txt
Normal file
1
tests/sanity/ignore-2.16.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
tests/utils/shippable/timing.py shebang
|
||||||
1
tests/sanity/ignore-2.17.txt
Normal file
1
tests/sanity/ignore-2.17.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
tests/utils/shippable/timing.py shebang
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
tests/utils/shippable/timing.py shebang
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
tests/utils/shippable/timing.py shebang
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
tests/utils/shippable/timing.py shebang
|
||||||
|
|||||||
34
tests/unit/compat/builtins.py
Normal file
34
tests/unit/compat/builtins.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# (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__']
|
||||||
116
tests/unit/mock/loader.py
Normal file
116
tests/unit/mock/loader.py
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
# (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
|
||||||
9
tests/unit/mock/path.py
Normal file
9
tests/unit/mock/path.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
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)
|
||||||
90
tests/unit/mock/procenv.py
Normal file
90
tests/unit/mock/procenv.py
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
# (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)
|
||||||
39
tests/unit/mock/vault_helper.py
Normal file
39
tests/unit/mock/vault_helper.py
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# 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)
|
||||||
125
tests/unit/mock/yaml_helper.py
Normal file
125
tests/unit/mock/yaml_helper.py
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
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}
|
||||||
32
tests/unit/modules/conftest.py
Normal file
32
tests/unit/modules/conftest.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# 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.common.text.converters import to_bytes
|
from ansible.module_utils._text 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,
|
||||||
|
|||||||
51
tests/unit/modules/utils.py
Normal file
51
tests/unit/modules/utils.py
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
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,5 +9,6 @@ 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
|
||||||
|
|
||||||
# To specify additional options, you can specify them into .ansible-lint file.
|
PATH="${PATH/\~/${HOME}}" ansible-lint \
|
||||||
PATH="${PATH/\~/${HOME}}" ansible-lint
|
--exclude changelogs/ \
|
||||||
|
--profile=production
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
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