4 Commits
main ... 1.6.1

Author SHA1 Message Date
softwarefactory-project-zuul[bot]
31559441dc Merge pull request #574 from saito-hideki/stable-1_v1.6.1
Release 1.6.1 commit

SUMMARY
Release 1.6.1 commit

#149
#463

ISSUE TYPE

Feature Pull Request

COMPONENT NAME

ansible.posix

ADDITIONAL INFORMATION
None
2024-10-11 01:03:21 +00:00
Hideki Saito
6c3892c01b Release 1.6.1 commit
Signed-off-by: Hideki Saito <saito@fgrep.org>
2024-10-11 09:24:32 +09:00
softwarefactory-project-zuul[bot]
5717de0974 Merge pull request #572 from saito-hideki/stable-1
Create a stable branch for ansible.posix version 1.x as stable-1

SUMMARY
We are creating a stable branch to improve maintainability and ensure more accurate releases in preparation for the version 2.x release.
The new features(A.K.A minor-changes and major-changes) will be reflected in main branch only, but bug fixes can be backported to the stable branch.

Fixes #463
Fixes #573

ISSUE TYPE

Feature Pull Request

COMPONENT NAME
ansible.posix
ADDITIONAL INFORMATION



None

Reviewed-by: Andrew Klychkov <aklychko@redhat.com>
Reviewed-by: Adam Miller <admiller@redhat.com>
Reviewed-by: Felix Fontein <felix@fontein.de>
2024-10-10 22:49:43 +00:00
Hideki Saito
e270777b8d Create a stable branch for ansible.posix version 1.x as stable-1
* Created sable-1 branch for version 1.x release
* Reverted removal of skippy plugin
* Chabnged the scheduled removal to December 5, 2024.

Signed-off-by: Hideki Saito <saito@fgrep.org>
2024-10-10 09:57:39 +09:00
80 changed files with 1092 additions and 1083 deletions

View File

@@ -4,12 +4,7 @@
# SPDX-FileCopyrightText: 2024, Ansible Project # SPDX-FileCopyrightText: 2024, Ansible Project
skip_list: skip_list:
- meta-runtime[unsupported-version] # This rule doesn't make any sense - meta-runtime[unsupported-version] # Tis rule doesn't make any sense
- fqcn[deep] # This rule produces false positives for files in tests/unit/plugins/action/fixtures/ - fqcn[deep] # This rule produces false positives for files in tests/unit/plugins/action/fixtures/
- sanity[cannot-ignore] # This rule is skipped to keep backward compatibility with Python 2
exclude_paths: exclude_paths:
- changelogs/ - changelogs/
- .github/
- tests/
- meta/

View File

@@ -37,13 +37,13 @@ variables:
resources: resources:
containers: containers:
- container: default - container: default
image: quay.io/ansible/azure-pipelines-test-container:7.0.0 image: quay.io/ansible/azure-pipelines-test-container:6.0.0
pool: Standard 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,57 +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
displayName: Ansible 2.19 Sanity & Units & Lint
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: "{0}"
testFormat: 2.19/{0}
targets:
- name: Sanity
test: sanity
- name: Units
test: units
- name: Lint
test: lint
- stage: Sanity_2_18 - stage: Sanity_2_18
displayName: Ansible 2.18 Sanity & Units & Lint displayName: Ansible 2.18 sanity
dependsOn: [] dependsOn: []
jobs: jobs:
- template: templates/matrix.yml - template: templates/matrix.yml
@@ -121,7 +72,47 @@ stages:
test: units test: units
- name: Lint - name: Lint
test: lint test: lint
- stage: Sanity_2_17
displayName: Ansible 2.17 sanity
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: "{0}"
testFormat: 2.17/{0}
targets:
- name: Sanity
test: sanity
- name: Units
test: units
- name: Lint
test: lint
- stage: Sanity_2_16
displayName: Ansible 2.16 sanity
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: "{0}"
testFormat: 2.16/{0}
targets:
- name: Sanity
test: sanity
- name: Units
test: units
- stage: Sanity_2_15
displayName: Ansible 2.15 sanity
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: "{0}"
testFormat: 2.15/{0}
targets:
- name: Sanity
test: sanity
- name: Units
test: units
## Docker ## Docker
- stage: Docker_devel - stage: Docker_devel
displayName: Docker devel displayName: Docker devel
@@ -131,60 +122,14 @@ stages:
parameters: parameters:
testFormat: devel/linux/{0}/1 testFormat: devel/linux/{0}/1
targets: targets:
- name: Fedora 44 - name: Fedora 40
test: fedora44 test: fedora40
- name: Ubuntu 22.04 - name: Ubuntu 22.04
test: ubuntu2204 test: ubuntu2204
- name: Ubuntu 24.04 - name: Ubuntu 24.04
test: ubuntu2404 test: ubuntu2404
- stage: Docker_2_21
displayName: Docker 2.21
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: devel/linux/{0}/1
targets:
- name: Fedora 44
test: fedora44
- name: Ubuntu 22.04
test: ubuntu2204
- name: Ubuntu 24.04
test: ubuntu2404
- stage: Docker_2_20
displayName: Docker 2.20
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.20/linux/{0}/1
targets:
- name: Fedora 42
test: fedora42
- name: Ubuntu 22.04
test: ubuntu2204
- name: Ubuntu 24.04
test: ubuntu2404
- stage: Docker_2_19
displayName: Docker 2.19
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.19/linux/{0}/1
targets:
- name: Fedora 41
test: fedora41
- name: Ubuntu 22.04
test: ubuntu2204
- name: Ubuntu 24.04
test: ubuntu2404
- stage: Docker_2_18 - stage: Docker_2_18
displayName: Docker 2.18 displayName: Docker devel
dependsOn: [] dependsOn: []
jobs: jobs:
- template: templates/matrix.yml - template: templates/matrix.yml
@@ -197,6 +142,55 @@ stages:
test: ubuntu2204 test: ubuntu2204
- name: Ubuntu 24.04 - name: Ubuntu 24.04
test: ubuntu2404 test: ubuntu2404
- stage: Docker_2_17
displayName: Docker 2.17
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.17/linux/{0}/1
targets:
- name: Fedora 39
test: fedora39
- name: Ubuntu 20.04
test: ubuntu2004
- name: Ubuntu 22.04
test: ubuntu2204
- stage: Docker_2_16
displayName: Docker 2.16
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.16/linux/{0}/1
targets:
- name: CentOS 7
test: centos7
- name: Fedora 38
test: fedora38
- name: Ubuntu 20.04
test: ubuntu2004
- name: Ubuntu 22.04
test: ubuntu2204
- stage: Docker_2_15
displayName: Docker 2.15
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.15/linux/{0}/1
targets:
- name: CentOS 7
test: centos7
- name: Fedora 37
test: fedora37
- name: openSUSE 15 py3
test: opensuse15
- name: Ubuntu 20.04
test: ubuntu2004
- name: Ubuntu 22.04
test: ubuntu2204
## Remote ## Remote
- stage: Remote_devel - stage: Remote_devel
@@ -207,100 +201,85 @@ stages:
parameters: parameters:
testFormat: devel/{0}/1 testFormat: devel/{0}/1
targets: targets:
- name: RHEL 10.1 - name: RHEL 9.4
test: rhel/10.1 test: rhel/9.4
- name: RHEL 9.7 - name: FreeBSD 13.3
test: rhel/9.7 test: freebsd/13.3
- 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
test: freebsd/14.3
- name: FreeBSD 13.5
test: freebsd/13.5
- stage: Remote_2_19
displayName: Remote 2.19
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.19/{0}/1
targets:
- name: RHEL 10.1
test: rhel/10.1
- name: RHEL 9.7
test: rhel/9.7
- name: FreeBSD 14.2
test: freebsd/14.2
- name: FreeBSD 13.5
test: freebsd/13.5
- stage: Remote_2_18 - stage: Remote_2_18
displayName: Remote 2.18 displayName: Remote devel
dependsOn: [] dependsOn: []
jobs: jobs:
- template: templates/matrix.yml - template: templates/matrix.yml
parameters: parameters:
testFormat: 2.18/{0}/1 testFormat: 2.18/{0}/1
targets: targets:
- name: RHEL 10.1 - name: RHEL 9.4
test: rhel/10.1 test: rhel/9.4
- name: RHEL 9.7 - name: FreeBSD 13.3
test: rhel/9.7 test: freebsd/13.3
- name: FreeBSD 13.5 - stage: Remote_2_17
test: freebsd/13.5 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.3
test: freebsd/13.3
- stage: Remote_2_16
displayName: Remote 2.16
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.16/{0}/1
targets:
- name: RHEL 8.8
test: rhel/8.8
- name: RHEL 9.2
test: rhel/9.2
- name: FreeBSD 13.2
test: freebsd/13.2
- stage: Remote_2_15
displayName: Remote 2.15
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.15/{0}/1
targets:
- name: RHEL 7.9
test: rhel/7.9
- name: RHEL 8.7
test: rhel/8.7
- name: RHEL 9.1
test: rhel/9.1
- name: FreeBSD 13.2
test: freebsd/13.2
## Finally ## Finally
- stage: Summary - stage: Summary
condition: succeededOrFailed() condition: succeededOrFailed()
dependsOn: dependsOn:
- Sanity_2_15
- Remote_2_15
- Docker_2_15
- Sanity_2_16
- Remote_2_16
- Docker_2_16
- Sanity_2_17
- Remote_2_17
- Docker_2_17
- Sanity_2_18 - Sanity_2_18
- Remote_2_18 - Remote_2_18
- Docker_2_18 - Docker_2_18
- Sanity_2_19
- Remote_2_19
- Docker_2_19
- Sanity_2_20
- Remote_2_20
- Docker_2_20
- Sanity_2_21
- Remote_2_21
- Docker_2_21
- Sanity_devel - Sanity_devel
- Remote_devel # - Remote_devel # Wait for test environment release
- Docker_devel # - Docker_devel # Wait for test environment release
jobs: jobs:
- template: templates/coverage.yml - template: templates/coverage.yml

53
.github/BOTMETA.yml vendored Normal file
View File

