15 Commits

Author SHA1 Message Date
Andrew Klychkov
692b906b82 chore: remove .github/BOTMETA.yml (#706) 2026-02-25 09:38:38 +01:00
Andrew Klychkov
aece4a9632 ci: add certification.yml GitHub workflow (#705) 2026-02-25 09:38:02 +01:00
softwarefactory-project-zuul[bot]
2cd1a6e4ab Merge pull request #704 from Andersson007/update_ci0
ci: .azure-pipelines/azure-pipelines.yml update distros

SUMMARY
ci: .azure-pipelines/azure-pipelines.yml update distros
As were reported in https://forum.ansible.com/t/ansible-test-images-and-vms-update-devel-2-20-2-19-2-18/45080
ISSUE TYPE


CI

Reviewed-by: Hideki Saito <saito@fgrep.org>
2026-02-25 08:19:39 +00:00
Andrew Klychkov
8af0b227cc ci: .azure-pipelines/azure-pipelines.yml update distros 2026-02-25 08:47:31 +01:00
softwarefactory-project-zuul[bot]
5f44339fa5 Merge pull request #693 from saito-hideki/pr/ci_2025120500
[CI] Update AZP CI matrix and sanity tests

SUMMARY

Update AZP CI matrix. Bump the remote target version for 2.16 and 2.17
Add ignore file for Ansible Core 2.21 for the current devel version sanity test

ISSUE TYPE

CI tests Pull Request

COMPONENT NAME

ansible.posix

ADDITIONAL INFORMATION
None
2025-12-09 05:56:49 +00:00
Hideki Saito
7d5aef07e2 Update AZP CI matrix and sanity test
* Update AZP CI matrix
* Add ignore file for Ansible Core 2.21
* Remove ignore lines for ansible-bad-import-from in 2.20 sanity tests

Signed-off-by: Hideki Saito <saito@fgrep.org>
2025-12-09 05:23:05 +00:00
softwarefactory-project-zuul[bot]
b39ee97ccc Merge pull request #677 from shenxianpeng/patch-1
docs: fix broken badge and restore coverage badge

SUMMARY
Replaced the outdated Shippable badge and active Codecov coverage badge, like other repos in ansible-collections org
ISSUE TYPE


Docs Pull Request

COMPONENT NAME

ADDITIONAL INFORMATION

Reviewed-by: Hideki Saito <saito@fgrep.org>
2025-11-28 07:14:56 +00:00
softwarefactory-project-zuul[bot]
72a6eb9729 Merge pull request #639 from Klaas-/Klaas-fix_authorized_key
Fixes #462 notice permission denied on authorized_key module

SUMMARY
As of right now the authorized_key module does not notice on an "absent" if a authorized_keys file is simply not readable to the executing user. I am trying to fix that
ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME
authorized_key
ADDITIONAL INFORMATION


Execute as a user that does not have access to the root users authorized keys file

- name: Delete key from root user
  ansible.posix.authorized_key:
    state: absent
    user: root
    key: ssh-rsa xxxxxxxx

- name: Delete key from root user
  become: true
  ansible.posix.authorized_key:
    state: absent
    user: root
    key: ssh-rsa xxxxxxxx

The one without become will succeed before my change and will fail with a permission denied error after my change. The 2nd task will actually remove a key from root user if become privileges are available for the executing user

Reviewed-by: Brian Coca
Reviewed-by: Klaas Demter
Reviewed-by: Felix Fontein <felix@fontein.de>
Reviewed-by: Hideki Saito <saito@fgrep.org>
2025-11-28 03:25:21 +00:00
Klaas Demter
9651a19805 change result.failed==True to result is failed in check_permissions.yml
Co-authored-by: Felix Fontein <felix@fontein.de>
2025-10-22 08:29:46 +02:00
Klaas Demter
413ab782a8 Fixes #462 notice permission denied on authorized_key module 2025-10-21 10:00:12 +02:00
softwarefactory-project-zuul[bot]
9343c6f56f Merge pull request #682 from saito-hideki/pr/ci_update_20250929
Ignore pylint errors caused by compatibility checks for six

SUMMARY
Ignore pylint errors caused by compatibility checks for six:

pylint:ansible-bad-import-from

Ansible Core 2.16 supports Python2 environment,  and six is required to maintain compatibility with Python 2.
We plan to continue supporting Ansible Core 2.16 at this time.
Additionally, removing the standalone ansible-lint test because it is already included in ansible-test sanity.
ISSUE TYPE

CI tests Request

COMPONENT NAME

ansible.posix

ADDITIONAL INFORMATION
None

Reviewed-by: Andrew Klychkov <aklychko@redhat.com>
Reviewed-by: Felix Fontein <felix@fontein.de>
Reviewed-by: Hideki Saito <saito@fgrep.org>
2025-10-02 05:55:28 +00:00
saito-hideki
9dc73a686a Ignore pylint errors caused by compatibility checks for six
* This is a temporary measure until we stop covering Python2
* Skipped sanity[cannot-ignore] to keep backward compatibility with Python2
* Consolidate all ansible-lint option locations into .ansible-lint
* Fixed some typos

Signed-off-by: saito-hideki <saito@fgrep.org>
2025-10-02 14:02:56 +09:00
softwarefactory-project-zuul[bot]
6da1331018 Merge pull request #670 from felixfontein/deprecations
Use module.warn() instead of returning warnings

SUMMARY
Returning warnings as warnings has been deprecated.
Ref: #635.
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME
firewalld_info
mount

Reviewed-by: Hideki Saito <saito@fgrep.org>
2025-08-16 01:03:30 +00:00
Xianpeng Shen
cda2e0657f docs: fix broken badge and restore coverage badge 2025-08-14 14:33:30 +03:00
Felix Fontein
ab8dfefd90 Use module.warn() instead of returning warnings. 2025-08-06 06:49:32 +02:00
19 changed files with 221 additions and 568 deletions

View File

@@ -3,23 +3,13 @@
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2024, Ansible Project
# Use a more permissive profile due to documentation parsing issues
profile: min
skip_list:
- meta-runtime[unsupported-version] # This rule doesn't make any sense
- fqcn[deep] # This rule produces false positives for files in tests/unit/plugins/action/fixtures/
- no-relative-paths # Temporary skip due to documentation parsing issue
- parser-error # Skip documentation parsing errors
- syntax-check # Skip syntax check issues in documentation
- load-failure # Skip module loading failures during documentation parsing
- args # Skip argument validation errors in documentation
- sanity[cannot-ignore] # This rule is skipped to keep backward compatibility with Python 2
exclude_paths:
- changelogs/
# Enable specific rules we want to keep
enable_list:
- yaml
- name
- var-naming
- .github/
- tests/
- meta/

View File

@@ -43,7 +43,7 @@ pool: Standard
stages:
- stage: Sanity_devel
displayName: Ansible devel sanity
displayName: Ansible devel Sanity & Units & Lint
dependsOn: []
jobs:
- template: templates/matrix.yml
@@ -57,8 +57,25 @@ stages:
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 sanitay & Units & Lint
displayName: Ansible 2.19 Sanity & Units & Lint
dependsOn: []
jobs:
- template: templates/matrix.yml
@@ -72,8 +89,9 @@ stages:
test: units
- name: Lint
test: lint
- stage: Sanity_2_18
displayName: Ansible 2.18 sanity & Units & Lint
displayName: Ansible 2.18 Sanity & Units & Lint
dependsOn: []
jobs:
- template: templates/matrix.yml
@@ -87,8 +105,9 @@ stages:
test: units
- name: Lint
test: lint
- stage: Sanity_2_17
displayName: Ansible 2.17 sanity & Units & Lint
displayName: Ansible 2.17 Sanity & Units & Lint
dependsOn: []
jobs:
- template: templates/matrix.yml
@@ -102,19 +121,7 @@ stages:
test: units
- name: Lint
test: lint
- stage: Sanity_2_16
displayName: Ansible 2.16 sanity & Units & Lint
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: "{0}"
testFormat: 2.16/{0}
targets:
- name: Sanity
test: sanity
- name: Units
test: units
## Docker
- stage: Docker_devel
displayName: Docker devel
@@ -123,6 +130,21 @@ stages:
- template: templates/matrix.yml
parameters:
testFormat: devel/linux/{0}/1
targets:
- name: Fedora 43
test: fedora43
- 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
@@ -130,6 +152,7 @@ stages:
test: ubuntu2204
- name: Ubuntu 24.04
test: ubuntu2404
- stage: Docker_2_19
displayName: Docker 2.19
dependsOn: []
@@ -144,6 +167,7 @@ stages:
test: ubuntu2204
- name: Ubuntu 24.04
test: ubuntu2404
- stage: Docker_2_18
displayName: Docker 2.18
dependsOn: []
@@ -158,6 +182,7 @@ stages:
test: ubuntu2204
- name: Ubuntu 24.04
test: ubuntu2404
- stage: Docker_2_17
displayName: Docker 2.17
dependsOn: []
@@ -170,20 +195,6 @@ stages:
test: fedora39
- name: Ubuntu 22.04
test: ubuntu2204
- stage: Docker_2_16
displayName: Docker 2.16
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.16/linux/{0}/1
targets:
- name: CentOS 7
test: centos7
- name: Fedora 38
test: fedora38
- name: Ubuntu 22.04
test: ubuntu2204
## Remote
- stage: Remote_devel
@@ -194,14 +205,32 @@ stages:
parameters:
testFormat: devel/{0}/1
targets:
- name: RHEL 10.0
test: rhel/10.0
- name: RHEL 9.6
test: rhel/9.6
- 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 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: []
@@ -210,14 +239,15 @@ stages:
parameters:
testFormat: 2.19/{0}/1
targets:
- name: RHEL 10.0
test: rhel/10.0
- name: RHEL 9.5
test: rhel/9.5
- 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
displayName: Remote 2.18
dependsOn: []
@@ -226,10 +256,13 @@ stages:
parameters:
testFormat: 2.18/{0}/1
targets:
- name: RHEL 9.4
test: rhel/9.4
- name: RHEL 10.1
test: rhel/10.1
- name: RHEL 9.7
test: rhel/9.7
- name: FreeBSD 13.5
test: freebsd/13.5
- stage: Remote_2_17
displayName: Remote 2.17
dependsOn: []
@@ -238,31 +271,17 @@ stages:
parameters:
testFormat: 2.17/{0}/1
targets:
- name: RHEL 9.3
test: rhel/9.3
# 2.17 remote target doesn't have RHEL 9 image
- name: RHEL 10.0
test: rhel/10.0
- name: FreeBSD 13.5
test: freebsd/13.5
- stage: Remote_2_16
displayName: Remote 2.16
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.16/{0}/1
targets:
- name: RHEL 8.8
test: rhel/8.8
- name: RHEL 9.2
test: rhel/9.2
## Finally
- stage: Summary
condition: succeededOrFailed()
dependsOn:
- Sanity_2_16
- Remote_2_16
- Docker_2_16
- Sanity_2_17
- Remote_2_17
- Docker_2_17
@@ -272,6 +291,9 @@ stages:
- Sanity_2_19
- Remote_2_19
- Docker_2_19
- Sanity_2_20
- Remote_2_20
- Docker_2_20
- Sanity_devel
- Remote_devel
- Docker_devel

52
.github/BOTMETA.yml vendored
View File

@@ -1,52 +0,0 @@
---
automerge: false
files:
$module_utils/mount.py:
labels: mount
$modules/acl.py:
authors: astorije bcoca
labels: acl
ignore: astorije
$modules/at.py:
authors: risaacson
labels: at
$modules/authorized_key.py:
authors: ansible
labels: authorized_key
$modules/mount.py:
authors: ansible skvidal
maintainers: jtyr
labels: mount
ignore: skvidal
$modules/patch.py:
authors: jirutka luisperlaz
$modules/seboolean.py:
authors: sfromm
labels: seboolean
$modules/selinux.py:
authors: goozbach
maintainers: samdoran
labels: selinux
$modules/synchronize.py:
authors: tima
labels: synchronize
$modules/sysctl.py:
authors: davixx
maintainers: Akasurde
labels: sysctl
$plugins/:
labels: profile
$plugins/debug.py:
labels: debug
$plugins/patch.py:
labels: patch
$plugins/synchronize.py:
labels: synchronize
$plugins/timer.py:
macros:
actions: plugins/action
callbacks: plugins/callback
module_utils: plugins/module_utils
modules: plugins/modules
plugins: plugins/plugins
shells: plugins/shell

35
.github/workflows/certification.yml vendored Normal file
View File

@@ -0,0 +1,35 @@
---
# This workflow calls the latest version of the
# reusable workflow.
# You can copy this file into your respository if
# you want to check against pinned versions of
# Automation Hub tests.
name: Run collection certification checks
on:
pull_request:
branches: [main]
workflow_dispatch:
schedule:
- cron: '0 6 * * *'
concurrency:
group: cert-ver-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
# Files that are not related to the core functionality
# of your collection can cause Ansible Lint to fail.
# If this happens, add an .ansible-lint file that includes
# those files and directories to the root of your
# repository; for example:
# https://github.com/ansible-collections/partner-certification-checker/blob/main/.ansible-lint
# https://github.com/ansible-collections/partner-certification-checker/blob/main/.ansible-lint
# If there are sanity test failures that cannot be fixed and are allowed to ignore
# https://docs.ansible.com/projects/lint/rules/sanity/, create a sanity ignore file
# https://docs.ansible.com/projects/ansible/devel/dev_guide/testing/sanity/ignores.html#ignore-file-location
# for each affected version of ansible-core (for example, `tests/sanity/ignore-2.18.txt`) and add corresponding entries.
jobs:
call:
uses: ansible-collections/partner-certification-checker/.github/workflows/certification-reusable.yml@v0.1

View File

@@ -2,7 +2,7 @@
<!-- Add CI and code coverage badges here. Samples included below. -->
[![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)
[![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)-->
[![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/ansible.posix)](https://codecov.io/gh/ansible-collections/ansible.posix)
## Communication

View File

@@ -0,0 +1,3 @@
---
bugfixes:
- ansible.posix.authorized_key - fixes error on permission denied in authorized_key module (https://github.com/ansible-collections/ansible.posix/issues/462).

View File

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

View File

@@ -0,0 +1,4 @@
trivial:
- Updatng AZP CI matrix to ignore ansible-bad-import-from on six(https://github.com/ansible-collections/ansible.posix/pull/682).
- Skipped sanity[cannot-ignore] to keep backward compatibility with Python2.
- Consolidate all ansible-lint option locations into .ansible-lint file.

View File

@@ -0,0 +1,5 @@
---
trivial:
- AZP - Update AZP matrix to follow ansible-test changes.
- Add ignore file for Ansible Core 2.21.
- Remove ignore lines for ansible-bad-import-from in 2.20 sanity tests.

View File

@@ -225,6 +225,8 @@ import os.path
import tempfile
import re
import shlex
import errno
import traceback
from operator import itemgetter
from ansible.module_utils._text import to_native
@@ -475,16 +477,18 @@ def parsekey(module, raw_key, rank=None):
return (key, key_type, options, comment, rank)
def readfile(filename):
if not os.path.isfile(filename):
return ''
f = open(filename)
def readfile(module, filename):
try:
return f.read()
finally:
f.close()
with open(filename, 'r') as f:
return f.read()
except IOError as e:
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):
@@ -597,7 +601,7 @@ def enforce_state(module, params):
# check current state -- just get the filename, don't create file
do_write = False
params["keyfile"] = keyfile(module, user, do_write, path, manage_dir)
existing_content = readfile(params["keyfile"])
existing_content = readfile(module, params["keyfile"])
existing_keys = parsekeys(module, existing_content)
# Add a place holder for keys that should exist in the state=present and

View File

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

View File

@@ -279,7 +279,7 @@ def _set_mount_save_old(module, args):
old_lines = []
exists = False
changed = False
escaped_args = dict([(k, _escape_fstab(v)) for k, v in iteritems(args) if k != 'warnings'])
escaped_args = dict([(k, _escape_fstab(v)) for k, v in iteritems(args)])
new_line = '%(src)s %(name)s %(fstype)s %(opts)s %(dump)s %(passno)s\n'
if platform.system() == 'SunOS':
@@ -804,7 +804,6 @@ def main():
passno='-',
fstab=module.params['fstab'],
boot='yes' if module.params['boot'] else 'no',
warnings=[]
)
if args['fstab'] is None:
args['fstab'] = '/etc/vfstab'
@@ -816,7 +815,6 @@ def main():
passno='0',
fstab=module.params['fstab'],
boot='yes',
warnings=[]
)
if args['fstab'] is None:
args['fstab'] = '/etc/fstab'
@@ -834,8 +832,7 @@ def main():
linux_mounts = get_linux_mounts(module)
if linux_mounts is None:
args['warnings'].append('Cannot open file /proc/self/mountinfo.'
' Bind mounts might be misinterpreted.')
module.warn('Cannot open file /proc/self/mountinfo. Bind mounts might be misinterpreted.')
# Override defaults with user specified params
for key in ('src', 'fstype', 'passno', 'opts', 'dump', 'fstab'):
@@ -847,7 +844,7 @@ def main():
# specified in 'opts', mount module will ignore 'boot'.
opts = args['opts'].split(',')
if module.params['boot'] and 'noauto' in opts:
args['warnings'].append("Ignore the 'boot' due to 'opts' contains 'noauto'.")
module.warn("Ignore the 'boot' due to 'opts' contains 'noauto'.")
elif not module.params['boot']:
args['boot'] = 'no'
opts.append('noauto')

View File

@@ -56,16 +56,6 @@ options:
- Verify token value with the sysctl command and set with C(-w) if necessary.
type: bool
default: false
system_wide:
description:
- If V(true), uses C(sysctl --system) behavior to reload all sysctl configuration files.
- This will reload configuration from C(/etc/sysctl.d/*.conf), C(/run/sysctl.d/*.conf),
C(/usr/local/lib/sysctl.d/*.conf), C(/usr/lib/sysctl.d/*.conf), C(/lib/sysctl.d/*.conf),
and C(/etc/sysctl.conf) in that order.
- If V(false), only reloads the specific sysctl file defined by O(sysctl_file).
- Only applies when O(reload) is V(true).
type: bool
default: false
author:
- David CHANIAL (@davixx)
'''
@@ -110,14 +100,6 @@ EXAMPLES = r'''
sysctl_set: true
state: present
reload: true
# Set vm.swappiness and reload all system sysctl configuration files (equivalent to sysctl --system)
- ansible.posix.sysctl:
name: vm.swappiness
value: '10'
state: present
reload: true
system_wide: true
'''
# ==============================================================
@@ -126,7 +108,6 @@ import os
import platform
import re
import tempfile
import glob
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.six import string_types
@@ -140,30 +121,17 @@ class SysctlModule(object):
# success or failure.
LANG_ENV = {'LANG': 'C', 'LC_ALL': 'C', 'LC_MESSAGES': 'C'}
# We define a variable to keep all the directories to be read, equivalent to
# (/sbin/sysctl --system) option
SYSCTL_DIRS = [
'/etc/sysctl.d/*.conf',
'/run/sysctl.d/*.conf',
'/usr/local/lib/sysctl.d/*.conf',
'/usr/lib/sysctl.d/*.conf',
'/lib/sysctl.d/*.conf',
'/etc/sysctl.conf'
]
def __init__(self, module):
self.module = module
self.args = self.module.params
self.sysctl_cmd = self.module.get_bin_path('sysctl', required=True)
self.sysctl_file = self.args['sysctl_file']
self.system_wide = self.args['system_wide']
self.proc_value = None # current token value in proc fs
self.file_value = None # current token value in file
self.file_lines = [] # all lines in the file
self.file_values = {} # dict of token values
self.system_wide_file_value = None # current token value from system-wide files
self.changed = False # will change occur
self.set_proc = False # does sysctl need to set value
@@ -193,36 +161,19 @@ class SysctlModule(object):
if thisname not in self.file_values:
self.file_values[thisname] = None
# if system_wide is enabled, also check system-wide configuration
if self.system_wide:
system_wide_values = self.read_system_wide_sysctl_files()
# If the value exists in system-wide config, use that for comparison
if thisname in system_wide_values:
self.system_wide_file_value = system_wide_values[thisname]
else:
self.system_wide_file_value = None
else:
self.system_wide_file_value = None
# update file contents with desired token/value
self.fix_lines()
# what do we need to do now?
# Determine the effective current value (system-wide takes precedence if enabled)
if self.system_wide and self.system_wide_file_value is not None:
current_file_value = self.system_wide_file_value
else:
current_file_value = self.file_values[thisname]
if current_file_value is None and self.args['state'] == "present":
if self.file_values[thisname] is None and self.args['state'] == "present":
self.changed = True
self.write_file = True
elif current_file_value is None and self.args['state'] == "absent":
elif self.file_values[thisname] is None and self.args['state'] == "absent":
self.changed = False
elif current_file_value and self.args['state'] == "absent":
elif self.file_values[thisname] and self.args['state'] == "absent":
self.changed = True
self.write_file = True
elif current_file_value != self.args['value']:
elif self.file_values[thisname] != self.args['value']:
self.changed = True
self.write_file = True
# with reload=yes we should check if the current system values are
@@ -355,25 +306,15 @@ class SysctlModule(object):
# https://github.com/ansible/ansible/issues/58158
return
else:
if self.system_wide:
for sysctl_file in self.SYSCTL_DIRS:
for conf_file in glob.glob(sysctl_file):
sysctl_args = [self.sysctl_cmd, '-p', conf_file]
if self.args['ignoreerrors']:
sysctl_args.insert(1, '-e')
rc, out, err = self.module.run_command(sysctl_args, environ_update=self.LANG_ENV)
if rc != 0 or self._stderr_failed(err):
self.module.fail_json(msg="Failed to reload sysctl: %s" % to_native(out) + to_native(err))
else:
# system supports reloading via the -p flag to sysctl, so we'll use that
sysctl_args = [self.sysctl_cmd, '-p', self.sysctl_file]
if self.args['ignoreerrors']:
sysctl_args.insert(1, '-e')
# system supports reloading via the -p flag to sysctl, so we'll use that
sysctl_args = [self.sysctl_cmd, '-p', self.sysctl_file]
if self.args['ignoreerrors']:
sysctl_args.insert(1, '-e')
rc, out, err = self.module.run_command(sysctl_args, environ_update=self.LANG_ENV)
rc, out, err = self.module.run_command(sysctl_args, environ_update=self.LANG_ENV)
if rc != 0 or self._stderr_failed(err):
self.module.fail_json(msg="Failed to reload sysctl: %s" % to_native(out) + to_native(err))
if rc != 0 or self._stderr_failed(err):
self.module.fail_json(msg="Failed to reload sysctl: %s" % to_native(out) + to_native(err))
# ==============================================================
# SYSCTL FILE MANAGEMENT
@@ -403,35 +344,6 @@ class SysctlModule(object):
v = v.strip()
self.file_values[k] = v.strip()
# Get the token value from all system-wide sysctl files
def read_system_wide_sysctl_files(self):
"""Read all system-wide sysctl configuration files when system_wide=True"""
system_values = {}
for sysctl_pattern in self.SYSCTL_DIRS:
for conf_file in glob.glob(sysctl_pattern):
if os.path.isfile(conf_file):
try:
with open(conf_file, "r") as read_file:
lines = read_file.readlines()
for line in lines:
line = line.strip()
# don't split empty lines or comments or line without equal sign
if not line or line.startswith(("#", ";")) or "=" not in line:
continue
k, v = line.split('=', 1)
k = k.strip()
v = v.strip()
# Later files override earlier ones (mimicking sysctl --system behavior)
system_values[k] = v.strip()
except IOError:
# Skip files that can't be read
continue
return system_values
# Fix the value in the sysctl file content
def fix_lines(self):
checked = []
@@ -489,8 +401,7 @@ def main():
reload=dict(default=True, type='bool'),
sysctl_set=dict(default=False, type='bool'),
ignoreerrors=dict(default=False, type='bool'),
sysctl_file=dict(default='/etc/sysctl.conf', type='path'),
system_wide=dict(default=False, type='bool'), # system_wide parameter
sysctl_file=dict(default='/etc/sysctl.conf', type='path')
),
supports_check_mode=True,
required_if=[('state', 'present', ['value'])],

View File

@@ -0,0 +1,41 @@
---
# -------------------------------------------------------------
# check permissions
- name: Create a file that is not accessible
ansible.builtin.file:
state: touch
path: "{{ output_dir | expanduser }}/file_permissions"
owner: root
mode: '0000'
- name: Create unprivileged user
ansible.builtin.user:
name: nopriv
create_home: true
- name: Try to delete a key from an unreadable file
become: true
become_user: nopriv
ansible.posix.authorized_key:
user: root
key: "{{ dss_key_basic }}"
state: absent
path: "{{ output_dir | expanduser }}/file_permissions"
register: result
ignore_errors: true
- name: Assert that the key deletion has failed
ansible.builtin.assert:
that:
- result is failed
- name: Remove the file
ansible.builtin.file:
state: absent
path: "{{ output_dir | expanduser }}/file_permissions"
- name: Remove the user
ansible.builtin.user:
name: nopriv
state: absent

View File

@@ -34,3 +34,6 @@
- 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

@@ -140,8 +140,8 @@
ansible.posix.sysctl:
name: test.invalid
value: 1
ignore_errors: true
register: sysctl_test3
ignore_errors: true
- name: Debug sysctl_test3
ansible.builtin.debug:
@@ -229,91 +229,6 @@
ansible.builtin.assert:
that:
- sysctl_test4 is failed
##
## sysctl --system
##
- name: Set vm.swappiness to 10 with --system option
ansible.posix.sysctl:
name: vm.swappiness
value: 10
state: present
reload: false
sysctl_set: true
system_wide: true
register: sysctl_system_test1
- name: Check with sysctl command
ansible.builtin.command: sysctl vm.swappiness
changed_when: false
register: sysctl_check_system1
- name: Debug sysctl_system_test1 sysctl_check_system1
ansible.builtin.debug:
var: item
verbosity: 1
with_items:
- "{{ sysctl_system_test1 }}"
- "{{ sysctl_check_system1 }}"
- name: Validate results for --system option
ansible.builtin.assert:
that:
- sysctl_system_test1 is changed
- "'10' in sysctl_check_system1.stdout"
# Test system_wide with reload=true
- name: Set vm.dirty_ratio to 20 with system_wide and reload=true
ansible.posix.sysctl:
name: vm.dirty_ratio
value: 20
state: present
reload: true
system_wide: true
register: sysctl_system_reload_test
- name: Check vm.dirty_ratio value
ansible.builtin.command: sysctl -n vm.dirty_ratio
changed_when: false
register: sysctl_check_dirty_ratio
- name: Validate system_wide with reload
ansible.builtin.assert:
that:
- sysctl_system_reload_test is changed
- sysctl_check_dirty_ratio.stdout == "20"
# Test system_wide=false behavior (default)
- name: Create custom sysctl file for testing
ansible.builtin.copy:
content: |
# Custom sysctl test file
vm.dirty_background_ratio=5
dest: "{{ output_dir_test }}/custom_sysctl.conf"
mode: "0644"
- name: Set vm.dirty_background_ratio with system_wide=false
ansible.posix.sysctl:
name: vm.dirty_background_ratio
value: 10
state: present
reload: true
system_wide: false
sysctl_file: "{{ output_dir_test }}/custom_sysctl.conf"
register: sysctl_system_false_test
- name: Check custom sysctl file content
ansible.builtin.command: cat {{ output_dir_test }}/custom_sysctl.conf
changed_when: false
register: custom_sysctl_content
- name: Validate system_wide=false behavior
ansible.builtin.assert:
that:
- sysctl_system_false_test is changed
- "'vm.dirty_background_ratio=10' in custom_sysctl_content.stdout"
- name: Test on RHEL VMs
when:
@@ -451,36 +366,3 @@
that:
- stat_result.stat.islnk is defined and stat_result.stat.islnk
- stat_result.stat.lnk_source == '/tmp/ansible_sysctl_test.conf'
# Test sysctl: --system
- name: Set vm.swappiness to 10 with --system option
ansible.posix.sysctl:
name: vm.swappiness
value: 10
state: present
reload: false
sysctl_set: true
system_wide: true
register: sysctl_system_test1
- name: Check with sysctl command
ansible.builtin.command: sysctl vm.swappiness
changed_when: false
register: sysctl_check_system1
- name: Debug sysctl_system_test1 sysctl_check_system1
ansible.builtin.debug:
var: item
verbosity: 1
with_items:
- "{{ sysctl_system_test1 }}"
- "{{ sysctl_check_system1 }}"
- name: Validate results for --system option
ansible.builtin.assert:
that:
- sysctl_system_test1 is changed
- sysctl_check_system1.stdout_lines == ["vm.swappiness = 10"]
- name: Include system_wide specific tests
ansible.builtin.include_tasks: system_wide_tests.yml

View File

@@ -1,203 +0,0 @@
---
# Additional tests specifically for system_wide parameter functionality
- name: Test system_wide parameter basic functionality
block:
# Test system_wide with a simple sysctl parameter
- name: Set vm.swappiness with system_wide=true (first time)
ansible.posix.sysctl:
name: vm.swappiness
value: 35
state: present
reload: false
system_wide: true
register: sysctl_system_wide_first_test
- name: Debug first test result
ansible.builtin.debug:
var: sysctl_system_wide_first_test
- name: Set vm.swappiness with system_wide=true (second time - should not change)
ansible.posix.sysctl:
name: vm.swappiness
value: 35
state: present
reload: false
system_wide: true
register: sysctl_system_wide_second_test
- name: Debug second test result
ansible.builtin.debug:
var: sysctl_system_wide_second_test
- name: Validate system_wide basic functionality
ansible.builtin.assert:
that:
- sysctl_system_wide_first_test is changed
- sysctl_system_wide_second_test is not changed
# Test system_wide with reload=true
- name: Set vm.dirty_expire_centisecs with system_wide=true and reload
ansible.posix.sysctl:
name: vm.dirty_expire_centisecs
value: 3000
state: present
reload: true
system_wide: true
register: sysctl_system_wide_reload_test
- name: Check vm.dirty_expire_centisecs value
ansible.builtin.command: sysctl -n vm.dirty_expire_centisecs
changed_when: false
register: sysctl_check_dirty_expire
- name: Validate system_wide with reload=true
ansible.builtin.assert:
that:
- sysctl_system_wide_reload_test is changed
- sysctl_check_dirty_expire.stdout == "3000"
# Test system_wide=false behavior (default)
- name: Create custom sysctl file for testing system_wide=false
ansible.builtin.copy:
content: |
# Custom sysctl test file
vm.dirty_background_ratio=5
dest: "{{ output_dir_test }}/custom_sysctl.conf"
mode: "0644"
- name: Set vm.dirty_background_ratio with system_wide=false
ansible.posix.sysctl:
name: vm.dirty_background_ratio
value: 10
state: present
reload: true
system_wide: false
sysctl_file: "{{ output_dir_test }}/custom_sysctl.conf"
register: sysctl_system_false_test
- name: Check custom sysctl file content
ansible.builtin.command: cat {{ output_dir_test }}/custom_sysctl.conf
changed_when: false
register: custom_sysctl_content
- name: Validate system_wide=false behavior
ansible.builtin.assert:
that:
- sysctl_system_false_test is changed
- "'vm.dirty_background_ratio=10' in custom_sysctl_content.stdout"
# Test system_wide with check mode
- name: Test system_wide in check mode
ansible.posix.sysctl:
name: vm.swappiness
value: 25
state: present
reload: true
system_wide: true
check_mode: true
register: sysctl_system_wide_check_mode
- name: Validate check mode works with system_wide
ansible.builtin.assert:
that:
- sysctl_system_wide_check_mode is changed
# Test system_wide with missing directories (should not fail)
- name: Test system_wide with potentially missing directories
ansible.posix.sysctl:
name: vm.overcommit_memory
value: 1
state: present
reload: true
system_wide: true
ignoreerrors: true
register: sysctl_system_wide_missing_dirs
- name: Validate system_wide handles missing directories
ansible.builtin.assert:
that:
- sysctl_system_wide_missing_dirs is not failed
- name: Test system_wide with multiple configuration files (RHEL/CentOS only)
when:
- ansible_facts.os_family == 'RedHat'
- ansible_facts.virtualization_type != 'docker'
block:
# Test that system_wide processes multiple configuration files
- name: Create test sysctl.d file
ansible.builtin.copy:
content: |
# Test system-wide sysctl reload
vm.dirty_writeback_centisecs=500
dest: /etc/sysctl.d/99-ansible-test.conf
mode: "0644"
backup: true
register: test_sysctl_file
- name: Apply setting with system_wide to test multiple file processing
ansible.posix.sysctl:
name: vm.overcommit_memory
value: 1
state: present
reload: true
system_wide: true
register: sysctl_multifile_test
- name: Verify both settings are applied
ansible.builtin.shell: |
sysctl -n vm.dirty_writeback_centisecs
sysctl -n vm.overcommit_memory
changed_when: false
register: sysctl_multifile_check
- name: Validate multiple file processing
ansible.builtin.assert:
that:
- sysctl_multifile_test is changed
- "'500' in sysctl_multifile_check.stdout"
- "'1' in sysctl_multifile_check.stdout"
- name: Cleanup test sysctl.d file
ansible.builtin.file:
path: /etc/sysctl.d/99-ansible-test.conf
state: absent
- name: Test system_wide parameter combinations
block:
# Test system_wide with sysctl_set
- name: Test system_wide with sysctl_set=true
ansible.posix.sysctl:
name: vm.swappiness
value: 15
state: present
reload: true
system_wide: true
sysctl_set: true
register: sysctl_system_wide_set_test
- name: Check vm.swappiness value after system_wide + sysctl_set
ansible.builtin.command: sysctl -n vm.swappiness
changed_when: false
register: sysctl_check_swappiness_set
- name: Validate system_wide with sysctl_set
ansible.builtin.assert:
that:
- sysctl_system_wide_set_test is changed
- sysctl_check_swappiness_set.stdout == "15"
# Test system_wide with reload=false (should not trigger system reload)
- name: Test system_wide with reload=false
ansible.posix.sysctl:
name: vm.dirty_ratio
value: 25
state: present
reload: false
system_wide: true
register: sysctl_system_wide_no_reload
- name: Validate system_wide with reload=false
ansible.builtin.assert:
that:
- sysctl_system_wide_no_reload is changed

View File

@@ -0,0 +1,10 @@
tests/utils/shippable/timing.py shebang
plugins/action/synchronize.py pylint:ansible-bad-import-from
plugins/callback/cgroup_perf_recap.py pylint:ansible-bad-import-from
plugins/modules/mount.py pylint:ansible-bad-import-from
plugins/modules/sysctl.py pylint:ansible-bad-import-from
plugins/shell/csh.py pylint:ansible-bad-import-from
plugins/shell/fish.py pylint:ansible-bad-import-from
tests/unit/mock/procenv.py pylint:ansible-bad-import-from
tests/unit/mock/yaml_helper.py pylint:ansible-bad-import-from
tests/unit/modules/conftest.py pylint:ansible-bad-import-from

View File

@@ -9,6 +9,5 @@ command -v ansible
pip install --upgrade --user pip
pip install --upgrade --user ansible-lint
PATH="${PATH/\~/${HOME}}" ansible-lint \
--exclude changelogs/ \
--profile=production
# To specify additional options, you can specify them into .ansible-lint file.
PATH="${PATH/\~/${HOME}}" ansible-lint