@@ -0,0 +1,53 @@
---
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/skippy.py:
$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

View File

@@ -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

View File

@@ -4,57 +4,6 @@ ansible.posix Release Notes
.. contents:: Topics .. contents:: Topics
v2.0.0
======
Release Summary
---------------
This is the major release of the ``ansible.posix`` collection.
This changelog contains all changes to the modules and plugins
in this collection that have been added after the release of
``ansible.posix`` 1.6.2
Minor Changes
-------------
- authorized_keys - allow using absolute path to a file as a SSH key(s) source (https://github.com/ansible-collections/ansible.posix/pull/568)
- callback plugins - Add recap information to timer, profile_roles and profile_tasks callback outputs (https://github.com/ansible-collections/ansible.posix/pull/387).
Breaking Changes / Porting Guide
--------------------------------
- firewalld - Changed the type of forward and masquerade options from str to bool (https://github.com/ansible-collections/ansible.posix/issues/582).
- firewalld - Changed the type of icmp_block_inversion option from str to bool (https://github.com/ansible-collections/ansible.posix/issues/586).
Removed Features (previously deprecated)
----------------------------------------
- skippy - Remove skippy pluglin as it is no longer supported(https://github.com/ansible-collections/ansible.posix/issues/350).
Bugfixes
--------
- acl - Fixed to set ACLs on paths mounted with NFS version 4 correctly (https://github.com/ansible-collections/ansible.posix/issues/240).
- mount - Handle ``boot`` option on Linux, NetBSD and OpenBSD correctly (https://github.com/ansible-collections/ansible.posix/issues/364).
- mount - If a comment is appended to a fstab entry, state present creates a double-entry (https://github.com/ansible-collections/ansible.posix/issues/595).
v1.6.2
======
Release Summary
---------------
This is the bugfix release of the stable version ``ansible.posix`` collection.
This changelog contains all changes to the modules and plugins
in this collection that have been added after the release of
``ansible.posix`` 1.6.1.
Bugfixes
--------
- backport - Drop ansible-core 2.14 and set 2.15 minimum version (https://github.com/ansible-collections/ansible.posix/issues/578).
v1.6.1 v1.6.1
====== ======

135
README.md
View File

@@ -2,7 +2,10 @@
<!-- Add CI and code coverage badges here. Samples included below. --> <!-- Add CI and code coverage badges here. Samples included below. -->
[![Build Status]( [![Build Status](
https://dev.azure.com/ansible/ansible.posix/_apis/build/status/CI?branchName=main)](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)
[![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/ansible.posix)](https://codecov.io/gh/ansible-collections/ansible.posix) [![Run Status](https://api.shippable.com/projects/5e669aaf8b17a60007e4d18d/badge?branch=main)]() <!--[![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/ansible.posix)](https://codecov.io/gh/ansible-collections/ansible.posix)-->
<!-- Describe the collection and why a user would want to use it. What does the collection do? -->
An Ansible Collection of modules and plugins that target POSIX UNIX/Linux and derivative Operating Systems.
## Communication ## Communication
@@ -11,102 +14,88 @@ https://dev.azure.com/ansible/ansible.posix/_apis/build/status/CI?branchName=mai
* [Social Spaces](https://forum.ansible.com/c/chat/4): gather and interact with fellow enthusiasts. * [Social Spaces](https://forum.ansible.com/c/chat/4): gather and interact with fellow enthusiasts.
* [News & Announcements](https://forum.ansible.com/c/news/5): track project-wide announcements including social events. * [News & Announcements](https://forum.ansible.com/c/news/5): track project-wide announcements including social events.
## Description
<!-- Describe the collection and why a user would want to use it. What does the collection do? -->
An Ansible Collection of modules and plugins that target POSIX UNIX/Linux and derivative Operating Systems.
## Requirements
* Python:
* The Python interpreter version must meet Ansible Core's requirements.
* Ansible Core:
- ansible-core 2.16 or later
## Installation
Before using this collection, you need to install it with the Ansible Galaxy command-line tool:
```shell
ansible-galaxy collection install ansible.posix
```
You can also include it in a requirements.yml file and install it with ansible-galaxy collection install -r requirements.yml, using the format:
```yaml
collections:
- name: ansible.posix
```
Note that if you install any collections from Ansible Galaxy, they will not be upgraded automatically when you upgrade the Ansible package.
To upgrade the collection to the latest available version, run the following command:
```shell
ansible-galaxy collection install ansible.posix --upgrade
```
You can also install a specific version of the collection, for example, if you need to downgrade when something is broken in the latest version (please report an issue in this repository). Use the following syntax to install version 2.0.0:
```shell
ansible-galaxy collection install ansible.posix:==2.0.0
```
See [using Ansible collections](https://docs.ansible.com/ansible/devel/user_guide/collections_using.html) for more details.
* The Ansible [Bullhorn newsletter](https://docs.ansible.com/ansible/devel/community/communication.html#the-bullhorn): used to announce releases and important changes. * The Ansible [Bullhorn newsletter](https://docs.ansible.com/ansible/devel/community/communication.html#the-bullhorn): used to announce releases and important changes.
For more information about communication, see the [Ansible communication guide](https://docs.ansible.com/ansible/devel/community/communication.html). For more information about communication, see the [Ansible communication guide](https://docs.ansible.com/ansible/devel/community/communication.html).
## Use Cases ## Supported Versions of Ansible
<!--start requires_ansible-->
## Ansible version compatibility
You can see the general use-cases as an example by `ansible-doc` command like below. This collection has been tested against following Ansible versions: **>=2.15**.
<!--end requires_ansible-->
For example, ansible.posix.firewalld module: ## Included content
```shell Check out [Ansible Galaxy](https://galaxy.ansible.com/ui/repo/published/ansible/posix/content/) or [the Ansible documentation](https://docs.ansible.com/ansible/devel/collections/ansible/posix/) for all modules and plugins included in this collection.
ansible-doc ansible.posix.firewalld
## Installing this collection
You can install the ``ansible.posix`` collection with the Ansible Galaxy CLI:
ansible-galaxy collection install ansible.posix
You can also include it in a `requirements.yml` file and install it with `ansible-galaxy collection install -r requirements.yml`, using the format:
```yaml
---
collections:
- name: ansible.posix
``` ```
Also, if you want to confirm the plugins descriptions, you can follow the following option with `ansible-doc` command: ## Using this collection
For example, ansible.posix.profile_tasks callback plugin: <!--Include some quick examples that cover the most common use cases for your collection content. -->
```shell
ansible-doc -t callback ansible.posix.profile_tasks
```
## Testing See [Ansible Using collections](https://docs.ansible.com/ansible/latest/user_guide/collections_using.html) for more details.
The following ansible-core versions have been tested with this collection: ## Contributing to this collection
- ansible-core 2.20 (devel) <!--Describe how the community can contribute to your collection. At a minimum, include how and where users can create issues to report problems or request features for this collection. List contribution requirements, including preferred workflows and necessary testing, so you can benefit from community PRs. If you are following general Ansible contributor guidelines, you can link to - [Ansible Community Guide](https://docs.ansible.com/ansible/latest/community/index.html). -->
- ansible-core 2.19 (stable) *
- ansible-core 2.18 (stable)
- ansible-core 2.17 (stable)
## Contributing We welcome community contributions to this collection. See [Contributing to Ansible-maintained collections](https://docs.ansible.com/ansible/devel/community/contributing_maintained_collections.html#contributing-maintained-collections) for complete details.
We welcome community contributions to this collection. For more details, see [Contributing to Ansible-maintained collections](https://docs.ansible.com/ansible/devel/community/contributing_maintained_collections.html#contributing-maintained-collections) for complete details.
* [Issues](https://github.com/ansible-collections/ansible.posix/issues) * [Issues](https://github.com/ansible-collections/ansible.posix/issues)
* [Pull Requests](https://github.com/ansible-collections/ansible.posix/pulls) * [Pull Requests](https://github.com/ansible-collections/ansible.posix/pulls)
* [Ansible Community Guide](https://docs.ansible.com/ansible/latest/community/index.html) * [Ansible Community Guide](https://docs.ansible.com/ansible/latest/community/index.html)
### Code of Conduct
This collection follows the Ansible project's
[Code of Conduct](https://docs.ansible.com/ansible/devel/community/code_of_conduct.html).
Please read and familiarize yourself with this document.
## Support ## Release notes
See [Communication](#Communication) section.
## Release Notes and Roadmap
See [changelog](https://github.com/ansible-collections/ansible.posix/blob/main/CHANGELOG.rst) for more details. See [changelog](https://github.com/ansible-collections/ansible.posix/blob/main/CHANGELOG.rst) for more details.
## Related Information ## External requirements
This document was written using the following [template](https://access.redhat.com/articles/7068606). None
The README has been carefully prepared to cover the [community template](https://github.com/ansible-collections/collection_template/blob/main/README.md), but if you find any problems, please file a [documentation issue](https://github.com/ansible-collections/ansible.posix/issues/new?assignees=&labels=&projects=&template=documentation_report.md). ## Tested with Ansible
## License Information <!-- List the versions of Ansible the collection has been tested with. Must match what is in galaxy.yml. -->
- ansible-core 2.19 (devel)
- ansible-core 2.18 (stable) *
- ansible-core 2.17 (stable)
- ansible-core 2.16 (stable)
- ansible-core 2.15 (stable)
*Note: For ansible-core 2.18, CI only covers sanity tests and no integration tests will be run until the test environment is released.*
## Roadmap
<!-- Optional. Include the roadmap for this collection, and the proposed release/versioning strategy so users can anticipate the upgrade/update cycle. -->
## More information
<!-- List out where the user can find additional information, such as working group meeting times, slack/IRC channels, or documentation for the product this collection automates. At a minimum, link to: -->
- [Ansible Collection overview](https://github.com/ansible-collections/overview)
- [Ansible User guide](https://docs.ansible.com/ansible/latest/user_guide/index.html)
- [Ansible Developer guide](https://docs.ansible.com/ansible/latest/dev_guide/index.html)
- [Ansible Community code of conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html)
## Licensing
GNU General Public License v3.0 or later. GNU General Public License v3.0 or later.

View File

@@ -429,64 +429,3 @@ releases:
- 571_ci_bump_core_version.yml - 571_ci_bump_core_version.yml
- 572_revert_removal_of_skippy.yml - 572_revert_removal_of_skippy.yml
release_date: '2024-10-11' release_date: '2024-10-11'
1.6.2:
changes:
bugfixes:
- backport - Drop ansible-core 2.14 and set 2.15 minimum version (https://github.com/ansible-collections/ansible.posix/issues/578).
release_summary: 'This is the bugfix release of the stable version ``ansible.posix``
collection.
This changelog contains all changes to the modules and plugins
in this collection that have been added after the release of
``ansible.posix`` 1.6.1.'
fragments:
- 1.6.2.yml
- 580_drop_ansible214.yml
release_date: '2024-10-22'
2.0.0:
changes:
breaking_changes:
- firewalld - Changed the type of forward and masquerade options from str to
bool (https://github.com/ansible-collections/ansible.posix/issues/582).
- firewalld - Changed the type of icmp_block_inversion option from str to bool
(https://github.com/ansible-collections/ansible.posix/issues/586).
bugfixes:
- acl - Fixed to set ACLs on paths mounted with NFS version 4 correctly (https://github.com/ansible-collections/ansible.posix/issues/240).
- mount - Handle ``boot`` option on Linux, NetBSD and OpenBSD correctly (https://github.com/ansible-collections/ansible.posix/issues/364).
- mount - If a comment is appended to a fstab entry, state present creates a
double-entry (https://github.com/ansible-collections/ansible.posix/issues/595).
minor_changes:
- authorized_keys - allow using absolute path to a file as a SSH key(s) source
(https://github.com/ansible-collections/ansible.posix/pull/568)
- callback plugins - Add recap information to timer, profile_roles and profile_tasks
callback outputs (https://github.com/ansible-collections/ansible.posix/pull/387).
release_summary: 'This is the major release of the ``ansible.posix`` collection.
This changelog contains all changes to the modules and plugins
in this collection that have been added after the release of
``ansible.posix`` 1.6.2'
removed_features:
- skippy - Remove skippy pluglin as it is no longer supported(https://github.com/ansible-collections/ansible.posix/issues/350).
fragments:
- 2.0.0.yml
- 365-boot-linux.yml
- 387_callback_output_header.yml
- 556_remove_skippy_callback.yml
- 566_bump_version_161.yml
- 567_remove_version_added.yml
- 568_update_authorized_key.yml
- 570_nfs4_acl.yml
- 571_ci_bump_core_version.yml
- 576_bump_version_2.yml
- 581_ci_selinux.yml
- 584_firewalld_opt_type.yml
- 587_update_README.yml
- 588_ci_enable_devel.yml
- 593_replace_freebsd_version.yml
- 597_remove_fstab_comment_on_updating.yml
- 598_icmp_block_inversion.yml
release_date: '2024-12-04'

View File

@@ -1,2 +0,0 @@
trivial:
- Bump version to 3.0.0 for the next release (https://github.com/ansible-collections/ansible.posix/issues/603).

View File

@@ -1,2 +0,0 @@
trivial:
- Remove ubuntu20.04 from CI tests (https://github.com/ansible-collections/ansible.posix/issues/612).

View File

@@ -1,3 +0,0 @@
---
minor_changes:
- profile_tasks - Add option to provide a different date/time format (https://github.com/ansible-collections/ansible.posix/issues/279).

View File

@@ -1,6 +0,0 @@
---
bugfixes:
- ansible.posix.cgroup_perf_recap - fixes json module load path (https://github.com/ansible-collections/ansible.posix/issues/630).
trivial:
- ansible.posix.seboolean - remove unnecessary condition from seboolean integration tests (https://github.com/ansible-collections/ansible.posix/issues/630).
- ansible.posix.selinux - optimize conditions for selinux integration tests (https://github.com/ansible-collections/ansible.posix/issues/630).

View File

@@ -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).

View File

@@ -1,2 +0,0 @@
trivial:
- Add Red Hat Enterprise Linux 10.0 to the CI matrix (https://github.com/ansible-collections/ansible.posix/issues/642).

View File

@@ -1,2 +0,0 @@
minor_changes:
- "profile_tasks and profile_roles callback plugins - avoid deleted/deprecated callback functions, instead use modern interface that was introduced a longer time ago (https://github.com/ansible-collections/ansible.posix/issues/650)."

View File

@@ -1,3 +0,0 @@
---
trivial:
- Bump ansible-core version to 2.20 of devel branch and add 2.19 to CI

View File

@@ -1,2 +0,0 @@
trivial:
- AZP - fixed syntax error in CI test.

View File

@@ -1,3 +0,0 @@
---
trivial:
- README - Update README to reflect Ansible Core 2.19 release.

View File

@@ -1,3 +0,0 @@
---
trivial:
- AZP - Update AZP matrix to follow ansible-test changes.

View File

@@ -1,3 +0,0 @@
bugfixes:
- "firewalld_info - stop returning warnings as return values; this has been deprecated by ansible-core (https://github.com/ansible-collections/ansible.posix/pull/670)."
- "mount - stop returning warnings as return values; this has been deprecated by ansible-core (https://github.com/ansible-collections/ansible.posix/pull/670)."

View File

@@ -1,2 +0,0 @@
trivial:
- Update AZP CI matrix (https://github.com/ansible-collections/ansible.posix/issues/673).

View File

@@ -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.

View 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).

View File

@@ -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.

View File

@@ -1,7 +1,7 @@
--- ---
namespace: ansible namespace: ansible
name: posix name: posix
version: 3.0.0 version: 1.6.1
readme: README.md readme: README.md
authors: authors:
- Ansible (github.com/ansible) - Ansible (github.com/ansible)

View File

@@ -1,2 +1,8 @@
--- ---
requires_ansible: ">=2.16.0" requires_ansible: ">=2.14.0"
plugin_routing:
callback:
skippy:
deprecation:
removal_date: "2024-12-05"
warning_text: See the plugin documentation for more details

View File

@@ -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

View File

@@ -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)]

View File

@@ -132,7 +132,6 @@ DOCUMENTATION = '''
import csv import csv
import datetime import datetime
import json
import os import os
import time import time
import threading import threading
@@ -141,8 +140,9 @@ 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.parsing.ajson import AnsibleJSONEncoder from ansible.module_utils.six import with_metaclass
from ansible.parsing.ajson import AnsibleJSONEncoder, json
from ansible.plugins.callback import CallbackBase from ansible.plugins.callback import CallbackBase
@@ -157,7 +157,7 @@ def dict_fromkeys(keys, default=None):
return d return d
class BaseProf(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

View File

@@ -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

View File

@@ -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

View File

@@ -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()
@@ -124,11 +124,11 @@ class CallbackModule(CallbackBase):
def v2_playbook_on_handler_task_start(self, task): def v2_playbook_on_handler_task_start(self, task):
self._record_task(task) self._record_task(task)
def v2_playbook_on_stats(self, stats): def playbook_on_setup(self):
# Align summary report header with other callback plugin summary self._display_tasktime()
self._display.banner("ROLES RECAP")
self._display.display(tasktime()) def playbook_on_stats(self, stats):
self._display_tasktime()
self._display.display(filled("", fchar="=")) self._display.display(filled("", fchar="="))
timestamp(self) timestamp(self)

View File

@@ -52,17 +52,6 @@ DOCUMENTATION = '''
- section: callback_profile_tasks - section: callback_profile_tasks
key: summary_only key: summary_only
version_added: 1.5.0 version_added: 1.5.0
datetime_format:
description:
- Datetime format, as expected by the C(strftime) and C(strptime) methods.
An C(iso8601) alias will be translated to C('%Y-%m-%dT%H:%M:%S.%f') if that datetime standard wants to be used.
default: '%A %d %B %Y %H:%M:%S %z'
env:
- name: PROFILE_TASKS_DATETIME_FORMAT
ini:
- section: callback_profile_tasks
key: datetime_format
version_added: 3.0.0
''' '''
EXAMPLES = ''' EXAMPLES = '''
@@ -83,15 +72,14 @@ sample output: >
''' '''
import collections import collections
import time
from datetime import datetime from ansible.module_utils.six.moves import reduce
from functools import reduce
from ansible.plugins.callback import CallbackBase from ansible.plugins.callback import CallbackBase
# define start time # define start time
dt0 = dtn = datetime.now().astimezone() t0 = tn = time.time()
def secondsToStr(t): def secondsToStr(t):
@@ -116,18 +104,17 @@ def filled(msg, fchar="*"):
def timestamp(self): def timestamp(self):
if self.current is not None: if self.current is not None:
elapsed = (datetime.now().astimezone() - self.stats[self.current]['started']).total_seconds() elapsed = time.time() - self.stats[self.current]['started']
self.stats[self.current]['elapsed'] += elapsed self.stats[self.current]['elapsed'] += elapsed
def tasktime(self): def tasktime():
global dtn global tn
cdtn = datetime.now().astimezone() time_current = time.strftime('%A %d %B %Y %H:%M:%S %z')
datetime_current = cdtn.strftime(self.datetime_format) time_elapsed = secondsToStr(time.time() - tn)
time_elapsed = secondsToStr((cdtn - dtn).total_seconds()) time_total_elapsed = secondsToStr(time.time() - t0)
time_total_elapsed = secondsToStr((cdtn - dt0).total_seconds()) tn = time.time()
dtn = cdtn return filled('%s (%s)%s%s' % (time_current, time_elapsed, ' ' * 7, time_total_elapsed))
return filled('%s (%s)%s%s' % (datetime_current, time_elapsed, ' ' * 7, time_total_elapsed))
class CallbackModule(CallbackBase): class CallbackModule(CallbackBase):
@@ -147,7 +134,6 @@ class CallbackModule(CallbackBase):
self.sort_order = None self.sort_order = None
self.summary_only = None self.summary_only = None
self.task_output_limit = None self.task_output_limit = None
self.datetime_format = None
super(CallbackModule, self).__init__() super(CallbackModule, self).__init__()
@@ -173,14 +159,9 @@ class CallbackModule(CallbackBase):
else: else:
self.task_output_limit = int(self.task_output_limit) self.task_output_limit = int(self.task_output_limit)
self.datetime_format = self.get_option('datetime_format')
if self.datetime_format is not None:
if self.datetime_format == 'iso8601':
self.datetime_format = '%Y-%m-%dT%H:%M:%S.%f'
def _display_tasktime(self): def _display_tasktime(self):
if not self.summary_only: if not self.summary_only:
self._display.display(tasktime(self)) self._display.display(tasktime())
def _record_task(self, task): def _record_task(self, task):
""" """
@@ -195,11 +176,10 @@ class CallbackModule(CallbackBase):
# with the same UUID is executed when `serial` is specified in a playbook. # with the same UUID is executed when `serial` is specified in a playbook.
# elapsed: Elapsed time since the first serialized task was started # elapsed: Elapsed time since the first serialized task was started
self.current = task._uuid self.current = task._uuid
dtn = datetime.now().astimezone()
if self.current not in self.stats: if self.current not in self.stats:
self.stats[self.current] = {'started': dtn, 'elapsed': 0.0, 'name': task.get_name()} self.stats[self.current] = {'started': time.time(), 'elapsed': 0.0, 'name': task.get_name()}
else: else:
self.stats[self.current]['started'] = dtn self.stats[self.current]['started'] = time.time()
if self._display.verbosity >= 2: if self._display.verbosity >= 2:
self.stats[self.current]['path'] = task.get_path() self.stats[self.current]['path'] = task.get_path()
@@ -209,11 +189,11 @@ class CallbackModule(CallbackBase):
def v2_playbook_on_handler_task_start(self, task): def v2_playbook_on_handler_task_start(self, task):
self._record_task(task) self._record_task(task)
def v2_playbook_on_stats(self, stats): def playbook_on_setup(self):
# Align summary report header with other callback plugin summary self._display_tasktime()
self._display.banner("TASKS RECAP")
self._display.display(tasktime(self)) def playbook_on_stats(self, stats):
self._display_tasktime()
self._display.display(filled("", fchar="=")) self._display.display(filled("", fchar="="))
timestamp(self) timestamp(self)

View File

@@ -0,0 +1,43 @@
# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
# (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
name: skippy
type: stdout
requirements:
- set as main display callback
short_description: Ansible screen output that ignores skipped status
deprecated:
why: The 'default' callback plugin now supports this functionality
removed_at_date: '2024-12-05'
alternative: "'default' callback plugin with 'display_skipped_hosts = no' option"
extends_documentation_fragment:
- default_callback
description:
- This callback does the same as the default except it does not output skipped host/task/item status
'''
from ansible.plugins.callback.default import CallbackModule as CallbackModule_default
class CallbackModule(CallbackModule_default):
'''
This is the default callback interface, which simply prints messages
to stdout when new callback events are received.
'''
CALLBACK_VERSION = 2.0
CALLBACK_TYPE = 'stdout'
CALLBACK_NAME = 'ansible.posix.skippy'
def v2_runner_on_skipped(self, result):
pass
def v2_runner_item_on_skipped(self, result):
pass

View File

@@ -46,6 +46,4 @@ class CallbackModule(CallbackBase):
def v2_playbook_on_stats(self, stats): def v2_playbook_on_stats(self, stats):
end_time = datetime.utcnow() end_time = datetime.utcnow()
runtime = end_time - self.start_time runtime = end_time - self.start_time
# Align summary report header with other callback plugin summary self._display.display("Playbook run took %s days, %s hours, %s minutes, %s seconds" % (self.days_hours_minutes_seconds(runtime)))
self._display.banner("PLAYBOOK RECAP")
self._display.display("Playbook run took %s days, %s hours, %s minutes, %s seconds\n\r" % (self.days_hours_minutes_seconds(runtime)))

View File

@@ -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):

View File

@@ -24,7 +24,6 @@ options:
key: key:
description: description:
- The SSH public key(s), as a string or (since Ansible 1.9) url (https://github.com/username.keys). - The SSH public key(s), as a string or (since Ansible 1.9) url (https://github.com/username.keys).
- You can also use V(file://) prefix to search remote for a file with SSH key(s).
type: str type: str
required: true required: true
path: path:
@@ -97,12 +96,6 @@ EXAMPLES = r'''
state: present state: present
key: https://github.com/charlie.keys key: https://github.com/charlie.keys
- name: Set authorized keys taken from path on controller node
ansible.posix.authorized_key:
user: charlie
state: present
key: file:///home/charlie/.ssh/id_rsa.pub
- name: Set authorized keys taken from url using lookup - name: Set authorized keys taken from url using lookup
ansible.posix.authorized_key: ansible.posix.authorized_key:
user: charlie user: charlie
@@ -225,20 +218,10 @@ 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
@@ -484,18 +467,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):
@@ -575,7 +556,7 @@ def enforce_state(module, params):
follow = params.get('follow', False) follow = params.get('follow', False)
error_msg = "Error getting key from: %s" error_msg = "Error getting key from: %s"
# if the key is a url or file, request it and use it as key source # if the key is a url, request it and use it as key source
if key.startswith("http"): if key.startswith("http"):
try: try:
resp, info = fetch_url(module, key) resp, info = fetch_url(module, key)
@@ -589,26 +570,13 @@ def enforce_state(module, params):
# resp.read gives bytes on python3, convert to native string type # resp.read gives bytes on python3, convert to native string type
key = to_native(key, errors='surrogate_or_strict') key = to_native(key, errors='surrogate_or_strict')
if key.startswith("file"):
# if the key is an absolute path, check for existense and use it as a key source
key_path = urlparse(key).path
if not os.path.exists(key_path):
module.fail_json(msg="Path to a key file not found: %s" % key_path)
if not os.path.isfile(key_path):
module.fail_json(msg="Path to a key is a directory and must be a file: %s" % key_path)
try:
with open(key_path, 'r') as source_fh:
key = source_fh.read()
except OSError as e:
module.fail_json(msg="Failed to read key file %s : %s" % (key_path, to_native(e)))
# extract individual keys into an array, skipping blank lines and comments # extract individual keys into an array, skipping blank lines and comments
new_keys = [s for s in key.splitlines() if s and not s.startswith('#')] new_keys = [s for s in key.splitlines() if s and not s.startswith('#')]
# 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

View File

@@ -74,8 +74,7 @@ options:
icmp_block_inversion: icmp_block_inversion:
description: description:
- Enable/Disable inversion of ICMP blocks for a zone in firewalld. - Enable/Disable inversion of ICMP blocks for a zone in firewalld.
- Note that the option type is changed to bool in ansible.posix version 2.0.0 and later. type: str
type: bool
zone: zone:
description: description:
- The firewalld zone to add/remove to/from. - The firewalld zone to add/remove to/from.
@@ -113,13 +112,11 @@ options:
description: description:
- The forward setting you would like to enable/disable to/from zones within firewalld. - The forward setting you would like to enable/disable to/from zones within firewalld.
- This option only is supported by firewalld v0.9.0 or later. - This option only is supported by firewalld v0.9.0 or later.
- Note that the option type is changed to bool in ansible.posix version 2.0.0 and later. type: str
type: bool
masquerade: masquerade:
description: description:
- The masquerade setting you would like to enable/disable to/from zones within firewalld. - The masquerade setting you would like to enable/disable to/from zones within firewalld.
- Note that the option type is changed to bool in ansible.posix version 2.0.0 and later. type: str
type: bool
offline: offline:
description: description:
- Ignores O(immediate) if O(permanent=true) and firewalld is not running. - Ignores O(immediate) if O(permanent=true) and firewalld is not running.
@@ -153,7 +150,7 @@ author:
''' '''
EXAMPLES = r''' EXAMPLES = r'''
- name: Permanently enable https service, also enable it immediately if possible - name: permanently enable https service, also enable it immediately if possible
ansible.posix.firewalld: ansible.posix.firewalld:
service: https service: https
state: enabled state: enabled
@@ -161,92 +158,81 @@ EXAMPLES = r'''
immediate: true immediate: true
offline: true offline: true
- name: Permit traffic in default zone for https service - name: permit traffic in default zone for https service
ansible.posix.firewalld: ansible.posix.firewalld:
service: https service: https
permanent: true permanent: true
state: enabled state: enabled
- name: Permit ospf traffic - name: permit ospf traffic
ansible.posix.firewalld: ansible.posix.firewalld:
protocol: ospf protocol: ospf
permanent: true permanent: true
state: enabled state: enabled
- name: Do not permit traffic in default zone on port 8081/tcp - name: do not permit traffic in default zone on port 8081/tcp
ansible.posix.firewalld: ansible.posix.firewalld:
port: 8081/tcp port: 8081/tcp
permanent: true permanent: true
state: disabled state: disabled
- name: Permit traffic in default zone on port 161-162/ucp - ansible.posix.firewalld:
ansible.posix.firewalld:
port: 161-162/udp port: 161-162/udp
permanent: true permanent: true
state: enabled state: enabled
- name: Permit traffic in dmz zone on http service - ansible.posix.firewalld:
ansible.posix.firewalld:
zone: dmz zone: dmz
service: http service: http
permanent: true permanent: true
state: enabled state: enabled
- name: Enable FTP service with rate limiting using firewalld rich rule - ansible.posix.firewalld:
ansible.posix.firewalld:
rich_rule: rule service name="ftp" audit limit value="1/m" accept rich_rule: rule service name="ftp" audit limit value="1/m" accept
permanent: true permanent: true
state: enabled state: enabled
- name: Allow traffic from 192.0.2.0/24 in internal zone - ansible.posix.firewalld:
ansible.posix.firewalld:
source: 192.0.2.0/24 source: 192.0.2.0/24
zone: internal zone: internal
state: enabled state: enabled
- name: Assign eth2 interface to trusted zone - ansible.posix.firewalld:
ansible.posix.firewalld:
zone: trusted zone: trusted
interface: eth2 interface: eth2
permanent: true permanent: true
state: enabled state: enabled
- name: Enable forwarding in internal zone - ansible.posix.firewalld:
ansible.posix.firewalld:
forward: true forward: true
state: enabled state: enabled
permanent: true permanent: true
zone: internal zone: internal
- name: Enable masquerade in dmz zone - ansible.posix.firewalld:
ansible.posix.firewalld:
masquerade: true masquerade: true
state: enabled state: enabled
permanent: true permanent: true
zone: dmz zone: dmz
- name: Create custom zone if not already present - ansible.posix.firewalld:
ansible.posix.firewalld:
zone: custom zone: custom
state: present state: present
permanent: true permanent: true
- name: Enable ICMP block inversion in drop zone - ansible.posix.firewalld:
ansible.posix.firewalld:
zone: drop zone: drop
state: enabled state: enabled
permanent: true permanent: true
icmp_block_inversion: true icmp_block_inversion: true
- name: Block ICMP echo requests in drop zone - ansible.posix.firewalld:
ansible.posix.firewalld:
zone: drop zone: drop
state: enabled state: enabled
permanent: true permanent: true
icmp_block: echo-request icmp_block: echo-request
- name: Set internal zone target to ACCEPT - ansible.posix.firewalld:
ansible.posix.firewalld:
zone: internal zone: internal
state: present state: present
permanent: true permanent: true
@@ -262,6 +248,7 @@ EXAMPLES = r'''
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.parsing.convert_bool import boolean
from ansible_collections.ansible.posix.plugins.module_utils.firewalld import FirewallTransaction, fw_offline from ansible_collections.ansible.posix.plugins.module_utils.firewalld import FirewallTransaction, fw_offline
try: try:
@@ -875,7 +862,7 @@ def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec=dict( argument_spec=dict(
icmp_block=dict(type='str'), icmp_block=dict(type='str'),
icmp_block_inversion=dict(type='bool'), icmp_block_inversion=dict(type='str'),
service=dict(type='str'), service=dict(type='str'),
protocol=dict(type='str'), protocol=dict(type='str'),
port=dict(type='str'), port=dict(type='str'),
@@ -888,8 +875,8 @@ def main():
state=dict(type='str', required=True, choices=['absent', 'disabled', 'enabled', 'present']), state=dict(type='str', required=True, choices=['absent', 'disabled', 'enabled', 'present']),
timeout=dict(type='int', default=0), timeout=dict(type='int', default=0),
interface=dict(type='str'), interface=dict(type='str'),
forward=dict(type='bool'), forward=dict(type='str'),
masquerade=dict(type='bool'), masquerade=dict(type='str'),
offline=dict(type='bool', default=False), offline=dict(type='bool', default=False),
target=dict(type='str', choices=['default', 'ACCEPT', 'DROP', '%%REJECT%%']), target=dict(type='str', choices=['default', 'ACCEPT', 'DROP', '%%REJECT%%']),
), ),
@@ -998,7 +985,16 @@ def main():
msgs.append("Changed icmp-block %s to %s" % (icmp_block, desired_state)) msgs.append("Changed icmp-block %s to %s" % (icmp_block, desired_state))
if icmp_block_inversion is not None: if icmp_block_inversion is not None:
expected_state = 'enabled' if (desired_state == 'enabled') == icmp_block_inversion else 'disabled' # Type of icmp_block_inversion will be changed to boolean in a future release.
icmp_block_inversion_status = True
try:
icmp_block_inversion_status = boolean(icmp_block_inversion, True)
except TypeError:
module.warn('The value of the icmp_block_inversion option is "%s". '
'The type of the option will be changed from string to boolean in a future release. '
'To avoid unexpected behavior, please change the value to boolean.' % icmp_block_inversion)
expected_state = 'enabled' if (desired_state == 'enabled') == icmp_block_inversion_status else 'disabled'
transaction = IcmpBlockInversionTransaction( transaction = IcmpBlockInversionTransaction(
module, module,
action_args=(), action_args=(),
@@ -1133,7 +1129,16 @@ def main():
msgs = msgs + transaction_msgs msgs = msgs + transaction_msgs
if forward is not None: if forward is not None:
expected_state = 'enabled' if (desired_state == 'enabled') == forward else 'disabled' # Type of forward will be changed to boolean in a future release.
forward_status = False
try:
forward_status = boolean(forward, False)
except TypeError:
module.warn('The value of the forward option is "%s". '
'The type of the option will be changed from string to boolean in a future release. '
'To avoid unexpected behavior, please change the value to boolean.' % forward)
expected_state = 'enabled' if (desired_state == 'enabled') == forward_status else 'disabled'
transaction = ForwardTransaction( transaction = ForwardTransaction(
module, module,
action_args=(), action_args=(),
@@ -1147,7 +1152,16 @@ def main():
msgs = msgs + transaction_msgs msgs = msgs + transaction_msgs
if masquerade is not None: if masquerade is not None:
expected_state = 'enabled' if (desired_state == 'enabled') == masquerade else 'disabled' # Type of masquerade will be changed to boolean in a future release.
masquerade_status = True
try:
masquerade_status = boolean(masquerade, True)
except TypeError:
module.warn('The value of the masquerade option is "%s". '
'The type of the option will be changed from string to boolean in a future release. '
'To avoid unexpected behavior, please change the value to boolean.' % masquerade)
expected_state = 'enabled' if (desired_state == 'enabled') == masquerade_status else 'disabled'
transaction = MasqueradeTransaction( transaction = MasqueradeTransaction(
module, module,
action_args=(), action_args=(),

View File

@@ -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
@@ -319,6 +319,7 @@ def main():
active_zones=module.params['active_zones'], active_zones=module.params['active_zones'],
collected_zones=list(), collected_zones=list(),
undefined_zones=list(), undefined_zones=list(),
warnings=list(),
) )
# Exit with failure message if requirements modules are not installed. # Exit with failure message if requirements modules are not installed.

View File

@@ -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) if k != 'warnings'])
new_line = '%(src)s %(name)s %(fstype)s %(opts)s %(dump)s %(passno)s\n' new_line = '%(src)s %(name)s %(fstype)s %(opts)s %(dump)s %(passno)s\n'
if platform.system() == 'SunOS': if platform.system() == 'SunOS':
@@ -302,7 +303,7 @@ def _set_mount_save_old(module, args):
continue continue
fields = line.split('#')[0].split() fields = line.split()
# Check if we got a valid line for splitting # Check if we got a valid line for splitting
# (on Linux the 5th and the 6th field is optional) # (on Linux the 5th and the 6th field is optional)
@@ -803,6 +804,7 @@ def main():
passno='-', passno='-',
fstab=module.params['fstab'], fstab=module.params['fstab'],
boot='yes' if module.params['boot'] else 'no', boot='yes' if module.params['boot'] else 'no',
warnings=[]
) )
if args['fstab'] is None: if args['fstab'] is None:
args['fstab'] = '/etc/vfstab' args['fstab'] = '/etc/vfstab'
@@ -814,6 +816,7 @@ def main():
passno='0', passno='0',
fstab=module.params['fstab'], fstab=module.params['fstab'],
boot='yes', boot='yes',
warnings=[]
) )
if args['fstab'] is None: if args['fstab'] is None:
args['fstab'] = '/etc/fstab' args['fstab'] = '/etc/fstab'
@@ -831,7 +834,8 @@ def main():
linux_mounts = get_linux_mounts(module) linux_mounts = get_linux_mounts(module)
if linux_mounts is None: if linux_mounts is None:
module.warn('Cannot open file /proc/self/mountinfo. Bind mounts might be misinterpreted.') args['warnings'].append('Cannot open file /proc/self/mountinfo.'
' Bind mounts might be misinterpreted.')
# Override defaults with user specified params # Override defaults with user specified params
for key in ('src', 'fstype', 'passno', 'opts', 'dump', 'fstab'): for key in ('src', 'fstype', 'passno', 'opts', 'dump', 'fstab'):
@@ -843,7 +847,7 @@ def main():
# specified in 'opts', mount module will ignore 'boot'. # specified in 'opts', mount module will ignore 'boot'.
opts = args['opts'].split(',') opts = args['opts'].split(',')
if module.params['boot'] and 'noauto' in opts: if module.params['boot'] and 'noauto' in opts:
module.warn("Ignore the 'boot' due to 'opts' contains 'noauto'.") args['warnings'].append("Ignore the 'boot' due to 'opts' contains 'noauto'.")
elif not module.params['boot']: elif not module.params['boot']:
args['boot'] = 'no' args['boot'] = 'no'
opts.append('noauto') opts.append('noauto')

View File

@@ -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):

View File

@@ -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):

View File

@@ -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):

View File

@@ -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

View File

@@ -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

View File

@@ -80,13 +80,6 @@ EXAMPLES = r'''
sysctl_file: /tmp/test_sysctl.conf sysctl_file: /tmp/test_sysctl.conf
reload: false reload: false
# Enable resource limits management in FreeBSD
- ansible.posix.sysctl:
name: kern.racct.enable
value: '1'
sysctl_file: /boot/loader.conf
reload: false
# Set ip forwarding on in /proc and verify token value with the sysctl command # Set ip forwarding on in /proc and verify token value with the sysctl command
- ansible.posix.sysctl: - ansible.posix.sysctl:
name: net.ipv4.ip_forward name: net.ipv4.ip_forward
@@ -107,20 +100,12 @@ EXAMPLES = r'''
import os import os
import platform import platform
import re import re
import sys
import tempfile import tempfile
# TODO(Python2): On Python 2, string_types is basestring (str + unicode).
# This module may run on target hosts with Python 2.7.
# Remove the Python 2 branch when Python 2 support is dropped.
if sys.version_info >= (3, 0):
string_types = str
else:
string_types = basestring # pylint: disable=undefined-variable
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.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):

View File

@@ -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)

View File

@@ -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):

View File

@@ -46,12 +46,6 @@
path: "{{ test_dir }}" path: "{{ test_dir }}"
state: directory state: directory
mode: "0755" mode: "0755"
- name: Install acl package
ansible.builtin.package:
name: acl
state: present
############################################################################## ##############################################################################
- name: Grant ansible user read access to a file - name: Grant ansible user read access to a file
ansible.posix.acl: ansible.posix.acl:

View File

@@ -35,5 +35,3 @@ multiple_keys_comments: |
ssh-rsa DATA_BASIC 1@testing ssh-rsa DATA_BASIC 1@testing
# I like adding comments yo-dude-this-is-not-a-key INVALID_DATA 2@testing # I like adding comments yo-dude-this-is-not-a-key INVALID_DATA 2@testing
ecdsa-sha2-nistp521 ECDSA_DATA 4@testing ecdsa-sha2-nistp521 ECDSA_DATA 4@testing
key_path: /tmp/id_rsa.pub

View File

@@ -1,32 +0,0 @@
---
- name: Create key file for test
ansible.builtin.copy:
dest: "{{ key_path }}"
content: "{{ rsa_key_basic }}"
mode: "0600"
- name: Add key using path
ansible.posix.authorized_key:
user: root
key: file://{{ key_path }}
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: Assert that the key was added
ansible.builtin.assert:
that:
- result.changed == true
- name: Add key using path again
ansible.posix.authorized_key:
user: root
key: file://{{ key_path }}
state: present
path: "{{ output_dir | expanduser }}/authorized_keys"
register: result
- name: Assert that no changes were applied
ansible.builtin.assert:
that:
- result.changed == false

View File

@@ -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

View File

@@ -31,9 +31,3 @@
- name: Test for the management of comments with key - name: Test for the management of comments with key
ansible.builtin.import_tasks: comments.yml ansible.builtin.import_tasks: comments.yml
- name: Test for specifying key as a path
ansible.builtin.import_tasks: check_path.yml
- name: Test for permission denied files
ansible.builtin.import_tasks: check_permissions.yml

View File

@@ -1,5 +1,3 @@
needs/privileged
needs/root
destructive destructive
shippable/posix/group1 shippable/posix/group1
skip/aix skip/aix

View File

@@ -114,3 +114,60 @@
ansible.builtin.assert: ansible.builtin.assert:
that: that:
- result is not changed - result is not changed
# Validate backwards compatible behavior until icmp block inversion is switched from string to boolean type
- name: Icmp block inversion enabled when icmp block inversion is non-boolean string and state is enabled
block:
- name: Testing enable icmp block inversion
ansible.posix.firewalld:
zone: trusted
icmp_block_inversion: some string
permanent: true
state: enabled
register: result
- name: Assert icmp block inversion is enabled
ansible.builtin.assert:
that:
- result is changed
- name: Testing enable icmp block inversion (verify not changed)
ansible.posix.firewalld:
zone: trusted
icmp_block_inversion: some string
permanent: true
state: enabled
register: result
- name: Assert icmp block inversion is enabled (verify not changed)
ansible.builtin.assert:
that:
- result is not changed
- name: Icmp block inversion disabled when icmp block inversion is non-boolean string and state is disabled
block:
- name: Testing disable icmp block inversion
ansible.posix.firewalld:
zone: trusted
icmp_block_inversion: some string
permanent: true
state: disabled
register: result
- name: Assert icmp block inversion is disabled
ansible.builtin.assert:
that:
- result is changed
- name: Testing disable icmp block inversion (verify not changed)
ansible.posix.firewalld:
zone: trusted
icmp_block_inversion: some string
permanent: true
state: disabled
register: result
- name: Assert icmp block inversion is disabled (verify not changed)
ansible.builtin.assert:
that:
- result is not changed

View File

@@ -114,3 +114,60 @@
ansible.builtin.assert: ansible.builtin.assert:
that: that:
- result is not changed - result is not changed
# Validate backwards compatible behavior until masquerade is switched from string to boolean type
- name: Masquerade enabled when masquerade is non-boolean string and state is enabled
block:
- name: Testing enable masquerade
ansible.posix.firewalld:
zone: trusted
masquerade: some string
permanent: true
state: enabled
register: result
- name: Assert masquerade is enabled
ansible.builtin.assert:
that:
- result is changed
- name: Testing enable masquerade (verify not changed)
ansible.posix.firewalld:
zone: trusted
masquerade: some string
permanent: true
state: enabled
register: result
- name: Assert masquerade is enabled (verify not changed)
ansible.builtin.assert:
that:
- result is not changed
- name: Masquerade disabled when masquerade is non-boolean string and state is disabled
block:
- name: Testing disable masquerade
ansible.posix.firewalld:
zone: trusted
masquerade: some string
permanent: true
state: disabled
register: result
- name: Assert masquerade is disabled
ansible.builtin.assert:
that:
- result is changed
- name: Testing disable masquerade (verify not changed)
ansible.posix.firewalld:
zone: trusted
masquerade: some string
permanent: true
state: disabled
register: result
- name: Assert masquerade is disabled (verify not changed)
ansible.builtin.assert:
that:
- result is not changed

View File

@@ -1,4 +1,3 @@
# SETUP ################################################################################
- name: Install dependencies (Linux) - name: Install dependencies (Linux)
ansible.builtin.package: ansible.builtin.package:
name: e2fsprogs name: e2fsprogs
@@ -111,42 +110,6 @@
mode: '0644' mode: '0644'
register: orig_info register: orig_info
# BIND MOUNT ################################################################################
# bind mount check mode
- name: Bind mount a filesystem (Linux) (check mode)
ansible.posix.mount:
src: '{{ output_dir }}/mount_source'
name: '{{ output_dir }}/mount_dest'
state: mounted
fstype: None
opts: bind
when: ansible_system == 'Linux'
register: bind_result_linux_dry_run
check_mode: true
- name: Bind mount a filesystem (FreeBSD) (check mode)
ansible.posix.mount:
src: '{{ output_dir }}/mount_source'
name: '{{ output_dir }}/mount_dest'
state: mounted
fstype: nullfs
when: ansible_system == 'FreeBSD'
register: bind_result_freebsd_dry_run
check_mode: true
- name: Attempt to stat bind mounted file
ansible.builtin.stat:
path: '{{ output_dir }}/mount_dest/test_file'
when: ansible_system in ('FreeBSD', 'Linux')
register: dest_stat
- name: Assert the bind mount did not take place
ansible.builtin.assert:
that:
- not dest_stat['stat']['exists']
when: ansible_system in ('FreeBSD', 'Linux')
# bind mount
- name: Bind mount a filesystem (Linux) - name: Bind mount a filesystem (Linux)
ansible.posix.mount: ansible.posix.mount:
src: '{{ output_dir }}/mount_source' src: '{{ output_dir }}/mount_source'
@@ -205,48 +168,6 @@
- (ansible_system == 'Linux' and not bind_result_linux['changed']) or (ansible_system == 'FreeBSD' and not bind_result_freebsd['changed']) - (ansible_system == 'Linux' and not bind_result_linux['changed']) or (ansible_system == 'FreeBSD' and not bind_result_freebsd['changed'])
when: ansible_system in ('FreeBSD', 'Linux') when: ansible_system in ('FreeBSD', 'Linux')
# remount check mode
- name: Remount filesystem with different opts (Linux) (check mode)
ansible.posix.mount:
src: '{{ output_dir }}/mount_source'
name: '{{ output_dir }}/mount_dest'
state: mounted
fstype: None
opts: bind,ro
when: ansible_system == 'Linux'
register: bind_result_linux
check_mode: true
- name: Remount filesystem with different opts (FreeBSD) (check mode)
ansible.posix.mount:
src: '{{ output_dir }}/mount_source'
name: '{{ output_dir }}/mount_dest'
state: mounted
fstype: nullfs
opts: ro
when: ansible_system == 'FreeBSD'
register: bind_result_freebsd
check_mode: true
- name: Get mount options
ansible.builtin.shell:
cmd: set -o pipefail && mount | grep mount_dest | grep -c -E -w '(ro|read-only)'
executable: "{{ shell_executable }}"
changed_when: false
failed_when: false
register: new_options_count
- name: Make sure the filesystem does not have the new opts
ansible.builtin.assert:
that:
- linux_and_changed or freebsd_and_changed
- new_options_count.stdout | int == 0
vars:
linux_and_changed: "{{ ansible_system == 'Linux' and bind_result_linux_dry_run['changed'] }}"
freebsd_and_changed: "{{ ansible_system == 'FreeBSD' and bind_result_freebsd['changed'] }}"
when: ansible_system in ('FreeBSD', 'Linux')
# remount
- name: Remount filesystem with different opts (Linux) - name: Remount filesystem with different opts (Linux)
ansible.posix.mount: ansible.posix.mount:
src: '{{ output_dir }}/mount_source' src: '{{ output_dir }}/mount_source'
@@ -282,29 +203,6 @@
- 1 == remount_options.stdout_lines | length - 1 == remount_options.stdout_lines | length
when: ansible_system in ('FreeBSD', 'Linux') when: ansible_system in ('FreeBSD', 'Linux')
# unmount check mode
- name: Unmount the bind mount (check mode)
ansible.posix.mount:
name: '{{ output_dir }}/mount_dest'
state: absent
when: ansible_system in ('Linux', 'FreeBSD')
register: unmount_result
check_mode: true
- name: Make sure the file still exists in dest
ansible.builtin.stat:
path: '{{ output_dir }}/mount_dest/test_file'
when: ansible_system in ('FreeBSD', 'Linux')
register: dest_stat
- name: Check that we did not unmount
ansible.builtin.assert:
that:
- unmount_result['changed']
- dest_stat['stat']['exists']
when: ansible_system in ('FreeBSD', 'Linux')
# unmount
- name: Unmount the bind mount - name: Unmount the bind mount
ansible.posix.mount: ansible.posix.mount:
name: '{{ output_dir }}/mount_dest' name: '{{ output_dir }}/mount_dest'
@@ -325,36 +223,9 @@
- not dest_stat['stat']['exists'] - not dest_stat['stat']['exists']
when: ansible_system in ('FreeBSD', 'Linux') when: ansible_system in ('FreeBSD', 'Linux')
# SWAP ############################################################# - name: Block to test remounted option
- name: Swap
when: ansible_system in ('Linux') when: ansible_system in ('Linux')
block: block:
# mount swap check mode
- name: Stat /etc/fstab
ansible.builtin.stat:
path: /etc/fstab
register: stat_fstab_before
- name: Create fstab record for the first swap file (check mode)
ansible.posix.mount:
name: none
src: /tmp/swap1
opts: sw
fstype: swap
state: present
check_mode: true
- name: Stat /etc/fstab
ansible.builtin.stat:
path: /etc/fstab
register: stat_fstab_after
- name: Assert that fstab checksum did not change
ansible.builtin.assert:
that:
- stat_fstab_before.stat.checksum == stat_fstab_after.stat.checksum
# mount swap1
- name: Create fstab record for the first swap file - name: Create fstab record for the first swap file
ansible.posix.mount: ansible.posix.mount:
name: none name: none
@@ -379,7 +250,6 @@
- swap1_created['changed'] - swap1_created['changed']
- not swap1_created_again['changed'] - not swap1_created_again['changed']
# mount swap2
- name: Create fstab record for the second swap file - name: Create fstab record for the second swap file
ansible.posix.mount: ansible.posix.mount:
name: none name: none
@@ -404,30 +274,6 @@
- swap2_created['changed'] - swap2_created['changed']
- not swap2_created_again['changed'] - not swap2_created_again['changed']
# remove swap check mode
- name: Stat /etc/fstab
ansible.builtin.stat:
path: /etc/fstab
register: stat_fstab_before
- name: Remove the fstab record for the first swap file (check mode)
ansible.posix.mount:
name: none
src: /tmp/swap1
state: absent
check_mode: true
- name: Stat /etc/fstab
ansible.builtin.stat:
path: /etc/fstab
register: stat_fstab_after
- name: Assert that fstab checksum did not change
ansible.builtin.assert:
that:
- stat_fstab_before.stat.checksum == stat_fstab_after.stat.checksum
# remove swap1
- name: Remove the fstab record for the first swap file - name: Remove the fstab record for the first swap file
ansible.posix.mount: ansible.posix.mount:
name: none name: none
@@ -448,7 +294,6 @@
- swap1_removed['changed'] - swap1_removed['changed']
- not swap1_removed_again['changed'] - not swap1_removed_again['changed']
# remove swap2
- name: Remove the fstab record for the second swap file - name: Remove the fstab record for the second swap file
ansible.posix.mount: ansible.posix.mount:
name: none name: none
@@ -469,10 +314,6 @@
- swap2_removed['changed'] - swap2_removed['changed']
- not swap2_removed_again['changed'] - not swap2_removed_again['changed']
# FIXUP #############################################################
- name: Fix incomplete entry already present in fstab
when: ansible_system == 'Linux'
block:
- name: Create fstab record with missing last two fields - name: Create fstab record with missing last two fields
ansible.builtin.copy: ansible.builtin.copy:
dest: /etc/fstab dest: /etc/fstab
@@ -502,11 +343,6 @@
- ''' 0 0'' in optional_fields_content.stdout' - ''' 0 0'' in optional_fields_content.stdout'
- 1 == optional_fields_content.stdout_lines | length - 1 == optional_fields_content.stdout_lines | length
# REMOUNTED #############################################################
- name: Block to test remounted option
when: ansible_system in ('Linux')
block:
# setup
- name: Create empty file - name: Create empty file
community.general.filesize: community.general.filesize:
path: /tmp/myfs.img path: /tmp/myfs.img
@@ -536,26 +372,6 @@
ansible.builtin.pause: ansible.builtin.pause:
seconds: 2 seconds: 2
# remount check mode
- name: Remount (check mode)
ansible.posix.mount:
path: /tmp/myfs
state: remounted
- name: Get again the last write time
ansible.builtin.shell:
cmd: >-
set -o pipefail && dumpe2fs /tmp/myfs.img 2>/dev/null | grep -i "last write time:" |cut -d: -f2-
executable: "{{ shell_executable }}"
changed_when: false
register: last_write_time_check
- name: Fail if they are different
ansible.builtin.fail:
msg: Filesytem was remounted, testing of the module failed!
when: last_write_time.stdout != last_write_time_check.stdout
# remount
- name: Test if the FS is remounted - name: Test if the FS is remounted
ansible.posix.mount: ansible.posix.mount:
path: /tmp/myfs path: /tmp/myfs
@@ -574,29 +390,6 @@
msg: Filesytem was not remounted, testing of the module failed! msg: Filesytem was not remounted, testing of the module failed!
when: last_write is defined and last_write_time2 is defined and last_write_time.stdout == last_write_time2.stdout when: last_write is defined and last_write_time2 is defined and last_write_time.stdout == last_write_time2.stdout
# remount different options check mode
- name: Remount filesystem with different opts using remounted option (Linux only)
ansible.posix.mount:
path: /tmp/myfs
state: remounted
opts: rw,noexec
check_mode: true
- name: Get remounted options (Linux only)
ansible.builtin.shell:
cmd: set -o pipefail && mount | grep myfs | grep -E -w 'noexec' | wc -l
executable: "{{ shell_executable }}"
failed_when: false
changed_when: false
register: remounted_options
- name: Make sure the filesystem now has the new opts after using remounted (Linux only)
ansible.builtin.assert:
that:
- "'0' in remounted_options.stdout"
- "1 == remounted_options.stdout_lines | length"
# remount different options
- name: Remount filesystem with different opts using remounted option (Linux only) - name: Remount filesystem with different opts using remounted option (Linux only)
ansible.posix.mount: ansible.posix.mount:
path: /tmp/myfs path: /tmp/myfs
@@ -616,7 +409,6 @@
- "'1' in remounted_options.stdout" - "'1' in remounted_options.stdout"
- "1 == remounted_options.stdout_lines | length" - "1 == remounted_options.stdout_lines | length"
# backup
- name: Mount the FS again to test backup - name: Mount the FS again to test backup
ansible.posix.mount: ansible.posix.mount:
path: /tmp/myfs path: /tmp/myfs
@@ -647,11 +439,9 @@
- /tmp/myfs.img - /tmp/myfs.img
- /tmp/myfs - /tmp/myfs
# BOOT #############################################################
- name: Block to test boot option for Linux - name: Block to test boot option for Linux
when: ansible_system in ('Linux') when: ansible_system in ('Linux')
block: block:
# setup
- name: Create empty file - name: Create empty file
community.general.filesize: community.general.filesize:
path: /tmp/myfs.img path: /tmp/myfs.img
@@ -662,7 +452,6 @@
fstype: ext3 fstype: ext3
dev: /tmp/myfs.img dev: /tmp/myfs.img
# noauto
- name: Mount the FS with noauto option - name: Mount the FS with noauto option
ansible.posix.mount: ansible.posix.mount:
path: /tmp/myfs path: /tmp/myfs
@@ -683,7 +472,6 @@
path: /tmp/myfs path: /tmp/myfs
state: absent state: absent
# noauto + defaults
- name: Mount the FS with noauto option and defaults - name: Mount the FS with noauto option and defaults
ansible.posix.mount: ansible.posix.mount:
path: /tmp/myfs path: /tmp/myfs
@@ -711,7 +499,6 @@
- /tmp/myfs.img - /tmp/myfs.img
- /tmp/myfs - /tmp/myfs
# NEWLINE END OF FILE ############################################
- name: Block to test missing newline at the EOF of fstab - name: Block to test missing newline at the EOF of fstab
when: ansible_system in ('Linux') when: ansible_system in ('Linux')
block: block:
@@ -750,7 +537,6 @@
- /tmp/myfs1 - /tmp/myfs1
- /tmp/test_fstab - /tmp/test_fstab
# EPHEMERAL ################################################
- name: Block to test ephemeral option - name: Block to test ephemeral option
environment: environment:
PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
@@ -766,7 +552,8 @@
path: /tmp/myfs_B.img path: /tmp/myfs_B.img
size: 20M size: 20M
##### FORMAT FS ON LINUX ##### FORMAT FS ON LINUX
- name: Block to format FS on Linux - name: Block to format FS on Linux
when: ansible_system == 'Linux' when: ansible_system == 'Linux'
block: block:
@@ -780,7 +567,8 @@
fstype: ext3 fstype: ext3
dev: /tmp/myfs_B.img dev: /tmp/myfs_B.img
##### FORMAT FS ON SOLARIS AND BSD ##### FORMAT FS ON SOLARIS AND BSD
- name: Create loop devices on Solaris and BSD - name: Create loop devices on Solaris and BSD
ansible.builtin.shell: ansible.builtin.shell:
cmd: "set -o pipefail && {{ ephemeral_create_loop_dev_cmd }}" cmd: "set -o pipefail && {{ ephemeral_create_loop_dev_cmd }}"
@@ -795,49 +583,14 @@
changed_when: true changed_when: true
when: ephemeral_format_fs_cmd is defined when: ephemeral_format_fs_cmd is defined
##### TESTS
- name: Create fstab if it does not exist - name: Create fstab if it does not exist
ansible.builtin.file: ansible.builtin.file:
path: "{{ ephemeral_fstab }}" path: "{{ ephemeral_fstab }}"
state: touch state: touch
mode: '0644' mode: '0644'
# normal ephemeral mount check mode
- name: Get checksum of /etc/fstab before mounting anything
ansible.builtin.stat:
path: '{{ ephemeral_fstab }}'
register: fstab_stat_before_mount
- name: Mount the FS A with ephemeral state (check mode)
ansible.posix.mount:
path: /tmp/myfs
src: '{{ ephemeral_device_a }}'
fstype: '{{ ephemeral_fstype }}'
opts: rw
state: ephemeral
register: ephemeral_mount_info
check_mode: true
- name: Get checksum of /etc/fstab after an ephemeral mount
ansible.builtin.stat:
path: '{{ ephemeral_fstab }}'
register: fstab_stat_after_mount
- name: Get mountinfo
ansible.builtin.shell:
cmd: grep -c '/tmp/myfs' <(mount -v)
executable: "{{ shell_executable }}"
register: check_mountinfo
failed_when: false
changed_when: false
- name: Assert the mount occurred and the fstab is unchanged
ansible.builtin.assert:
that:
- check_mountinfo.stdout|int == 0
- ephemeral_mount_info['changed']
- fstab_stat_before_mount['stat']['checksum'] == fstab_stat_after_mount['stat']['checksum']
# normal ephemeral mount
- name: Get checksum of /etc/fstab before mounting anything - name: Get checksum of /etc/fstab before mounting anything
ansible.builtin.stat: ansible.builtin.stat:
path: '{{ ephemeral_fstab }}' path: '{{ ephemeral_fstab }}'
@@ -878,48 +631,6 @@
- ephemeral_mount_info['changed'] - ephemeral_mount_info['changed']
- fstab_stat_before_mount['stat']['checksum'] == fstab_stat_after_mount['stat']['checksum'] - fstab_stat_before_mount['stat']['checksum'] == fstab_stat_after_mount['stat']['checksum']
# remount different options check mode
- name: Get first mount record
ansible.builtin.shell:
cmd: grep '/tmp/myfs' <(mount -v)
executable: "{{ shell_executable }}"
register: ephemeral_mount_record_1
changed_when: false
- name: Try to mount FS A where FS A is already mounted (should trigger remount and changed)
ansible.posix.mount:
path: /tmp/myfs
src: '{{ ephemeral_device_a }}'
fstype: '{{ ephemeral_fstype }}'
opts: ro
state: ephemeral
register: ephemeral_mount_info
check_mode: true
- name: Get second mount record (should be different than the first)
ansible.builtin.shell:
cmd: grep '/tmp/myfs' <(mount -v)
executable: "{{ shell_executable }}"
register: ephemeral_mount_record_2
changed_when: false
- name: Get mountinfo
ansible.builtin.shell:
cmd: grep -c '/tmp/myfs' <(mount -v)
executable: "{{ shell_executable }}"
failed_when: false
register: check_mountinfo
changed_when: false
- name: Assert the FS A is still mounted, the options unchanged and the fstab unchanged
ansible.builtin.assert:
that:
- check_mountinfo.stdout|int == 1
- ephemeral_mount_record_1.stdout == ephemeral_mount_record_2.stdout
- ephemeral_mount_info['changed']
- fstab_stat_before_mount['stat']['checksum'] == fstab_stat_after_mount['stat']['checksum']
# remount different options
- name: Get first mount record - name: Get first mount record
ansible.builtin.shell: ansible.builtin.shell:
cmd: grep '/tmp/myfs' <(mount -v) cmd: grep '/tmp/myfs' <(mount -v)
@@ -959,7 +670,6 @@
- ephemeral_mount_info['changed'] - ephemeral_mount_info['changed']
- fstab_stat_before_mount['stat']['checksum'] == fstab_stat_after_mount['stat']['checksum'] - fstab_stat_before_mount['stat']['checksum'] == fstab_stat_after_mount['stat']['checksum']
# conflicting mount
- name: Try to mount file B on file A mountpoint (should fail) - name: Try to mount file B on file A mountpoint (should fail)
ansible.posix.mount: ansible.posix.mount:
path: /tmp/myfs path: /tmp/myfs
@@ -997,39 +707,6 @@
- test_file_stat['stat']['exists'] - test_file_stat['stat']['exists']
- ephemeral_mount_b_info is failed - ephemeral_mount_b_info is failed
# unmount check mode
- name: Unmount FS with state = unmounted
ansible.posix.mount:
path: /tmp/myfs
state: unmounted
check_mode: true
- name: Get fstab checksum after unmounting an ephemeral mount with state = unmounted
ansible.builtin.stat:
path: '{{ ephemeral_fstab }}'
register: fstab_stat_after_unmount
- name: Get mountinfo
ansible.builtin.shell:
cmd: grep -c '/tmp/myfs' <(mount -v)
executable: "{{ shell_executable }}"
register: check_mountinfo
failed_when: false
changed_when: false
- name: Try to stat our test file
ansible.builtin.stat:
path: /tmp/myfs/test_file
register: test_file_stat
- name: Assert that unmount did not take place and fstab unchanged
ansible.builtin.assert:
that:
- check_mountinfo.stdout|int == 1
- test_file_stat['stat']['exists']
- fstab_stat_before_mount['stat']['checksum'] == fstab_stat_after_unmount['stat']['checksum']
# unmount
- name: Unmount FS with state = unmounted - name: Unmount FS with state = unmounted
ansible.posix.mount: ansible.posix.mount:
path: /tmp/myfs path: /tmp/myfs
@@ -1082,7 +759,6 @@
- /tmp/myfs_B.img - /tmp/myfs_B.img
- /tmp/myfs - /tmp/myfs
# OPTS_NO_LOG ######################################
- name: Block to test opts_no_log option - name: Block to test opts_no_log option
when: ansible_system == 'Linux' when: ansible_system == 'Linux'
block: block:

View File

@@ -20,4 +20,5 @@
ansible.builtin.include_tasks: seboolean.yml ansible.builtin.include_tasks: seboolean.yml
when: when:
- ansible_selinux is defined - ansible_selinux is defined
- ansible_selinux
- ansible_selinux.status == 'enabled' - ansible_selinux.status == 'enabled'

View File

@@ -19,21 +19,23 @@
- name: Debug message for when SELinux is disabled - name: Debug message for when SELinux is disabled
ansible.builtin.debug: ansible.builtin.debug:
msg: SELinux is disabled msg: SELinux is disabled
when: ansible_selinux is defined and ansible_selinux.status == 'disabled' when: ansible_selinux is defined and not ansible_selinux
- name: Debug message for when SELinux is enabled and not disabled - name: Debug message for when SELinux is enabled and not disabled
ansible.builtin.debug: ansible.builtin.debug:
msg: SELinux is {{ ansible_selinux.status }} msg: SELinux is {{ ansible_selinux.status }}
when: ansible_selinux is defined when: ansible_selinux is defined and ansible_selinux
- name: Include_tasks for when SELinux is enabled - name: Include_tasks for when SELinux is enabled
ansible.builtin.include_tasks: selinux.yml ansible.builtin.include_tasks: selinux.yml
when: when:
- ansible_selinux is defined - ansible_selinux is defined
- ansible_selinux
- ansible_selinux.status == 'enabled' - ansible_selinux.status == 'enabled'
- name: Include tasks for selogin when SELinux is enabled - name: Include tasks for selogin when SELinux is enabled
ansible.builtin.include_tasks: selogin.yml ansible.builtin.include_tasks: selogin.yml
when: when:
- ansible_selinux is defined - ansible_selinux is defined
- ansible_selinux
- ansible_selinux.status == 'enabled' - ansible_selinux.status == 'enabled'

View File

@@ -128,8 +128,8 @@
ansible.builtin.assert: ansible.builtin.assert:
that: that:
- selinux_config_original | length == selinux_config_after | length - selinux_config_original | length == selinux_config_after | length
- (selinux_config_after | select("search", "^SELINUX=disabled\s*$") | list | length) > 0 - selinux_config_after[selinux_config_after.index('SELINUX=disabled')] is search("^SELINUX=\w+$")
- (selinux_config_after | select("search", "^SELINUXTYPE=targeted\s*$") | list | length) > 0 - selinux_config_after[selinux_config_after.index('SELINUXTYPE=targeted')] is search("^SELINUXTYPE=\w+$")
- name: TEST 1 | Disable SELinux again, with kernel arguments update - name: TEST 1 | Disable SELinux again, with kernel arguments update
ansible.posix.selinux: ansible.posix.selinux:

View File

@@ -0,0 +1,2 @@
tests/utils/shippable/check_matrix.py replace-urlopen
tests/utils/shippable/timing.py shebang

View File

@@ -0,0 +1,2 @@
tests/utils/shippable/check_matrix.py replace-urlopen
tests/utils/shippable/timing.py shebang

View File

@@ -0,0 +1 @@
tests/utils/shippable/timing.py shebang

View File

@@ -0,0 +1 @@
tests/utils/shippable/timing.py shebang

View File

@@ -0,0 +1 @@
tests/utils/shippable/timing.py shebang

View File

@@ -0,0 +1 @@
tests/utils/shippable/timing.py shebang

View 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
View 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
View 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)

View 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)

View 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)

View 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}

View 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))

View File

@@ -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,

View 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)

View File

@@ -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

View File

@@ -62,15 +62,15 @@ else
retry pip install "https://github.com/ansible/ansible/archive/stable-${ansible_version}.tar.gz" --disable-pip-version-check retry pip install "https://github.com/ansible/ansible/archive/stable-${ansible_version}.tar.gz" --disable-pip-version-check
fi fi
export ANSIBLE_COLLECTIONS_PATH="${PWD}/../../../" export ANSIBLE_COLLECTIONS_PATHS="${PWD}/../../../"
# START: HACK install dependencies # START: HACK install dependencies
if [ "${ansible_version}" == "2.9" ] || [ "${ansible_version}" == "2.10" ]; then if [ "${ansible_version}" == "2.9" ] || [ "${ansible_version}" == "2.10" ]; then
# Note: Since community.general 5.x, Ansible Core versions prior to 2.11 are not supported. # Note: Since community.general 5.x, Ansible Core versions prior to 2.11 are not supported.
# So we need to use 4.8.1 for Ansible 2.9 and Ansible Engine 2.10. # So we need to use 4.8.1 for Ansible 2.9 and Ansible Engine 2.10.
retry git clone --depth=1 --single-branch -b 4.8.1 https://github.com/ansible-collections/community.general.git "${ANSIBLE_COLLECTIONS_PATH}/ansible_collections/community/general" retry git clone --depth=1 --single-branch -b 4.8.1 https://github.com/ansible-collections/community.general.git "${ANSIBLE_COLLECTIONS_PATHS}/ansible_collections/community/general"
else else
retry git clone --depth=1 --single-branch https://github.com/ansible-collections/community.general.git "${ANSIBLE_COLLECTIONS_PATH}/ansible_collections/community/general" retry git clone --depth=1 --single-branch https://github.com/ansible-collections/community.general.git "${ANSIBLE_COLLECTIONS_PATHS}/ansible_collections/community/general"
fi fi
# Note: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429) # Note: we're installing with git to work around Galaxy being a huge PITA (https://github.com/ansible/galaxy/issues/2429)
# END: HACK # END: HACK

View File

@@ -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