Compare commits

...

88 Commits
9.5.4 ... 9.5.8

Author SHA1 Message Date
Felix Fontein
d481a6b0d4 Release 9.5.8. 2025-05-19 18:08:30 +02:00
patchback[bot]
7a9253e68b [PR #10145/3daa1dec backport][stable-9] Fix TypeError caused by giving more than 2 positional arguments to CobblerXMLRPCInterface.get_system_handle() (#10157)
Fix TypeError caused by giving more than 2 positional arguments to CobblerXMLRPCInterface.get_system_handle()  (#10145)

* Update cobbler system module to also use new get_system_handle method definition

* Add changelog for bug fix for cobbler system module

(cherry picked from commit 3daa1dec0c)

Co-authored-by: umiruka <211638667+umiruka@users.noreply.github.com>
2025-05-18 22:45:04 +02:00
Felix Fontein
7945d5afbe Fix action group config. 2025-05-18 22:30:27 +02:00
Felix Fontein
c28021b662 Prepare 9.5.8 release. 2025-05-18 22:25:01 +02:00
patchback[bot]
3dd39fedd2 [PR #10128/626ee311 backport][stable-9] kdeconfig: mark end of options before sending value (#10147)
kdeconfig: mark end of options before sending value (#10128)

* mark end of options before sending value

* fix linting issue

* fragment update

(cherry picked from commit 626ee3115d)

Co-authored-by: Bob Mroczka <bob@mroczka.com>
2025-05-17 08:13:31 +02:00
patchback[bot]
6d8549f00a [PR #10097/ff0ed6f9 backport][stable-9] rundeck_acl_policy: fix project acls are put/posted to the wrong endpoint (#10150)
rundeck_acl_policy: fix project acls are put/posted to the wrong endpoint (#10097)

* Fix project acls are put/posted to the wrong endpoint

* Add changelog fragment.

* Fix 2.7 sanity errors in github

* Fix fragment extension and use 2.7 syntax in test

* Update changelogs/fragments/10097-fix-rundeck_acl_policy-project-endpoint.yml



* Fix pep8 formatting

* Add licensing to unit test

---------


(cherry picked from commit ff0ed6f912)

Co-authored-by: kjoyce77 <kevin.joyce@outlook.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2025-05-17 08:13:19 +02:00
patchback[bot]
805362f337 [PR #10104/6008e6e1 backport][stable-9] Allow running sanity and unit tests with antsibull-nox; impove testing documentation (#10152)
Allow running sanity and unit tests with antsibull-nox; impove testing documentation (#10104)

* Whitespace fixes.

* Allow to run unit and sanity tests with antsibull-nox.

* Document installation of needed collections for tests.

* Also mention other sanity tests.

(cherry picked from commit 6008e6e1a7)

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-05-17 08:13:10 +02:00
patchback[bot]
c0b5119034 [PR #10136/937d92ee backport][stable-9] pickle cache plugin, avoid extra steps in DT (#10143)
pickle cache plugin, avoid extra steps in DT (#10136)

* pickle cache plugin, avoid extra steps in DT

* clog

* Update changelogs/fragments/10136-cache-pickle-json.yml



---------


(cherry picked from commit 937d92ee25)

Co-authored-by: Brian Coca <bcoca@users.noreply.github.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2025-05-16 22:37:53 +02:00
patchback[bot]
fd8a452f22 [PR #10140/94eb385c backport][stable-9] sysrc - add integration test. value contains equals sign. (#10141)
sysrc - add integration test. value contains equals sign. (#10140)

(cherry picked from commit 94eb385c21)

Co-authored-by: Vladimir Botka <vbotka@gmail.com>
2025-05-16 22:37:41 +02:00
patchback[bot]
6d46e650b7 [PR #10129/e853a6f3 backport][stable-9] redis_info: adjust tests for Arch Linux (#10130)
redis_info: adjust tests for Arch Linux (#10129)

(cherry picked from commit e853a6f39b)

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-05-14 07:34:36 +02:00
patchback[bot]
b4468bd4c7 [PR #10121/de60ea1d backport][stable-9] Fix #10120. Split key=value where value may comprise = (#10124)
Fix #10120. Split key=value where value may comprise = (#10121)

* Fix #10120. Split key=value where value may comprise =

* Added fragment.

* Update plugins/modules/sysrc.py



* Update changelogs/fragments/10121-sysrc-fix-split-first-separator.yml



---------


(cherry picked from commit de60ea1da4)

Co-authored-by: Vladimir Botka <vbotka@gmail.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2025-05-12 22:10:09 +02:00
patchback[bot]
e2af16b03f [PR #10115/86507e8a backport][stable-9] lxc: fix unit tests (#10117)
lxc: fix unit tests (#10115)

Don't compare strings passed through set_option()/get_option() with 'is'.

(cherry picked from commit 86507e8aca)

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-05-10 15:12:36 +02:00
patchback[bot]
3abf169a2f [PR #10111/fcd2d8b7 backport][stable-9] Fix deprecation test (#10112)
Fix deprecation test (#10111)

Fix deprecation test.

(cherry picked from commit fcd2d8b7b7)

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-05-06 23:13:42 +02:00
patchback[bot]
5039265621 [PR #10106/94acd180 backport][stable-9] antsibull-nox: use community.crypto 2.x.y for ansible-core < 2.17 (#10107)
* antsibull-nox: use community.crypto 2.x.y for ansible-core < 2.17 (#10106)

Use community.crypto 2.x.y for ansible-core < 2.17.

(cherry picked from commit 94acd18052)

* community.general 9.x.y supports ansible-core >= 2.13.

---------

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-05-06 21:54:53 +02:00
patchback[bot]
b52b754a3d [PR #10096/a042721c backport][stable-9] pipx/pipx_info: fix scheduled tests (#10099)
pipx/pipx_info: fix scheduled tests (#10096)

(cherry picked from commit a042721c82)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2025-05-04 14:02:25 +02:00
patchback[bot]
9aef7ad67e [PR #10076/f3ea40db backport][stable-9] keycloak_user_rolemapping: fix diff mode (#10092)
keycloak_user_rolemapping: fix diff mode (#10076)

(cherry picked from commit f3ea40db3d)

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-05-02 06:15:43 +02:00
patchback[bot]
0e15608149 [PR #10086/60f1169d backport][stable-9] CI: Use community.crypto 2.x.y for ansible-core 2.16 and before (#10088)
CI: Use community.crypto 2.x.y for ansible-core 2.16 and before (#10086)

* Use community.crypto 2.x.y for ansible-core 2.16 and before.

* Also use stable-2 for ubuntu2004 tests.

(cherry picked from commit 60f1169d42)

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-05-01 09:17:58 +02:00
Felix Fontein
844e3a581c [stable-9] nmcli: fix misspelled option in example (#10075) (#10085)
nmcli: fix misspelled option in example (#10075)

Fix misspelled option.

(cherry picked from commit d89a0bbc0e)
2025-04-30 22:32:03 +02:00
Felix Fontein
3c86bb9cda Use community.crypto's stable-2 branch in EOL CI.
(cherry picked from commit aeb668a645)
2025-04-30 07:50:44 +02:00
Felix Fontein
8222f1f064 [stable-9] crypttab: removes jijna delimiters from example using when (#10079) (#10081)
crypttab: removes jijna delimiters from example using when (#10079)

The current example includes extra jinja delimiters which
result in double-interpretation of the statement.

Fixes: #10078


(cherry picked from commit 1936fe5181)

Signed-off-by: Abhijeet Kasurde <Akasurde@redhat.com>
Co-authored-by: Abhijeet Kasurde <akasurde@redhat.com>
2025-04-29 23:14:40 +02:00
Felix Fontein
78e552469a Fix info on blanket license statement for changelog fragments.
(cherry picked from commit 8fa357e74b)
2025-04-24 22:49:51 +02:00
patchback[bot]
acdf0cdc2f [PR #10057/a720e994 backport][stable-9] Mark supervisorctl tests as unstable (#10059)
Mark supervisorctl tests as unstable (#10057)

Mark supervisorctl tests as unstable.

(cherry picked from commit a720e99482)

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-04-23 07:07:55 +02:00
patchback[bot]
1246c3357b [PR #10051/4a2920b0 backport][stable-9] Remove FreeBSD 14.0 from CI (#10053)
Remove FreeBSD 14.0 from CI (#10051)

Remove FreeBSD 14.0 from CI.

In ansible-core it has been replaced with 14.1, but we're already testing against that.
Ref: 3546111f2d

(cherry picked from commit 4a2920b0fd)

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-04-22 19:08:00 +02:00
Felix Fontein
c5f939fbc5 The next release will be 9.5.8. 2025-04-21 21:29:44 +02:00
Felix Fontein
666c07acee Release 9.5.7. 2025-04-21 21:08:31 +02:00
patchback[bot]
bcbd04a8fd [PR #10043/2a5abab7 backport][stable-9] Remove blanket skips for Python 3 in CI (#10047)
* Remove blanket skips for Python 3 in CI (#10043)

* Remove blanket skips for Python 3 in CI.

* Try to fix hg tests.

* Disable hg tests.

* Drop restriction of supervisor to <4.0.0.

This was introduced in https://github.com/ansible/ansible/pull/54935.

* Make tests work with supervisorctl 4.0.0.

According to https://supervisord.org/changes.html#id12,
"supervisorctl will now set its exit code to a non-zero value when an error condition occurs."
I'm not sure why a stopped service in 'status' constitutes an error condition,
but whatever 🤷...

* Use correct Python executable.

* Skip RHEL/macOS; diff on config write.

* Skip CentOS 7 and OpenSuSE on ansible-core 2.16.

(cherry picked from commit 2a5abab738)

* Skip OpenSuSE 15/Python 2 on ansible-core 2.13.

---------

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-04-21 16:41:03 +02:00
Felix Fontein
36cb2c22a1 [stable-9] Use antsibull-nox instead of extra sanity test runner and extra workfows (#10041)
* Use antsibull-nox instead of extra sanity test runner and extra workflows (#10022)

* Use antsibull-nox instead of extra sanity test runner and extra workflows.

* Avoid sys.argv[0].

(cherry picked from commit 3ee55c6828)

* Action group keycloak does not exist in 9.x.y.
2025-04-21 14:28:09 +02:00
patchback[bot]
419893eb65 [PR #10005/e0a283bb backport][stable-9] Fix method exists in sysrc (#10033)
Fix method exists in sysrc (#10005)

* Fix method exists.

* Add changelog fragment.

* Update the exists method to pass the present method tests.

* Replace f-string formatting.

* Update changelogs/fragments/10005-fix-method-exists-in-sysrc.yml

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>

* Add comment to the method exists.

* Update plugins/modules/sysrc.py

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>

* Update changelogs/fragments/10005-fix-method-exists-in-sysrc.yml

Co-authored-by: Felix Fontein <felix@fontein.de>

* The improved comment formatting fixed.

---------

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit e0a283bb36)

Co-authored-by: Vladimir Botka <vbotka@gmail.com>
2025-04-21 13:20:48 +02:00
patchback[bot]
2448503e8b [PR #10011/c2480730 backport][stable-9] fix: github_deploy_key check key exists on 422 (#10035)
fix: github_deploy_key check key exists on 422 (#10011)

* fix: github_deploy_key check key exists on 422

If we get a 422 response code as we add a key, check if it's because the key already exists or for another reason.

fixes: #6718

* chore: add changelog 10011-github_deploy_key-check-key-present

* chore: fix changelog fragment

* chore: fix changelog fragment

* Update changelog fragment.

---------

Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit c248073079)

Co-authored-by: Alex Garel <alex@garel.org>
2025-04-21 13:20:35 +02:00
patchback[bot]
8b1a193a49 [PR #9987/a8b97732 backport][stable-9] Fix Keycloak authentication flow configuration issues (#10017)
Fix Keycloak authentication flow configuration issues (#9987)

* Add delete_authentication_config method and integrate it into create_or_update_executions

* typo

* Sanity

* Add integration tests for keycloak_authentication module with README, tasks, and variables

* Add copyright and license information to access_token.yml

* Sanity

* Refactor Keycloak integration tests: streamline README, update access token task, and enhance variable management

* Maj changelogs fragments

---------

Co-authored-by: Andre Desrosiers <andre.desrosiers@ssss.gouv.qc.ca>
(cherry picked from commit a8b977320c)

Co-authored-by: desand01 <desrosiers.a@hotmail.com>
2025-04-19 09:33:59 +02:00
patchback[bot]
69bb4420d8 [PR #9952/1243846c backport][stable-9] improve ansible_host in proxmox inventory plugin (#10002)
improve ansible_host in proxmox inventory plugin (#9952)

* improve ansible_host in proxmox inventory plugin

I had this issue myself and found out there was already an issue thread:

https://github.com/ansible-collections/community.general/issues/5906

this fixes the issue for hope we can all benefit after this gets merged

* f string styling

* add log line for the successful address selection

* remove white space

* add changelog: 9952-proxmox-inventory-plugin-improve-ansible_host.yml

* Update changelogs/fragments/9952-proxmox-inventory-plugin-improve-ansible_host.yml

Co-authored-by: Felix Fontein <felix@fontein.de>

---------

Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 1243846c3a)

Co-authored-by: Stein van Broekhoven <stein@aapjeisbaas.nl>
2025-04-16 21:06:02 +02:00
patchback[bot]
69590f55ac [PR #9976/04137746 backport][stable-9] keycloak_client: fix idempotency regression (#9996)
keycloak_client: fix idempotency regression (#9976)

* add function to normalize kc responses

* add changelog fragment

* Update changelogs/fragments/9976-keycloak_client-fix-idempotency-regression.yml

Co-authored-by: Felix Fontein <felix@fontein.de>

* add newline to changelog fragment

---------

Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 0413774641)

Co-authored-by: gruenbauer@b1-systems.de <gruenbauer@b1-systems.de>
2025-04-14 22:51:06 +02:00
Felix Fontein
69cb9b7578 Prepare 9.5.7. 2025-04-14 22:11:16 +02:00
patchback[bot]
72e4deee9b [PR #9992/8525e420 backport][stable-9] Avoid deprecated AnsibleFilterTypeError (#9993)
Avoid deprecated AnsibleFilterTypeError (#9992)

Avoid deprecated AnsibleFilterTypeError.

(cherry picked from commit 8525e420bc)

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-04-14 21:23:23 +02:00
Felix Fontein
f12f69d2a5 [stable-9] Make ready for data tagging (#9991)
Make ready for data tagging (#9833)

* Fix dependent lookup.

* Fix ansible_type plugin utils and adjust documentation of reveal_ansible_type filter and ansible_type test.

* Fix diy callback plugin.

* Adjust to Data Tagging.

* Vendor and use internal code from ansible-core to fix YAML callback.

Ref: https://github.com/ansible/ansible/issues/84781
(cherry picked from commit 04cfce78ea)
2025-04-14 21:23:04 +02:00
patchback[bot]
ff7a8f8018 [PR #9951/02ffb6e7 backport][stable-9] update PHP apache module workaround (#9978)
update PHP apache module workaround (#9951)

* update php apache module workaround

* Update apache2_module.py

* Update apache2_module.py

* Update apache2_module.py

* add changelog fragment

* Update changelogs/fragments/9951-mod-php-identifier.yml

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>

* Update 9951-mod-php-identifier.yml

---------

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
(cherry picked from commit 02ffb6e7e3)

Co-authored-by: simonLeary42 <71396965+simonLeary42@users.noreply.github.com>
2025-04-10 07:27:01 +02:00
patchback[bot]
08cfbf4f99 [PR #9963/34b6fb74 backport][stable-9] proxmox_disk: fail gracefully if storage hasn't been provided by the user (#9967)
proxmox_disk: fail gracefully if storage hasn't been provided by the user (#9963)

Fail gracefully if storage hasn't been provided by the user.

(cherry picked from commit 34b6fb74eb)

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-04-06 14:24:04 +02:00
Felix Fontein
513ea79c19 Migrate .reuse/dep5 to REUSE.toml.
(cherry picked from commit 70b5e362f9)
2025-03-29 13:46:29 +01:00
patchback[bot]
0409f4048b [PR #9945/e5e33534 backport][stable-9] Simplify YAML callback tests (#9947)
Simplify YAML callback tests (#9945)

Simplify YAML callback tests.

(cherry picked from commit e5e335348a)

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-03-29 11:01:57 +01:00
Felix Fontein
3aa6185f09 Next expected release will be 9.5.7. 2025-03-24 22:10:59 +01:00
Felix Fontein
9a7fb38301 Release 9.5.6. 2025-03-24 21:02:34 +01:00
patchback[bot]
0b33bf4e5a [PR #9910/1fbf5d8e backport][stable-9] proxmox_vm_info: don't expect key 'template' exists in dictionary (#9934)
proxmox_vm_info: don't expect key 'template' exists in dictionary (#9910)

* don't expect key 'template' exists

* add changelog fragment

* Update changelogs/fragments/9875-proxmox-dont-expect-key-template-to-exist.yml

Co-authored-by: Felix Fontein <felix@fontein.de>

---------

Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 1fbf5d8eb4)

Co-authored-by: florianfischer91 <72799603+florianfischer91@users.noreply.github.com>
2025-03-24 05:52:45 +01:00
Felix Fontein
961a7cea8b [stable-9] The yarn module is Yarn Classic only at the moment (#9928)
The yarn module is Yarn Classic only at the moment (#9926)

The yarn module is Yarn Classic only.

(cherry picked from commit cb776e7cd5)
2025-03-23 15:15:41 +01:00
patchback[bot]
7916877179 [PR #9867/ec38a82e backport][stable-9] tests: enable copr tests (#9930)
tests: enable copr tests (#9867)

[WIP] tests: enable copr tests

Signed-off-by: Abhijeet Kasurde <Akasurde@redhat.com>
(cherry picked from commit ec38a82ef1)

Co-authored-by: Abhijeet Kasurde <akasurde@redhat.com>
2025-03-23 15:14:55 +01:00
Felix Fontein
7df07f31a6 [stable-9] Unit tests: replace mock and compat with code from community.internal_test_tools (#9923)
* Unit tests: replace mock and compat with code from community.internal_test_tools (#9921)

* Replace compat with equivalent from community.internal_test_tools.

* Replace mock with equivalent from community.internal_test_tools.

* Remove ignore.txt entries.

* Add test that's no longer present in later versions.
2025-03-22 14:32:01 +01:00
Felix Fontein
928cdaaf87 [stable-9] Use more unit test utils from community.internal_test_tools (#9920)
Use more unit test utils from community.internal_test_tools (#9918)

* Make conftest's patch_ansible_module use the context manager from .utils.

* Fix test dependencies.

* Use module mock utils from community.internal_test_tools.

* Use DataDictLoader from community.internal_test_tools.

* Use trust util from community.internal_test_tools.

(cherry picked from commit 8ab8010b6d)
2025-03-22 14:12:44 +01:00
patchback[bot]
3727bf7cd4 [PR #9880/3922b82a backport][stable-9] nmcli: fix reordering of DNS nameservers and search suffixes (#9911)
nmcli: fix reordering of DNS nameservers and search suffixes (#9880)

* nmcli: fix reordering of DNS nameservers and search suffixes

- Fixes #8724

* Update changelog fragment index in line with PR number

- Now I understand what that number is for

* Use correct changelog format for nmcli PR #9880

(cherry picked from commit 3922b82a57)

Co-authored-by: ashleyghooper <ashleyghooper@gmail.com>
2025-03-21 21:50:35 +01:00
patchback[bot]
845b13d5aa [PR #9904/e3d92491 backport][stable-9] Add caddy example to copr module (#9914)
Add caddy example to copr module (#9904)

Add caddy example to copr.py

(cherry picked from commit e3d92491a3)

Co-authored-by: Elijah Lopez <elijahllopezz@gmail.com>
2025-03-21 21:50:26 +01:00
Felix Fontein
fa3e6673d0 Prepare 9.5.6. 2025-03-21 21:07:32 +01:00
patchback[bot]
84033ec80a [PR #9900/6a2d9ccd backport][stable-9] sysrc: extend the list of FreeBSD releases where the jail test fails (#9902)
sysrc: extend the list of FreeBSD releases where the jail test fails (#9900)

Extend the list of FreeBSD releases where the jail test fails.

(cherry picked from commit 6a2d9ccd99)

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-03-18 22:14:22 +01:00
patchback[bot]
3bceabce93 [PR #9881/e5eac9fe backport][stable-9] homebrew_cask: Handle unusual brew version strings (#9888)
homebrew_cask: Handle unusual brew version strings (#9881)

* Use regex to parse unusual brew version strings

Fixes: #8432

Signed-off-by: Abhijeet Kasurde <Akasurde@redhat.com>
(cherry picked from commit e5eac9fed1)

Co-authored-by: Abhijeet Kasurde <akasurde@redhat.com>
2025-03-15 09:22:42 +01:00
patchback[bot]
0dd960d8ab [PR #9871/dd0a2cbf backport][stable-9] sudoers: display stderr raised while validation (#9884)
sudoers: display stderr raised while validation (#9871)

* sudoers: display stderr raised while validation

* Print stdout and stderr raised from sudoers validation

Fixes: #9674

Signed-off-by: Abhijeet Kasurde <Akasurde@redhat.com>

* Apply suggestions from code review

Co-authored-by: Felix Fontein <felix@fontein.de>

---------

Signed-off-by: Abhijeet Kasurde <Akasurde@redhat.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit dd0a2cbff9)

Co-authored-by: Abhijeet Kasurde <akasurde@redhat.com>
2025-03-15 07:46:11 +01:00
patchback[bot]
e1b338cf41 [PR #9694/d5add1ed backport][stable-9] ipa_host: Maintain the host certificates (#9720)
ipa_host: Maintain the host certificates (#9694)

* ipa_host: Maintain the host certificates

Fix #9693

* Add changelog fragment

* Fix changelog message

* Fix changelog message again

(cherry picked from commit d5add1ed9f)

Co-authored-by: sedrubal <sedrubal@users.noreply.github.com>
2025-03-12 18:09:35 +01:00
patchback[bot]
f2e8354229 [PR #9872/fdbc06c7 backport][stable-9] CI: Add FreeBSD 13.5 (#9873)
CI: Add FreeBSD 13.5 (#9872)

Add FreeBSD 13.5.

(cherry picked from commit fdbc06c714)

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-03-12 18:09:20 +01:00
patchback[bot]
abc435466d [PR #9846/86dea88c backport][stable-9] dnf_versionlock: add support for Fedora 41 and dnf5 (#9864)
dnf_versionlock: add support for Fedora 41 and dnf5 (#9846)

Fixes: #9556

Signed-off-by: Abhijeet Kasurde <Akasurde@redhat.com>
(cherry picked from commit 86dea88cb6)

Co-authored-by: Abhijeet Kasurde <akasurde@redhat.com>
2025-03-10 06:31:05 +01:00
patchback[bot]
3c49c096a9 [PR #9845/7d5357d7 backport][stable-9] Fix roles/policies normalization in consul_token. (#9862)
Fix roles/policies normalization in consul_token. (#9845)

* Fix roles/policies normalization in consul_token.

* Update changelogs/fragments/9845-consul_token_idempotency.yml

Co-authored-by: Felix Fontein <felix@fontein.de>

---------

Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 7d5357d74c)

Co-authored-by: Florian Apolloner <florian@apolloner.eu>
2025-03-10 06:30:50 +01:00
Felix Fontein
de754eacbc [stable-9] Fix/improve tests (#9861)
Fix/improve tests (#9859)

* Fix tests.

* Improve callback tests.

(cherry picked from commit eff25c8a6e)
2025-03-09 17:15:21 +01:00
patchback[bot]
0ccb961ff7 [PR #9853/4727fb77 backport][stable-9] cmd_runner tests: fix reliance on unspecified behavior (#9856)
cmd_runner tests: fix reliance on unspecified behavior (#9853)

Fix reliance on unspecified behavior.

(cherry picked from commit 4727fb77b3)

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-03-09 08:56:49 +01:00
patchback[bot]
c6429e7740 [PR #9850/9df84654 backport][stable-9] Improve/fix unit tests (#9851)
Improve/fix unit tests (#9850)

* Improve/fix tests.

* Fix cargo test.

(cherry picked from commit 9df8465476)

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-03-08 16:42:08 +01:00
patchback[bot]
ba7439e657 [PR #9842/c46575cf backport][stable-9] Simplify module_utils unit tests (#9843)
Simplify module_utils unit tests (#9842)

Simplify module_utils unit tests.

(cherry picked from commit c46575cf06)

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-03-07 18:33:16 +01:00
Felix Fontein
013fb9c006 [stable-9] Unit tests: make set_module_args() a context manager, and remove copies of it in some tests (#9840)
Unit tests: make set_module_args() a context manager, and remove copies of it in some tests (#9838)

Make set_module_args() a context manager, and remove copies of set_module_args().

Prepares for Data Tagging.

(cherry picked from commit a1781d09dd)
2025-03-07 07:31:42 +01:00
patchback[bot]
9a6bd80613 [PR #9819/5f48f2ca backport][stable-9] Example typo in homebrew_services.py (#9826)
Example typo in homebrew_services.py (#9819)

Maybe this was mixed up with the _brew_service_state() function? I get this error as-written:
```
fatal: [eahmm3]: FAILED! => {"changed": false, "msg": "Unsupported parameters for (community.general.homebrew_services) module: service
_state. Supported parameters include: name, path, state (formula)."}
```

(cherry picked from commit 5f48f2ca0d)

Co-authored-by: Ernie Hershey <github@ernie.org>
2025-03-03 21:30:37 +01:00
patchback[bot]
17d11cb587 [PR #9828/77dc0868 backport][stable-9] homebrew_services: skip tests on macOS 13.2 and 14.3 (#9829)
homebrew_services: skip tests on macOS 13.2 and 14.3 (#9828)

Skip tests on macOS 13.2 and 14.3.

(cherry picked from commit 77dc086896)

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-03-03 21:30:25 +01:00
patchback[bot]
933166b984 [PR #9818/3b6efd5c backport][stable-9] cloudflare_dns: handle exhausted response stream in case of http error (#9822)
cloudflare_dns: handle exhausted response stream in case of http error (#9818)

* cloudflare_dns: handle exhausted response stream in case of http error

* Update changelogs/fragments/9818-cloudflare-dns-exhausted-response.yml

Co-authored-by: Felix Fontein <felix@fontein.de>

---------

Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 3b6efd5cbc)

Co-authored-by: Kristian Heljas <11139388+kristianheljas@users.noreply.github.com>
2025-03-03 07:24:08 +01:00
patchback[bot]
162add04b9 [PR #9812/cf147b9f backport][stable-9] misc typo fix (#9815)
misc typo fix (#9812)

Signed-off-by: Abhijeet Kasurde <Akasurde@redhat.com>
(cherry picked from commit cf147b9fca)

Co-authored-by: Abhijeet Kasurde <akasurde@redhat.com>
2025-03-01 11:30:56 +01:00
patchback[bot]
faaeacfaa0 [PR #9805/dd4268e0 backport][stable-9] CI: Add macOS 15.3 (#9807)
CI: Add macOS 15.3 (#9805)

* Add macOS 15.3.

* Install setuptools on macOS 15.

(cherry picked from commit dd4268e0d9)

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-02-26 22:02:35 +01:00
Felix Fontein
bbf3cae316 Next expected release will be 9.5.6. 2025-02-24 07:04:41 +01:00
Felix Fontein
53ebbe4b94 Release 9.5.5. 2025-02-24 06:46:51 +01:00
patchback[bot]
2674e2494d [PR #9796/217a1883 backport][stable-9] locale_gen: enable tests for Arch Linux, make sure they don't even try to run on RHEL and Fedora VMs (#9797)
locale_gen: enable tests for Arch Linux, make sure they don't even try to run on RHEL and Fedora VMs (#9796)

Enable locale_gen tests for Arch Linux, make sure they don't even try to run on RHEL and Fedora VMs.

(cherry picked from commit 217a18839d)

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-02-23 15:27:01 +01:00
patchback[bot]
341f86e2bc [PR #9788/bb2c45b5 backport][stable-9] json_query filter docs: fix typo cluster2 when cluster1 is mentioned (#9792)
json_query filter docs: fix typo cluster2 when cluster1 is mentioned (#9788)

Typo cluster2 but cluster1 is mentioned

(cherry picked from commit bb2c45b5bb)

Co-authored-by: Kloppi313 <36038231+Kloppi313@users.noreply.github.com>
2025-02-21 20:50:41 +01:00
patchback[bot]
dd63fb5347 [PR #9774/ddc1ea6a backport][stable-9] Fix proxy settings for elasticsearch_plugin.py (#9785)
Fix proxy settings for elasticsearch_plugin.py (#9774)

elasticsearch_plugin: fix error when setting proxy settings

Co-authored-by: Tim Hovius <w.hovius@rechtspraak.nl>
(cherry picked from commit ddc1ea6ae4)

Co-authored-by: Tim Hovius <timhovius@gmail.com>
2025-02-20 22:27:19 +01:00
patchback[bot]
b418b2c00d [PR #9778/203c1ecf backport][stable-9] redhat_registration: use 'enable_content' D-Bus option when available (#9783)
redhat_registration: use 'enable_content' D-Bus option when available (#9778)

This makes sure that subscription-manager always enables the content for
the system right after the registration.

This is particular important on EL 10+ and Fedora 41+.

(cherry picked from commit 203c1ecfec)

Co-authored-by: Pino Toscano <ptoscano@redhat.com>
2025-02-20 22:26:59 +01:00
patchback[bot]
382c0a4af6 [PR #9106/105ae056 backport][stable-9] bugfix - Prevent passwordstore lookup to create subkey when create == false (#9779)
bugfix - Prevent passwordstore lookup to create subkey when create == false (#9106)

Fixes #9105

Apply suggestion

Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 105ae0566a)

Co-authored-by: Manuel Luzarreta <mluzarreta.pro@pm.me>
2025-02-19 22:30:22 +01:00
Felix Fontein
1a0a44d179 [stable-9] Make apache2_mod_proxy work with Python 3, half-way modern Apache 2 versions, and add basic tests (#9772)
* Make apache2_mod_proxy work with Python 3, half-way modern Apache 2 versions, and add basic tests (#9762)

* Move Apache 2 installation to setup role.

* Make module work with Python 3.

* Add basic tests.

* Add changelog fragment.

* Simplify change.

* Pass referer.

* apache2_mod_proxy: follow-up for #9762, forgot one place with find_all/findAll (#9775)

Follow-up for #9762, forgot one place.

(cherry picked from commit 8e36fd4847)
2025-02-18 21:53:18 +01:00
patchback[bot]
18e4637042 [PR #9760/d696bb7b backport][stable-9] proxmox inventory: proposal for #9710 (caching) (#9769)
proxmox inventory: proposal for #9710 (caching) (#9760)

* Proposal for #9710

* Fixed comments

* Fixed trailing whitespace

* Fixed changelog fragment

(cherry picked from commit d696bb7b89)

Co-authored-by: Dirk S. <iqt4@users.noreply.github.com>
2025-02-17 19:26:01 +01:00
Felix Fontein
fb68abd6b2 Prepare 9.5.5. 2025-02-16 20:28:09 +01:00
patchback[bot]
2d5999c579 [PR #9739/b2e2d2d3 backport][stable-9] keycloak_client: compare desired and before dicts directly in checkmode (#9758)
keycloak_client: compare desired and before dicts directly in checkmode (#9739)

* compare desired and before dicts directly in checkmode

* fix authorizationServicesEnabled being dropped by kc if unset

* only add authorizationsServicesEnabled=false if before_client exists

* add changelog fragment

* Update changelog.

---------

Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit b2e2d2d37b)

Co-authored-by: gruenbauer@b1-systems.de <gruenbauer@b1-systems.de>
2025-02-16 12:38:02 +01:00
patchback[bot]
525ed41a0a [PR #9727/910c57aa backport][stable-9] keycloak: repair integration tests by removing jinja2 templating from conditionals (#9726) (#9747)
keycloak: repair integration tests by removing jinja2 templating from conditionals (#9726) (#9727)

* fix: remove jinja2 templating from conditionals in keycloak_role module integration tests (#9726)

* fix: remove jinja2 templating in conditional in keycloak clientsecret info integration test (#9726)

This test needs a further fix; see #9744. Left for a future PR for now.

* fix: remove jinja2 templating in conditional in keycloak clientsecret regenerate integration test (#9726)

* chore: remove jinja2 templating in conditional in keycloak user federation integration test (#9726)

These instances of templating were not causing failures,
but this removes the warnings.

* chore: remove jinja2 templating in conditional in keycloak user rolemapping integration test (#9726)

These instances of templating were not causing failures,
but this removes the warnings.

* docs: add changelog fragment (#9726)

* docs: repair changelog fragment yaml (#9726)

* docs: actually repair changelog fragment yaml (#9726)

* chore: remove changelog fragment for test only pr (#9726)

(cherry picked from commit 910c57aaa0)

Co-authored-by: Mark Armstrong <markparmstrong@gmail.com>
2025-02-15 12:31:37 +01:00
patchback[bot]
4a4fe8c61f [PR #9722/d756aeb6 backport][stable-9] CI: Cleanup AZP config similarly to ansible-core did some years ago (#9724)
CI: Cleanup AZP config similarly to ansible-core did some years ago (#9722)

Cleanup AZP config similarly to ansible-core did some years ago.

(cherry picked from commit d756aeb6ce)

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-02-10 23:19:52 +01:00
patchback[bot]
f9e4bc85e9 [PR #9695/191a4d8f backport][stable-9] xml: ensure the stream object is closed in main() (#9711)
xml: ensure the stream object is closed in main() (#9695)

* ensure the stream object is closed in main()

* add changelog frag

* Update plugins/modules/xml.py

Co-authored-by: Felix Fontein <felix@fontein.de>

* Update plugins/modules/xml.py

Co-authored-by: Felix Fontein <felix@fontein.de>

---------

Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 191a4d8f63)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2025-02-09 14:26:42 +01:00
patchback[bot]
bde1c721e0 [PR #9705/efe0c464 backport][stable-9] Disable failing copr tests (#9708)
Disable failing copr tests (#9705)

Disable failing copr tests.

(cherry picked from commit efe0c464ff)

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-02-09 12:41:35 +01:00
Felix Fontein
285c97e7ea Fix typo.
(cherry picked from commit d6943c9838)
2025-02-09 08:11:06 +01:00
patchback[bot]
d45a889c3f [PR #9699/10c15d31 backport][stable-9] filesystem tests: reiserfsprogs is no longer available on Arch Linux (#9701)
filesystem tests: reiserfsprogs is no longer available on Arch Linux (#9699)

reiserfsprogs is no longer available on Arch Linux.

(cherry picked from commit 10c15d31f7)

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-02-08 20:25:38 +01:00
patchback[bot]
1e7294716e [PR #9686/0b4337c1 backport][stable-9] Also disable snap_alias tests for RHEL 8.8 (#9688)
Also disable snap_alias tests for RHEL 8.8 (#9686)

Also disable snap_alias tests for RHEL 8.8.

(cherry picked from commit 0b4337c13d)

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-02-04 22:29:23 +01:00
patchback[bot]
88c605a344 [PR #9679/54eec2cb backport][stable-9] Disable snap tests on RHEL 8.8 (#9681)
Disable snap tests on RHEL 8.8 (#9679)

Disable snap tests on RHEL 8.8.

(cherry picked from commit 54eec2cb09)

Co-authored-by: Felix Fontein <felix@fontein.de>
2025-02-03 10:53:45 +01:00
patchback[bot]
4a41ab583a [PR #9644/250dc113 backport][stable-9] Fb keycloak client improvement (#9670)
Fb keycloak client improvement (#9644)

* Fix for failed test

TASK [keycloak_client : Assert changes not detected in last two tasks (desire when same, and check)] ***
task path: /root/ansible_collections/community/general/tests/output/.tmp/integration/keycloak_client-p3ttqf7d-ÅÑŚÌβŁÈ/tests/integration/targets/keycloak_client/tasks/main.yml:79
fatal: [testhost]: FAILED! => {
    "assertion": "check_client_when_present_and_same is not changed",
    "changed": false,
    "evaluated_to": false,
    "msg": "Assertion failed"
}

* Improved test data to test more scenarios, e.g documentation uses True in examples

* Normalize values in config

* add changelog

* Apply suggestions from code review

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>

* Update tests/integration/targets/keycloak_client/vars/main.yml

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>

* Update changelogs/fragments/9644-kc_client-test-improvement-and-fix.yaml

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>

---------

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
(cherry picked from commit 250dc1139c)

Co-authored-by: amPrimeSign <146177975+amPrimeSign@users.noreply.github.com>
2025-02-01 22:46:10 +01:00
patchback[bot]
5d86045048 [PR #9649/19d00496 backport][stable-9] cloudflare_dns: fix crash when deleting a DNS record or when updating a record with solo=true (#9654)
cloudflare_dns: fix crash when deleting a DNS record or when updating a record with solo=true (#9649)

* cloudflare_dns: fix crash when deleting a DNS record or when updating a record with solo=true

On 2025-01-27, Cloudflare removed the 'zone_id' field from the DNS record API responses. This caused a KeyError in the delete_dns_records method, which previously relied on rr['zone_id'].

This commit ensures the zone ID is retrieved via _get_zone_id() rather than using the no-longer-provided 'zone_id' field in the record response.

Reference: https://developers.cloudflare.com/dns/changelog/#2025-01-27

* Add changelog fragment

* Update changelogs/fragments/9649-cloudflare_dns-fix-crash-when-deleting-record.yml

Co-authored-by: Felix Fontein <felix@fontein.de>

* Update changelogs/fragments/9649-cloudflare_dns-fix-crash-when-deleting-record.yml

Co-authored-by: Felix Fontein <felix@fontein.de>

---------

Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 19d0049698)

Co-authored-by: valievkarim <valievkarim@gmail.com>
2025-01-31 10:57:21 +01:00
Felix Fontein
2eb067e3e0 The next release will be 9.5.5. 2025-01-27 06:56:49 +01:00
313 changed files with 6988 additions and 6120 deletions

View File

@@ -43,8 +43,6 @@ variables:
value: ansible_collections/community/general
- name: coverageBranches
value: main
- name: pipelinesCoverage
value: coverage
- name: entryPoint
value: tests/utils/shippable/shippable.sh
- name: fetchDepth
@@ -72,7 +70,6 @@ stages:
- test: 2
- test: 3
- test: 4
- test: extra
- stage: Sanity_2_18
displayName: Sanity 2.18
dependsOn: []
@@ -190,14 +187,14 @@ stages:
parameters:
testFormat: devel/{0}
targets:
- name: macOS 14.3
test: macos/14.3
- name: macOS 15.3
test: macos/15.3
- name: RHEL 9.5
test: rhel/9.5
- name: FreeBSD 14.2
test: freebsd/14.2
- name: FreeBSD 13.4
test: freebsd/13.4
- name: FreeBSD 13.5
test: freebsd/13.5
groups:
- 1
- 2
@@ -210,6 +207,8 @@ stages:
parameters:
testFormat: 2.18/{0}
targets:
- name: macOS 14.3
test: macos/14.3
- name: RHEL 9.4
test: rhel/9.4
- name: FreeBSD 14.1
@@ -230,8 +229,6 @@ stages:
test: freebsd/13.3
- name: RHEL 9.3
test: rhel/9.3
- name: FreeBSD 14.0
test: freebsd/14.0
groups:
- 1
- 2

View File

@@ -28,16 +28,6 @@ jobs:
- bash: .azure-pipelines/scripts/report-coverage.sh
displayName: Generate Coverage Report
condition: gt(variables.coverageFileCount, 0)
- task: PublishCodeCoverageResults@1
inputs:
codeCoverageTool: Cobertura
# Azure Pipelines only accepts a single coverage data file.
# That means only Python or PowerShell coverage can be uploaded, but not both.
# Set the "pipelinesCoverage" variable to determine which type is uploaded.
# Use "coverage" for Python and "coverage-powershell" for PowerShell.
summaryFileLocation: "$(outputPath)/reports/$(pipelinesCoverage).xml"
displayName: Publish to Azure Pipelines
condition: gt(variables.coverageFileCount, 0)
- bash: .azure-pipelines/scripts/publish-codecov.py "$(outputPath)"
displayName: Publish to codecov.io
condition: gt(variables.coverageFileCount, 0)

View File

@@ -47,6 +47,8 @@ jobs:
coverage: ${{ github.event_name == 'schedule' && 'always' || 'never' }}
pull-request-change-detection: 'true'
testing-type: sanity
pre-test-cmd: >-
git clone --depth=1 --single-branch https://github.com/ansible-collections/community.internal_test_tools.git ../../community/internal_test_tools
units:
# Ansible-test on various stable branches does not yet work well with cgroups v2.
@@ -212,12 +214,15 @@ jobs:
integration-continue-on-error: 'false'
integration-diff: 'false'
integration-retry-on-error: 'true'
# TODO: remove "--branch stable-2" from community.crypto install once we're only using ansible-core 2.17 or newer!
pre-test-cmd: >-
mkdir -p ../../ansible
;
git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.posix.git ../../ansible/posix
;
git clone --depth=1 --single-branch https://github.com/ansible-collections/community.crypto.git ../../community/crypto
git clone --depth=1 --single-branch --branch stable-2 https://github.com/ansible-collections/community.crypto.git ../../community/crypto
;
git clone --depth=1 --single-branch https://github.com/ansible-collections/community.docker.git ../../community/docker
;
git clone --depth=1 --single-branch https://github.com/ansible-collections/community.internal_test_tools.git ../../community/internal_test_tools
pull-request-change-detection: 'true'

View File

@@ -1,20 +0,0 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
name: import-galaxy
'on':
# Run CI against all pushes (direct commits, also merged PRs) to main, and all Pull Requests
push:
branches:
- main
- stable-*
pull_request:
jobs:
import-galaxy:
permissions:
contents: read
name: Test to import built collection artifact with Galaxy importer
uses: ansible-community/github-action-test-galaxy-import/.github/workflows/test-galaxy-import.yml@main

28
.github/workflows/nox.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
name: nox
'on':
push:
branches:
- main
- stable-*
pull_request:
# Run CI once per day (at 08:00 UTC)
schedule:
- cron: '0 8 * * *'
workflow_dispatch:
jobs:
nox:
runs-on: ubuntu-latest
name: "Run extra sanity tests"
steps:
- name: Check out collection
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Run nox
uses: ansible-community/antsibull-nox@main

View File

@@ -1,35 +0,0 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
name: Verify REUSE
on:
push:
branches:
- main
- stable-*
pull_request:
types: [opened, synchronize, reopened]
branches:
- main
- stable-*
# Run CI once per day (at 07:30 UTC)
schedule:
- cron: '30 7 * * *'
jobs:
check:
permissions:
contents: read
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
ref: ${{ github.event.pull_request.head.sha || '' }}
- name: REUSE Compliance Check
uses: fsfe/reuse-action@v5

View File

@@ -1,5 +0,0 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Files: changelogs/fragments/*
Copyright: Ansible Project
License: GPL-3.0-or-later

View File

@@ -2,67 +2,82 @@
**Topics**
- <a href="#v9-5-4">v9\.5\.4</a>
- <a href="#security-fixes">Security Fixes</a>
- <a href="#bugfixes">Bugfixes</a>
- <a href="#v9-5-3">v9\.5\.3</a>
- <a href="#v9-5-8">v9\.5\.8</a>
- <a href="#release-summary">Release Summary</a>
- <a href="#minor-changes">Minor Changes</a>
- <a href="#security-fixes-1">Security Fixes</a>
- <a href="#bugfixes-1">Bugfixes</a>
- <a href="#v9-5-2">v9\.5\.2</a>
- <a href="#bugfixes">Bugfixes</a>
- <a href="#v9-5-7">v9\.5\.7</a>
- <a href="#release-summary-1">Release Summary</a>
- <a href="#minor-changes">Minor Changes</a>
- <a href="#bugfixes-1">Bugfixes</a>
- <a href="#known-issues">Known Issues</a>
- <a href="#v9-5-6">v9\.5\.6</a>
- <a href="#release-summary-2">Release Summary</a>
- <a href="#minor-changes-1">Minor Changes</a>
- <a href="#bugfixes-2">Bugfixes</a>
- <a href="#v9-5-1">v9\.5\.1</a>
- <a href="#release-summary-2">Release Summary</a>
- <a href="#minor-changes-2">Minor Changes</a>
- <a href="#bugfixes-3">Bugfixes</a>
- <a href="#v9-5-0">v9\.5\.0</a>
- <a href="#v9-5-5">v9\.5\.5</a>
- <a href="#release-summary-3">Release Summary</a>
- <a href="#minor-changes-3">Minor Changes</a>
- <a href="#deprecated-features">Deprecated Features</a>
- <a href="#bugfixes-3">Bugfixes</a>
- <a href="#v9-5-4">v9\.5\.4</a>
- <a href="#security-fixes">Security Fixes</a>
- <a href="#bugfixes-4">Bugfixes</a>
- <a href="#v9-5-3">v9\.5\.3</a>
- <a href="#release-summary-4">Release Summary</a>
- <a href="#minor-changes-2">Minor Changes</a>
- <a href="#security-fixes-1">Security Fixes</a>
- <a href="#bugfixes-5">Bugfixes</a>
- <a href="#v9-5-2">v9\.5\.2</a>
- <a href="#release-summary-5">Release Summary</a>
- <a href="#minor-changes-3">Minor Changes</a>
- <a href="#bugfixes-6">Bugfixes</a>
- <a href="#v9-5-1">v9\.5\.1</a>
- <a href="#release-summary-6">Release Summary</a>
- <a href="#minor-changes-4">Minor Changes</a>
- <a href="#bugfixes-7">Bugfixes</a>
- <a href="#v9-5-0">v9\.5\.0</a>
- <a href="#release-summary-7">Release Summary</a>
- <a href="#minor-changes-5">Minor Changes</a>
- <a href="#deprecated-features">Deprecated Features</a>
- <a href="#bugfixes-8">Bugfixes</a>
- <a href="#new-modules">New Modules</a>
- <a href="#v9-4-0">v9\.4\.0</a>
- <a href="#release-summary-4">Release Summary</a>
- <a href="#minor-changes-4">Minor Changes</a>
- <a href="#release-summary-8">Release Summary</a>
- <a href="#minor-changes-6">Minor Changes</a>
- <a href="#deprecated-features-1">Deprecated Features</a>
- <a href="#bugfixes-5">Bugfixes</a>
- <a href="#bugfixes-9">Bugfixes</a>
- <a href="#new-modules-1">New Modules</a>
- <a href="#v9-3-0">v9\.3\.0</a>
- <a href="#release-summary-5">Release Summary</a>
- <a href="#minor-changes-5">Minor Changes</a>
- <a href="#bugfixes-6">Bugfixes</a>
- <a href="#release-summary-9">Release Summary</a>
- <a href="#minor-changes-7">Minor Changes</a>
- <a href="#bugfixes-10">Bugfixes</a>
- <a href="#new-modules-2">New Modules</a>
- <a href="#v9-2-0">v9\.2\.0</a>
- <a href="#release-summary-6">Release Summary</a>
- <a href="#minor-changes-6">Minor Changes</a>
- <a href="#bugfixes-7">Bugfixes</a>
- <a href="#release-summary-10">Release Summary</a>
- <a href="#minor-changes-8">Minor Changes</a>
- <a href="#bugfixes-11">Bugfixes</a>
- <a href="#new-plugins">New Plugins</a>
- <a href="#filter">Filter</a>
- <a href="#test">Test</a>
- <a href="#v9-1-0">v9\.1\.0</a>
- <a href="#release-summary-7">Release Summary</a>
- <a href="#minor-changes-7">Minor Changes</a>
- <a href="#release-summary-11">Release Summary</a>
- <a href="#minor-changes-9">Minor Changes</a>
- <a href="#deprecated-features-2">Deprecated Features</a>
- <a href="#bugfixes-8">Bugfixes</a>
- <a href="#known-issues">Known Issues</a>
- <a href="#bugfixes-12">Bugfixes</a>
- <a href="#known-issues-1">Known Issues</a>
- <a href="#new-plugins-1">New Plugins</a>
- <a href="#filter-1">Filter</a>
- <a href="#new-modules-3">New Modules</a>
- <a href="#v9-0-1">v9\.0\.1</a>
- <a href="#release-summary-8">Release Summary</a>
- <a href="#minor-changes-8">Minor Changes</a>
- <a href="#bugfixes-9">Bugfixes</a>
- <a href="#release-summary-12">Release Summary</a>
- <a href="#minor-changes-10">Minor Changes</a>
- <a href="#bugfixes-13">Bugfixes</a>
- <a href="#v9-0-0">v9\.0\.0</a>
- <a href="#release-summary-9">Release Summary</a>
- <a href="#minor-changes-9">Minor Changes</a>
- <a href="#release-summary-13">Release Summary</a>
- <a href="#minor-changes-11">Minor Changes</a>
- <a href="#breaking-changes--porting-guide">Breaking Changes / Porting Guide</a>
- <a href="#deprecated-features-3">Deprecated Features</a>
- <a href="#removed-features-previously-deprecated">Removed Features \(previously deprecated\)</a>
- <a href="#security-fixes-2">Security Fixes</a>
- <a href="#bugfixes-10">Bugfixes</a>
- <a href="#bugfixes-14">Bugfixes</a>
- <a href="#new-plugins-2">New Plugins</a>
- <a href="#become">Become</a>
- <a href="#callback">Callback</a>
@@ -73,6 +88,107 @@
- <a href="#new-modules-4">New Modules</a>
This changelog describes changes after version 8\.0\.0\.
<a id="v9-5-8"></a>
## v9\.5\.8
<a id="release-summary"></a>
### Release Summary
Regular bugfix release\.
<a id="bugfixes"></a>
### Bugfixes
* cobbler\_system \- fix bug with Cobbler \>\= 3\.4\.0 caused by giving more than 2 positional arguments to <code>CobblerXMLRPCInterface\.get\_system\_handle\(\)</code> \([https\://github\.com/ansible\-collections/community\.general/issues/8506](https\://github\.com/ansible\-collections/community\.general/issues/8506)\, [https\://github\.com/ansible\-collections/community\.general/pull/10145](https\://github\.com/ansible\-collections/community\.general/pull/10145)\)\.
* kdeconfig \- allow option values beginning with a dash \([https\://github\.com/ansible\-collections/community\.general/issues/10127](https\://github\.com/ansible\-collections/community\.general/issues/10127)\, [https\://github\.com/ansible\-collections/community\.general/pull/10128](https\://github\.com/ansible\-collections/community\.general/pull/10128)\)\.
* keycloak\_user\_rolemapping \- fix <code>\-\-diff</code> mode \([https\://github\.com/ansible\-collections/community\.general/issues/10067](https\://github\.com/ansible\-collections/community\.general/issues/10067)\, [https\://github\.com/ansible\-collections/community\.general/pull/10075](https\://github\.com/ansible\-collections/community\.general/pull/10075)\)\.
* pickle cache plugin \- avoid extra JSON serialization with ansible\-core \>\= 2\.19 \([https\://github\.com/ansible\-collections/community\.general/pull/10136](https\://github\.com/ansible\-collections/community\.general/pull/10136)\)\.
* rundeck\_acl\_policy \- ensure that project ACLs are sent to the correct endpoint \([https\://github\.com/ansible\-collections/community\.general/pull/10097](https\://github\.com/ansible\-collections/community\.general/pull/10097)\)\.
* sysrc \- split the output of <code>sysrc \-e \-a</code> on the first <code>\=</code> only \([https\://github\.com/ansible\-collections/community\.general/issues/10120](https\://github\.com/ansible\-collections/community\.general/issues/10120)\, [https\://github\.com/ansible\-collections/community\.general/pull/10121](https\://github\.com/ansible\-collections/community\.general/pull/10121)\)\.
<a id="v9-5-7"></a>
## v9\.5\.7
<a id="release-summary-1"></a>
### Release Summary
Regular bugfix release\.
<a id="minor-changes"></a>
### Minor Changes
* apache2\_module \- added workaround for new PHP module name\, from <code>php7\_module</code> to <code>php\_module</code> \([https\://github\.com/ansible\-collections/community\.general/pull/9951](https\://github\.com/ansible\-collections/community\.general/pull/9951)\)\.
<a id="bugfixes-1"></a>
### Bugfixes
* dependent look plugin \- make compatible with ansible\-core\'s Data Tagging feature \([https\://github\.com/ansible\-collections/community\.general/pull/9833](https\://github\.com/ansible\-collections/community\.general/pull/9833)\)\.
* diy callback plugin \- make compatible with ansible\-core\'s Data Tagging feature \([https\://github\.com/ansible\-collections/community\.general/pull/9833](https\://github\.com/ansible\-collections/community\.general/pull/9833)\)\.
* github\_deploy\_key \- check that key really exists on 422 to avoid masking other errors \([https\://github\.com/ansible\-collections/community\.general/issues/6718](https\://github\.com/ansible\-collections/community\.general/issues/6718)\, [https\://github\.com/ansible\-collections/community\.general/pull/10011](https\://github\.com/ansible\-collections/community\.general/pull/10011)\)\.
* hashids and unicode\_normalize filter plugins \- avoid deprecated <code>AnsibleFilterTypeError</code> on ansible\-core 2\.19 \([https\://github\.com/ansible\-collections/community\.general/pull/9992](https\://github\.com/ansible\-collections/community\.general/pull/9992)\)\.
* keycloak\_authentication \- fix authentification config duplication for Keycloak \< 26\.2\.0 \([https\://github\.com/ansible\-collections/community\.general/pull/9987](https\://github\.com/ansible\-collections/community\.general/pull/9987)\)\.
* keycloak\_client \- fix the idempotency regression by normalizing the Keycloak response for <code>after\_client</code> \([https\://github\.com/ansible\-collections/community\.general/issues/9905](https\://github\.com/ansible\-collections/community\.general/issues/9905)\, [https\://github\.com/ansible\-collections/community\.general/pull/9976](https\://github\.com/ansible\-collections/community\.general/pull/9976)\)\.
* proxmox inventory plugin \- fix <code>ansible\_host</code> staying empty for certain Proxmox nodes \([https\://github\.com/ansible\-collections/community\.general/issues/5906](https\://github\.com/ansible\-collections/community\.general/issues/5906)\, [https\://github\.com/ansible\-collections/community\.general/pull/9952](https\://github\.com/ansible\-collections/community\.general/pull/9952)\)\.
* proxmox\_disk \- fail gracefully if <code>storage</code> is required but not provided by the user \([https\://github\.com/ansible\-collections/community\.general/issues/9941](https\://github\.com/ansible\-collections/community\.general/issues/9941)\, [https\://github\.com/ansible\-collections/community\.general/pull/9963](https\://github\.com/ansible\-collections/community\.general/pull/9963)\)\.
* reveal\_ansible\_type filter plugin and ansible\_type test plugin \- make compatible with ansible\-core\'s Data Tagging feature \([https\://github\.com/ansible\-collections/community\.general/pull/9833](https\://github\.com/ansible\-collections/community\.general/pull/9833)\)\.
* sysrc \- no longer always reporting <code>changed\=true</code> when <code>state\=absent</code>\. This fixes the method <code>exists\(\)</code> \([https\://github\.com/ansible\-collections/community\.general/issues/10004](https\://github\.com/ansible\-collections/community\.general/issues/10004)\, [https\://github\.com/ansible\-collections/community\.general/pull/10005](https\://github\.com/ansible\-collections/community\.general/pull/10005)\)\.
* yaml callback plugin \- use ansible\-core internals to avoid breakage with Data Tagging \([https\://github\.com/ansible\-collections/community\.general/pull/9833](https\://github\.com/ansible\-collections/community\.general/pull/9833)\)\.
<a id="known-issues"></a>
### Known Issues
* reveal\_ansible\_type filter plugin and ansible\_type test plugin \- note that ansible\-core\'s Data Tagging feature implements new aliases\, such as <code>\_AnsibleTaggedStr</code> for <code>str</code>\, <code>\_AnsibleTaggedInt</code> for <code>int</code>\, and <code>\_AnsibleTaggedFloat</code> for <code>float</code> \([https\://github\.com/ansible\-collections/community\.general/pull/9833](https\://github\.com/ansible\-collections/community\.general/pull/9833)\)\.
<a id="v9-5-6"></a>
## v9\.5\.6
<a id="release-summary-2"></a>
### Release Summary
Regular bugfix release\.
<a id="minor-changes-1"></a>
### Minor Changes
* consul\_token \- fix idempotency when <code>policies</code> or <code>roles</code> are supplied by name \([https\://github\.com/ansible\-collections/community\.general/issues/9841](https\://github\.com/ansible\-collections/community\.general/issues/9841)\, [https\://github\.com/ansible\-collections/community\.general/pull/9845](https\://github\.com/ansible\-collections/community\.general/pull/9845)\)\.
<a id="bugfixes-2"></a>
### Bugfixes
* cloudlare\_dns \- handle exhausted response stream in case of HTTP errors to show nice error message to the user \([https\://github\.com/ansible\-collections/community\.general/issues/9782](https\://github\.com/ansible\-collections/community\.general/issues/9782)\, [https\://github\.com/ansible\-collections/community\.general/pull/9818](https\://github\.com/ansible\-collections/community\.general/pull/9818)\)\.
* dnf\_versionlock \- add support for dnf5 \([https\://github\.com/ansible\-collections/community\.general/issues/9556](https\://github\.com/ansible\-collections/community\.general/issues/9556)\)\.
* homebrew\_cask \- handle unusual brew version strings \([https\://github\.com/ansible\-collections/community\.general/issues/8432](https\://github\.com/ansible\-collections/community\.general/issues/8432)\, [https\://github\.com/ansible\-collections/community\.general/pull/9881](https\://github\.com/ansible\-collections/community\.general/pull/9881)\)\.
* ipa\_host \- module revoked existing host certificates even if <code>user\_certificate</code> was not given \([https\://github\.com/ansible\-collections/community\.general/pull/9694](https\://github\.com/ansible\-collections/community\.general/pull/9694)\)\.
* nmcli \- enable changing only the order of DNS servers or search suffixes \([https\://github\.com/ansible\-collections/community\.general/issues/8724](https\://github\.com/ansible\-collections/community\.general/issues/8724)\, [https\://github\.com/ansible\-collections/community\.general/pull/9880](https\://github\.com/ansible\-collections/community\.general/pull/9880)\)\.
* proxmox\_vm\_info \- the module no longer expects that the key <code>template</code> exists in a dictionary returned by Proxmox \([https\://github\.com/ansible\-collections/community\.general/issues/9875](https\://github\.com/ansible\-collections/community\.general/issues/9875)\, [https\://github\.com/ansible\-collections/community\.general/pull/9910](https\://github\.com/ansible\-collections/community\.general/pull/9910)\)\.
* sudoers \- display stdout and stderr raised while failed validation \([https\://github\.com/ansible\-collections/community\.general/issues/9674](https\://github\.com/ansible\-collections/community\.general/issues/9674)\, [https\://github\.com/ansible\-collections/community\.general/pull/9871](https\://github\.com/ansible\-collections/community\.general/pull/9871)\)\.
<a id="v9-5-5"></a>
## v9\.5\.5
<a id="release-summary-3"></a>
### Release Summary
Regular bugfix release\.
<a id="bugfixes-3"></a>
### Bugfixes
* apache2\_mod\_proxy \- make compatible with Python 3 \([https\://github\.com/ansible\-collections/community\.general/pull/9762](https\://github\.com/ansible\-collections/community\.general/pull/9762)\)\.
* apache2\_mod\_proxy \- passing the cluster\'s page as referer for the member\'s pages\. This makes the module actually work again for halfway modern Apache versions\. According to some comments founds on the net the referer was required since at least 2019 for some versions of Apache 2 \([https\://github\.com/ansible\-collections/community\.general/pull/9762](https\://github\.com/ansible\-collections/community\.general/pull/9762)\)\.
* cloudflare\_dns \- fix crash when deleting a DNS record or when updating a record with <code>solo\=true</code> \([https\://github\.com/ansible\-collections/community\.general/issues/9652](https\://github\.com/ansible\-collections/community\.general/issues/9652)\, [https\://github\.com/ansible\-collections/community\.general/pull/9649](https\://github\.com/ansible\-collections/community\.general/pull/9649)\)\.
* elasticsearch\_plugin \- fix <code>ERROR\: D is not a recognized option</code> issue when configuring proxy settings \([https\://github\.com/ansible\-collections/community\.general/pull/9774](https\://github\.com/ansible\-collections/community\.general/pull/9774)\, [https\://github\.com/ansible\-collections/community\.general/issues/9773](https\://github\.com/ansible\-collections/community\.general/issues/9773)\)\.
* keycloak\_client \- fix and improve existing tests\. The module showed a diff without actual changes\, solved by improving the <code>normalise\_cr\(\)</code> function \([https\://github\.com/ansible\-collections/community\.general/pull/9644](https\://github\.com/ansible\-collections/community\.general/pull/9644)\)\.
* keycloak\_client \- in check mode\, detect whether the lists in before client \(for example redirect URI list\) contain items that the lists in the desired client do not contain \([https\://github\.com/ansible\-collections/community\.general/pull/9739](https\://github\.com/ansible\-collections/community\.general/pull/9739)\)\.
* passwordstore lookup plugin \- fix subkey creation even when <code>create\=false</code> \([https\://github\.com/ansible\-collections/community\.general/issues/9105](https\://github\.com/ansible\-collections/community\.general/issues/9105)\, [https\://github\.com/ansible\-collections/community\.general/pull/9106](https\://github\.com/ansible\-collections/community\.general/pull/9106)\)\.
* proxmox inventory plugin \- plugin did not update cache correctly after <code>meta\: refresh\_inventory</code> \([https\://github\.com/ansible\-collections/community\.general/issues/9710](https\://github\.com/ansible\-collections/community\.general/issues/9710)\, [https\://github\.com/ansible\-collections/community\.general/pull/9760](https\://github\.com/ansible\-collections/community\.general/pull/9760)\)\.
* redhat\_subscription \- use the \"enable\_content\" option \(when available\) when
registering using D\-Bus\, to ensure that subscription\-manager enables the
content on registration\; this is particular important on EL 10\+ and Fedora
41\+
\([https\://github\.com/ansible\-collections/community\.general/pull/9778](https\://github\.com/ansible\-collections/community\.general/pull/9778)\)\.
* xml \- ensure file descriptor is closed \([https\://github\.com/ansible\-collections/community\.general/pull/9695](https\://github\.com/ansible\-collections/community\.general/pull/9695)\)\.
<a id="v9-5-4"></a>
## v9\.5\.4
@@ -81,7 +197,7 @@ This changelog describes changes after version 8\.0\.0\.
* keycloak\_client \- Sanitize <code>saml\.encryption\.private\.key</code> so it does not show in the logs \([https\://github\.com/ansible\-collections/community\.general/pull/9621](https\://github\.com/ansible\-collections/community\.general/pull/9621)\)\.
<a id="bugfixes"></a>
<a id="bugfixes-4"></a>
### Bugfixes
* redhat\_subscription \- do not try to unsubscribe \(i\.e\. remove subscriptions\)
@@ -93,12 +209,12 @@ This changelog describes changes after version 8\.0\.0\.
<a id="v9-5-3"></a>
## v9\.5\.3
<a id="release-summary"></a>
<a id="release-summary-4"></a>
### Release Summary
Regular bugfix release\.
<a id="minor-changes"></a>
<a id="minor-changes-2"></a>
### Minor Changes
* proxmox module utils \- add method <code>api\_task\_complete</code> that can wait for task completion and return error message \([https\://github\.com/ansible\-collections/community\.general/pull/9256](https\://github\.com/ansible\-collections/community\.general/pull/9256)\)\.
@@ -108,7 +224,7 @@ Regular bugfix release\.
* keycloak\_authentication \- API calls did not properly set the <code>priority</code> during update resulting in incorrectly sorted authentication flows\. This apparently only affects Keycloak 25 or newer \([https\://github\.com/ansible\-collections/community\.general/pull/9263](https\://github\.com/ansible\-collections/community\.general/pull/9263)\)\.
<a id="bugfixes-1"></a>
<a id="bugfixes-5"></a>
### Bugfixes
* dig lookup plugin \- correctly handle <code>NoNameserver</code> exception \([https\://github\.com/ansible\-collections/community\.general/pull/9363](https\://github\.com/ansible\-collections/community\.general/pull/9363)\, [https\://github\.com/ansible\-collections/community\.general/issues/9362](https\://github\.com/ansible\-collections/community\.general/issues/9362)\)\.
@@ -121,17 +237,17 @@ Regular bugfix release\.
<a id="v9-5-2"></a>
## v9\.5\.2
<a id="release-summary-1"></a>
<a id="release-summary-5"></a>
### Release Summary
Regular bugfix release\.
<a id="minor-changes-1"></a>
<a id="minor-changes-3"></a>
### Minor Changes
* proxmox inventory plugin \- fix urllib3 <code>InsecureRequestWarnings</code> not being suppressed when a token is used \([https\://github\.com/ansible\-collections/community\.general/pull/9099](https\://github\.com/ansible\-collections/community\.general/pull/9099)\)\.
<a id="bugfixes-2"></a>
<a id="bugfixes-6"></a>
### Bugfixes
* dnf\_config\_manager \- fix hanging when prompting to import GPG keys \([https\://github\.com/ansible\-collections/community\.general/pull/9124](https\://github\.com/ansible\-collections/community\.general/pull/9124)\, [https\://github\.com/ansible\-collections/community\.general/issues/8830](https\://github\.com/ansible\-collections/community\.general/issues/8830)\)\.
@@ -148,17 +264,17 @@ Regular bugfix release\.
<a id="v9-5-1"></a>
## v9\.5\.1
<a id="release-summary-2"></a>
<a id="release-summary-6"></a>
### Release Summary
Regular bugfix release\.
<a id="minor-changes-2"></a>
<a id="minor-changes-4"></a>
### Minor Changes
* redfish\_utils module utils \- schedule a BIOS configuration job at next reboot when the BIOS config is changed \([https\://github\.com/ansible\-collections/community\.general/pull/9012](https\://github\.com/ansible\-collections/community\.general/pull/9012)\)\.
<a id="bugfixes-3"></a>
<a id="bugfixes-7"></a>
### Bugfixes
* bitwarden lookup plugin \- support BWS v0\.3\.0 syntax breaking change \([https\://github\.com/ansible\-collections/community\.general/pull/9028](https\://github\.com/ansible\-collections/community\.general/pull/9028)\)\.
@@ -176,7 +292,7 @@ Regular bugfix release\.
<a id="v9-5-0"></a>
## v9\.5\.0
<a id="release-summary-3"></a>
<a id="release-summary-7"></a>
### Release Summary
Regular bugfix and feature release\.
@@ -184,7 +300,7 @@ Regular bugfix and feature release\.
Please note that this is the last feature release for community\.general 9\.x\.y\.
From now on\, new features will only go into community\.general 10\.x\.y\.
<a id="minor-changes-3"></a>
<a id="minor-changes-5"></a>
### Minor Changes
* dig lookup plugin \- add <code>port</code> option to specify DNS server port \([https\://github\.com/ansible\-collections/community\.general/pull/8966](https\://github\.com/ansible\-collections/community\.general/pull/8966)\)\.
@@ -241,7 +357,7 @@ From now on\, new features will only go into community\.general 10\.x\.y\.
* hipchat \- the hipchat service has been discontinued and the self\-hosted variant has been End of Life since 2020\. The module is therefore deprecated and will be removed from community\.general 11\.0\.0 if nobody provides compelling reasons to still keep it \([https\://github\.com/ansible\-collections/community\.general/pull/8919](https\://github\.com/ansible\-collections/community\.general/pull/8919)\)\.
<a id="bugfixes-4"></a>
<a id="bugfixes-8"></a>
### Bugfixes
* cloudflare\_dns \- fix changing Cloudflare SRV records \([https\://github\.com/ansible\-collections/community\.general/issues/8679](https\://github\.com/ansible\-collections/community\.general/issues/8679)\, [https\://github\.com/ansible\-collections/community\.general/pull/8948](https\://github\.com/ansible\-collections/community\.general/pull/8948)\)\.
@@ -275,12 +391,12 @@ From now on\, new features will only go into community\.general 10\.x\.y\.
<a id="v9-4-0"></a>
## v9\.4\.0
<a id="release-summary-4"></a>
<a id="release-summary-8"></a>
### Release Summary
Bugfix and feature release\.
<a id="minor-changes-4"></a>
<a id="minor-changes-6"></a>
### Minor Changes
* MH module utils \- add parameter <code>when</code> to <code>cause\_changes</code> decorator \([https\://github\.com/ansible\-collections/community\.general/pull/8766](https\://github\.com/ansible\-collections/community\.general/pull/8766)\)\.
@@ -367,7 +483,7 @@ Bugfix and feature release\.
* pipx \- support for versions of the command line tool <code>pipx</code> older than <code>1\.7\.0</code> is deprecated and will be removed in community\.general 11\.0\.0 \([https\://github\.com/ansible\-collections/community\.general/pull/8793](https\://github\.com/ansible\-collections/community\.general/pull/8793)\)\.
* pipx\_info \- support for versions of the command line tool <code>pipx</code> older than <code>1\.7\.0</code> is deprecated and will be removed in community\.general 11\.0\.0 \([https\://github\.com/ansible\-collections/community\.general/pull/8793](https\://github\.com/ansible\-collections/community\.general/pull/8793)\)\.
<a id="bugfixes-5"></a>
<a id="bugfixes-9"></a>
### Bugfixes
* gitlab\_group\_access\_token \- fix crash in check mode caused by attempted access to a newly created access token \([https\://github\.com/ansible\-collections/community\.general/pull/8796](https\://github\.com/ansible\-collections/community\.general/pull/8796)\)\.
@@ -389,12 +505,12 @@ Bugfix and feature release\.
<a id="v9-3-0"></a>
## v9\.3\.0
<a id="release-summary-5"></a>
<a id="release-summary-9"></a>
### Release Summary
Regular bugfix and feature release\.
<a id="minor-changes-5"></a>
<a id="minor-changes-7"></a>
### Minor Changes
* cgroup\_memory\_recap\, hipchat\, jabber\, log\_plays\, loganalytics\, logentries\, logstash\, slack\, splunk\, sumologic\, syslog\_json callback plugins \- make sure that all options are typed \([https\://github\.com/ansible\-collections/community\.general/pull/8628](https\://github\.com/ansible\-collections/community\.general/pull/8628)\)\.
@@ -417,7 +533,7 @@ Regular bugfix and feature release\.
* proxmox inventory plugin \- add new fact for LXC interface details \([https\://github\.com/ansible\-collections/community\.general/pull/8713](https\://github\.com/ansible\-collections/community\.general/pull/8713)\)\.
* redis\, redis\_info \- add <code>client\_cert</code> and <code>client\_key</code> options to specify path to certificate for Redis authentication \([https\://github\.com/ansible\-collections/community\.general/pull/8654](https\://github\.com/ansible\-collections/community\.general/pull/8654)\)\.
<a id="bugfixes-6"></a>
<a id="bugfixes-10"></a>
### Bugfixes
* gitlab\_runner \- fix <code>paused</code> parameter being ignored \([https\://github\.com/ansible\-collections/community\.general/pull/8648](https\://github\.com/ansible\-collections/community\.general/pull/8648)\)\.
@@ -438,12 +554,12 @@ Regular bugfix and feature release\.
<a id="v9-2-0"></a>
## v9\.2\.0
<a id="release-summary-6"></a>
<a id="release-summary-10"></a>
### Release Summary
Regular bugfix and feature release\.
<a id="minor-changes-6"></a>
<a id="minor-changes-8"></a>
### Minor Changes
* CmdRunner module utils \- the parameter <code>force\_lang</code> now supports the special value <code>auto</code> which will automatically try and determine the best parsable locale in the system \([https\://github\.com/ansible\-collections/community\.general/pull/8517](https\://github\.com/ansible\-collections/community\.general/pull/8517)\)\.
@@ -455,7 +571,7 @@ Regular bugfix and feature release\.
* virtualbox inventory plugin \- expose a new parameter <code>enable\_advanced\_group\_parsing</code> to change how the VirtualBox dynamic inventory parses VM groups \([https\://github\.com/ansible\-collections/community\.general/issues/8508](https\://github\.com/ansible\-collections/community\.general/issues/8508)\, [https\://github\.com/ansible\-collections/community\.general/pull/8510](https\://github\.com/ansible\-collections/community\.general/pull/8510)\)\.
* wdc\_redfish\_command \- minor change to handle upgrade file for Redfish WD platforms \([https\://github\.com/ansible\-collections/community\.general/pull/8444](https\://github\.com/ansible\-collections/community\.general/pull/8444)\)\.
<a id="bugfixes-7"></a>
<a id="bugfixes-11"></a>
### Bugfixes
* bitwarden lookup plugin \- fix <code>KeyError</code> in <code>search\_field</code> \([https\://github\.com/ansible\-collections/community\.general/issues/8549](https\://github\.com/ansible\-collections/community\.general/issues/8549)\, [https\://github\.com/ansible\-collections/community\.general/pull/8557](https\://github\.com/ansible\-collections/community\.general/pull/8557)\)\.
@@ -480,12 +596,12 @@ Regular bugfix and feature release\.
<a id="v9-1-0"></a>
## v9\.1\.0
<a id="release-summary-7"></a>
<a id="release-summary-11"></a>
### Release Summary
Regular feature and bugfix release\.
<a id="minor-changes-7"></a>
<a id="minor-changes-9"></a>
### Minor Changes
* CmdRunner module util \- argument formats can be specified as plain functions without calling <code>cmd\_runner\_fmt\.as\_func\(\)</code> \([https\://github\.com/ansible\-collections/community\.general/pull/8479](https\://github\.com/ansible\-collections/community\.general/pull/8479)\)\.
@@ -509,7 +625,7 @@ Regular feature and bugfix release\.
* git\_config \- the <code>list\_all</code> option has been deprecated and will be removed in community\.general 11\.0\.0\. Use the <code>community\.general\.git\_config\_info</code> module instead \([https\://github\.com/ansible\-collections/community\.general/pull/8453](https\://github\.com/ansible\-collections/community\.general/pull/8453)\)\.
* git\_config \- using <code>state\=present</code> without providing <code>value</code> is deprecated and will be disallowed in community\.general 11\.0\.0\. Use the <code>community\.general\.git\_config\_info</code> module instead to read a value \([https\://github\.com/ansible\-collections/community\.general/pull/8453](https\://github\.com/ansible\-collections/community\.general/pull/8453)\)\.
<a id="bugfixes-8"></a>
<a id="bugfixes-12"></a>
### Bugfixes
* git\_config \- fix behavior of <code>state\=absent</code> if <code>value</code> is present \([https\://github\.com/ansible\-collections/community\.general/issues/8436](https\://github\.com/ansible\-collections/community\.general/issues/8436)\, [https\://github\.com/ansible\-collections/community\.general/pull/8452](https\://github\.com/ansible\-collections/community\.general/pull/8452)\)\.
@@ -520,7 +636,7 @@ Regular feature and bugfix release\.
* opentelemetry callback \- do not save the content response when using the <code>ansible\.builtin\.slurp</code> module \([https\://github\.com/ansible\-collections/community\.general/pull/8430](https\://github\.com/ansible\-collections/community\.general/pull/8430)\)\.
* paman \- do not fail if an empty list of packages has been provided and there is nothing to do \([https\://github\.com/ansible\-collections/community\.general/pull/8514](https\://github\.com/ansible\-collections/community\.general/pull/8514)\)\.
<a id="known-issues"></a>
<a id="known-issues-1"></a>
### Known Issues
* homectl \- the module does not work under Python 3\.13 or newer\, since it relies on the removed <code>crypt</code> standard library module \([https\://github\.com/ansible\-collections/community\.general/issues/4691](https\://github\.com/ansible\-collections/community\.general/issues/4691)\, [https\://github\.com/ansible\-collections/community\.general/pull/8497](https\://github\.com/ansible\-collections/community\.general/pull/8497)\)\.
@@ -547,17 +663,17 @@ Regular feature and bugfix release\.
<a id="v9-0-1"></a>
## v9\.0\.1
<a id="release-summary-8"></a>
<a id="release-summary-12"></a>
### Release Summary
Bugfix release for inclusion in Ansible 10\.0\.0rc1\.
<a id="minor-changes-8"></a>
<a id="minor-changes-10"></a>
### Minor Changes
* ansible\_galaxy\_install \- minor refactor in the module \([https\://github\.com/ansible\-collections/community\.general/pull/8413](https\://github\.com/ansible\-collections/community\.general/pull/8413)\)\.
<a id="bugfixes-9"></a>
<a id="bugfixes-13"></a>
### Bugfixes
* cpanm \- use new <code>VarDict</code> to prevent deprecation warning \([https\://github\.com/ansible\-collections/community\.general/issues/8410](https\://github\.com/ansible\-collections/community\.general/issues/8410)\, [https\://github\.com/ansible\-collections/community\.general/pull/8411](https\://github\.com/ansible\-collections/community\.general/pull/8411)\)\.
@@ -576,12 +692,12 @@ Bugfix release for inclusion in Ansible 10\.0\.0rc1\.
<a id="v9-0-0"></a>
## v9\.0\.0
<a id="release-summary-9"></a>
<a id="release-summary-13"></a>
### Release Summary
This is release 9\.0\.0 of <code>community\.general</code>\, released on 2024\-05\-20\.
<a id="minor-changes-9"></a>
<a id="minor-changes-11"></a>
### Minor Changes
* PythonRunner module utils \- specialisation of <code>CmdRunner</code> to execute Python scripts \([https\://github\.com/ansible\-collections/community\.general/pull/8289](https\://github\.com/ansible\-collections/community\.general/pull/8289)\)\.
@@ -751,7 +867,7 @@ This is release 9\.0\.0 of <code>community\.general</code>\, released on 2024\-0
* cobbler\, gitlab\_runners\, icinga2\, linode\, lxd\, nmap\, online\, opennebula\, proxmox\, scaleway\, stackpath\_compute\, virtualbox\, and xen\_orchestra inventory plugin \- make sure all data received from the remote servers is marked as unsafe\, so remote code execution by obtaining texts that can be evaluated as templates is not possible \([https\://www\.die\-welt\.net/2024/03/remote\-code\-execution\-in\-ansible\-dynamic\-inventory\-plugins/](https\://www\.die\-welt\.net/2024/03/remote\-code\-execution\-in\-ansible\-dynamic\-inventory\-plugins/)\, [https\://github\.com/ansible\-collections/community\.general/pull/8098](https\://github\.com/ansible\-collections/community\.general/pull/8098)\)\.
* keycloak\_identity\_provider \- the client secret was not correctly sanitized by the module\. The return values <code>proposed</code>\, <code>existing</code>\, and <code>end\_state</code>\, as well as the diff\, did contain the client secret unmasked \([https\://github\.com/ansible\-collections/community\.general/pull/8355](https\://github\.com/ansible\-collections/community\.general/pull/8355)\)\.
<a id="bugfixes-10"></a>
<a id="bugfixes-14"></a>
### Bugfixes
* aix\_filesystem \- fix <code>\_validate\_vg</code> not passing VG name to <code>lsvg\_cmd</code> \([https\://github\.com/ansible\-collections/community\.general/issues/8151](https\://github\.com/ansible\-collections/community\.general/issues/8151)\)\.

View File

@@ -6,6 +6,107 @@ Community General Release Notes
This changelog describes changes after version 8.0.0.
v9.5.8
======
Release Summary
---------------
Regular bugfix release.
Bugfixes
--------
- cobbler_system - fix bug with Cobbler >= 3.4.0 caused by giving more than 2 positional arguments to ``CobblerXMLRPCInterface.get_system_handle()`` (https://github.com/ansible-collections/community.general/issues/8506, https://github.com/ansible-collections/community.general/pull/10145).
- kdeconfig - allow option values beginning with a dash (https://github.com/ansible-collections/community.general/issues/10127, https://github.com/ansible-collections/community.general/pull/10128).
- keycloak_user_rolemapping - fix ``--diff`` mode (https://github.com/ansible-collections/community.general/issues/10067, https://github.com/ansible-collections/community.general/pull/10075).
- pickle cache plugin - avoid extra JSON serialization with ansible-core >= 2.19 (https://github.com/ansible-collections/community.general/pull/10136).
- rundeck_acl_policy - ensure that project ACLs are sent to the correct endpoint (https://github.com/ansible-collections/community.general/pull/10097).
- sysrc - split the output of ``sysrc -e -a`` on the first ``=`` only (https://github.com/ansible-collections/community.general/issues/10120, https://github.com/ansible-collections/community.general/pull/10121).
v9.5.7
======
Release Summary
---------------
Regular bugfix release.
Minor Changes
-------------
- apache2_module - added workaround for new PHP module name, from ``php7_module`` to ``php_module`` (https://github.com/ansible-collections/community.general/pull/9951).
Bugfixes
--------
- dependent look plugin - make compatible with ansible-core's Data Tagging feature (https://github.com/ansible-collections/community.general/pull/9833).
- diy callback plugin - make compatible with ansible-core's Data Tagging feature (https://github.com/ansible-collections/community.general/pull/9833).
- github_deploy_key - check that key really exists on 422 to avoid masking other errors (https://github.com/ansible-collections/community.general/issues/6718, https://github.com/ansible-collections/community.general/pull/10011).
- hashids and unicode_normalize filter plugins - avoid deprecated ``AnsibleFilterTypeError`` on ansible-core 2.19 (https://github.com/ansible-collections/community.general/pull/9992).
- keycloak_authentication - fix authentification config duplication for Keycloak < 26.2.0 (https://github.com/ansible-collections/community.general/pull/9987).
- keycloak_client - fix the idempotency regression by normalizing the Keycloak response for ``after_client`` (https://github.com/ansible-collections/community.general/issues/9905, https://github.com/ansible-collections/community.general/pull/9976).
- proxmox inventory plugin - fix ``ansible_host`` staying empty for certain Proxmox nodes (https://github.com/ansible-collections/community.general/issues/5906, https://github.com/ansible-collections/community.general/pull/9952).
- proxmox_disk - fail gracefully if ``storage`` is required but not provided by the user (https://github.com/ansible-collections/community.general/issues/9941, https://github.com/ansible-collections/community.general/pull/9963).
- reveal_ansible_type filter plugin and ansible_type test plugin - make compatible with ansible-core's Data Tagging feature (https://github.com/ansible-collections/community.general/pull/9833).
- sysrc - no longer always reporting ``changed=true`` when ``state=absent``. This fixes the method ``exists()`` (https://github.com/ansible-collections/community.general/issues/10004, https://github.com/ansible-collections/community.general/pull/10005).
- yaml callback plugin - use ansible-core internals to avoid breakage with Data Tagging (https://github.com/ansible-collections/community.general/pull/9833).
Known Issues
------------
- reveal_ansible_type filter plugin and ansible_type test plugin - note that ansible-core's Data Tagging feature implements new aliases, such as ``_AnsibleTaggedStr`` for ``str``, ``_AnsibleTaggedInt`` for ``int``, and ``_AnsibleTaggedFloat`` for ``float`` (https://github.com/ansible-collections/community.general/pull/9833).
v9.5.6
======
Release Summary
---------------
Regular bugfix release.
Minor Changes
-------------
- consul_token - fix idempotency when ``policies`` or ``roles`` are supplied by name (https://github.com/ansible-collections/community.general/issues/9841, https://github.com/ansible-collections/community.general/pull/9845).
Bugfixes
--------
- cloudlare_dns - handle exhausted response stream in case of HTTP errors to show nice error message to the user (https://github.com/ansible-collections/community.general/issues/9782, https://github.com/ansible-collections/community.general/pull/9818).
- dnf_versionlock - add support for dnf5 (https://github.com/ansible-collections/community.general/issues/9556).
- homebrew_cask - handle unusual brew version strings (https://github.com/ansible-collections/community.general/issues/8432, https://github.com/ansible-collections/community.general/pull/9881).
- ipa_host - module revoked existing host certificates even if ``user_certificate`` was not given (https://github.com/ansible-collections/community.general/pull/9694).
- nmcli - enable changing only the order of DNS servers or search suffixes (https://github.com/ansible-collections/community.general/issues/8724, https://github.com/ansible-collections/community.general/pull/9880).
- proxmox_vm_info - the module no longer expects that the key ``template`` exists in a dictionary returned by Proxmox (https://github.com/ansible-collections/community.general/issues/9875, https://github.com/ansible-collections/community.general/pull/9910).
- sudoers - display stdout and stderr raised while failed validation (https://github.com/ansible-collections/community.general/issues/9674, https://github.com/ansible-collections/community.general/pull/9871).
v9.5.5
======
Release Summary
---------------
Regular bugfix release.
Bugfixes
--------
- apache2_mod_proxy - make compatible with Python 3 (https://github.com/ansible-collections/community.general/pull/9762).
- apache2_mod_proxy - passing the cluster's page as referer for the member's pages. This makes the module actually work again for halfway modern Apache versions. According to some comments founds on the net the referer was required since at least 2019 for some versions of Apache 2 (https://github.com/ansible-collections/community.general/pull/9762).
- cloudflare_dns - fix crash when deleting a DNS record or when updating a record with ``solo=true`` (https://github.com/ansible-collections/community.general/issues/9652, https://github.com/ansible-collections/community.general/pull/9649).
- elasticsearch_plugin - fix ``ERROR: D is not a recognized option`` issue when configuring proxy settings (https://github.com/ansible-collections/community.general/pull/9774, https://github.com/ansible-collections/community.general/issues/9773).
- keycloak_client - fix and improve existing tests. The module showed a diff without actual changes, solved by improving the ``normalise_cr()`` function (https://github.com/ansible-collections/community.general/pull/9644).
- keycloak_client - in check mode, detect whether the lists in before client (for example redirect URI list) contain items that the lists in the desired client do not contain (https://github.com/ansible-collections/community.general/pull/9739).
- passwordstore lookup plugin - fix subkey creation even when ``create=false`` (https://github.com/ansible-collections/community.general/issues/9105, https://github.com/ansible-collections/community.general/pull/9106).
- proxmox inventory plugin - plugin did not update cache correctly after ``meta: refresh_inventory`` (https://github.com/ansible-collections/community.general/issues/9710, https://github.com/ansible-collections/community.general/pull/9760).
- redhat_subscription - use the "enable_content" option (when available) when
registering using D-Bus, to ensure that subscription-manager enables the
content on registration; this is particular important on EL 10+ and Fedora
41+
(https://github.com/ansible-collections/community.general/pull/9778).
- xml - ensure file descriptor is closed (https://github.com/ansible-collections/community.general/pull/9695).
v9.5.4
======

View File

@@ -44,7 +44,49 @@ If you want to test a PR locally, refer to [our testing guide](https://github.co
If you find any inconsistencies or places in this document which can be improved, feel free to raise an issue or pull request to fix it.
## Run sanity, unit or integration tests locally
## Run sanity or unit locally (with antsibull-nox)
The easiest way to run sanity and unit tests locally is to use [antsibull-nox](https://ansible.readthedocs.io/projects/antsibull-nox/).
(If you have [nox](https://nox.thea.codes/en/stable/) installed, it will automatically install antsibull-nox in a virtual environment for you.)
### Sanity tests
The following commands show how to run ansible-test sanity tests:
```.bash
# Run basic sanity tests for all files in the collection:
nox -Re ansible-test-sanity-devel
# Run basic sanity tests for the given files and directories:
nox -Re ansible-test-sanity-devel -- plugins/modules/system/pids.py tests/integration/targets/pids/
# Run all other sanity tests for all files in the collection:
nox -R
```
If you replace `-Re` with `-e`, respectively. leave `-R` away, then the virtual environments will be re-created. The `-R` re-uses them (if they already exist).
### Unit tests
The following commands show how to run unit tests:
```.bash
# Run all unit tests:
nox -Re ansible-test-units-devel
# Run all unit tests for one Python version (a lot faster):
nox -Re ansible-test-units-devel -- --python 3.13
# Run a specific unit test (for the nmcli module) for one Python version:
nox -Re ansible-test-units-devel -- --python 3.13 tests/unit/plugins/modules/net_tools/test_nmcli.py
```
If you replace `-Re` with `-e`, then the virtual environments will be re-created. The `-R` re-uses them (if they already exist).
## Run basic sanity, unit or integration tests locally (with ansible-test)
Instead of using antsibull-nox, you can also run sanity and unit tests with ansible-test directly.
This also allows you to run integration tests.
You have to check out the repository into a specific path structure to be able to run `ansible-test`. The path to the git checkout must end with `.../ansible_collections/community/general`. Please see [our testing guide](https://github.com/ansible/community-docs/blob/main/test_pr_locally_guide.rst) for instructions on how to check out the repository into a correct path structure. The short version of these instructions is:
@@ -56,20 +98,27 @@ cd ~/dev/ansible_collections/community/general
Then you can run `ansible-test` (which is a part of [ansible-core](https://pypi.org/project/ansible-core/)) inside the checkout. The following example commands expect that you have installed Docker or Podman. Note that Podman has only been supported by more recent ansible-core releases. If you are using Docker, the following will work with Ansible 2.9+.
### Sanity tests
### Basic sanity tests
The following commands show how to run sanity tests:
The following commands show how to run basic sanity tests:
```.bash
# Run sanity tests for all files in the collection:
# Run basic sanity tests for all files in the collection:
ansible-test sanity --docker -v
# Run sanity tests for the given files and directories:
# Run basic sanity tests for the given files and directories:
ansible-test sanity --docker -v plugins/modules/system/pids.py tests/integration/targets/pids/
```
### Unit tests
Note that for running unit tests, you need to install required collections in the same folder structure that `community.general` is checked out in.
Right now, you need to install [`community.internal_test_tools`](https://github.com/ansible-collections/community.internal_test_tools).
If you want to use the latest version from GitHub, you can run:
```
git clone https://github.com/ansible-collections/community.internal_test_tools.git ~/dev/ansible_collections/community/internal_test_tools
```
The following commands show how to run unit tests:
```.bash
@@ -85,6 +134,16 @@ ansible-test units --docker -v --python 3.8 tests/unit/plugins/modules/net_tools
### Integration tests
Note that for running integration tests, you need to install required collections in the same folder structure that `community.general` is checked out in.
Right now, depending on the test, you need to install [`ansible.posix`](https://github.com/ansible-collections/ansible.posix), [`community.crypto`](https://github.com/ansible-collections/community.crypto), and [`community.docker`](https://github.com/ansible-collections/community.docker):
If you want to use the latest versions from GitHub, you can run:
```
mkdir -p ~/dev/ansible_collections/ansible
git clone https://github.com/ansible-collections/ansible.posix.git ~/dev/ansible_collections/ansible/posix
git clone https://github.com/ansible-collections/community.crypto.git ~/dev/ansible_collections/community/crypto
git clone https://github.com/ansible-collections/community.docker.git ~/dev/ansible_collections/community/docker
```
The following commands show how to run integration tests:
#### In Docker
@@ -92,8 +151,8 @@ The following commands show how to run integration tests:
Integration tests on Docker have the following parameters:
- `image_name` (required): The name of the Docker image. To get the list of supported Docker images, run
`ansible-test integration --help` and look for _target docker images_.
- `test_name` (optional): The name of the integration test.
For modules, this equals the short name of the module; for example, `pacman` in case of `community.general.pacman`.
- `test_name` (optional): The name of the integration test.
For modules, this equals the short name of the module; for example, `pacman` in case of `community.general.pacman`.
For plugins, the plugin type is added before the plugin's short name, for example `callback_yaml` for the `community.general.yaml` callback.
```.bash
# Test all plugins/modules on fedora40

View File

@@ -9,6 +9,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
[![Documentation](https://img.shields.io/badge/docs-brightgreen.svg)](https://docs.ansible.com/ansible/latest/collections/community/general/)
[![Build Status](https://dev.azure.com/ansible/community.general/_apis/build/status/CI?branchName=stable-9)](https://dev.azure.com/ansible/community.general/_build?definitionId=31)
[![EOL CI](https://github.com/ansible-collections/community.general/actions/workflows/ansible-test.yml/badge.svg?branch=stable-9)](https://github.com/ansible-collections/community.general/actions)
[![Nox CI](https://github.com/ansible-collections/community.general/actions/workflows/nox.yml/badge.svg?branch=stable-9)](https://github.com/ansible-collections/community.general/actions)
[![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/community.general)](https://codecov.io/gh/ansible-collections/community.general)
[![REUSE status](https://api.reuse.software/badge/github.com/ansible-collections/community.general)](https://api.reuse.software/info/github.com/ansible-collections/community.general)
@@ -140,4 +141,4 @@ See [LICENSES/GPL-3.0-or-later.txt](https://github.com/ansible-collections/commu
Parts of the collection are licensed under the [BSD 2-Clause license](https://github.com/ansible-collections/community.general/blob/stable-9/LICENSES/BSD-2-Clause.txt), the [MIT license](https://github.com/ansible-collections/community.general/blob/stable-9/LICENSES/MIT.txt), and the [PSF 2.0 license](https://github.com/ansible-collections/community.general/blob/stable-9/LICENSES/PSF-2.0.txt).
All files have a machine readable `SDPX-License-Identifier:` comment denoting its respective license(s) or an equivalent entry in an accompanying `.license` file. Only changelog fragments (which will not be part of a release) are covered by a blanket statement in `.reuse/dep5`. This conforms to the [REUSE specification](https://reuse.software/spec/).
All files have a machine readable `SDPX-License-Identifier:` comment denoting its respective license(s) or an equivalent entry in an accompanying `.license` file. Only changelog fragments (which will not be part of a release) are covered by a blanket statement in `REUSE.toml`. This conforms to the [REUSE specification](https://reuse.software/spec/).

11
REUSE.toml Normal file
View File

@@ -0,0 +1,11 @@
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
version = 1
[[annotations]]
path = "changelogs/fragments/**"
precedence = "aggregate"
SPDX-FileCopyrightText = "Ansible Project"
SPDX-License-Identifier = "GPL-3.0-or-later"

61
antsibull-nox.toml Normal file
View File

@@ -0,0 +1,61 @@
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2025 Felix Fontein <felix@fontein.de>
[collection_sources]
"ansible.posix" = "git+https://github.com/ansible-collections/ansible.posix.git,main"
"community.crypto" = "git+https://github.com/ansible-collections/community.crypto.git,main"
"community.docker" = "git+https://github.com/ansible-collections/community.docker.git,main"
"community.internal_test_tools" = "git+https://github.com/ansible-collections/community.internal_test_tools.git,main"
[collection_sources_per_ansible.'2.13']
"community.crypto" = "git+https://github.com/ansible-collections/community.crypto.git,stable-2"
[collection_sources_per_ansible.'2.14']
"community.crypto" = "git+https://github.com/ansible-collections/community.crypto.git,stable-2"
[collection_sources_per_ansible.'2.15']
# community.crypto's main branch needs ansible-core >= 2.17
"community.crypto" = "git+https://github.com/ansible-collections/community.crypto.git,stable-2"
[collection_sources_per_ansible.'2.16']
# community.crypto's main branch needs ansible-core >= 2.17
"community.crypto" = "git+https://github.com/ansible-collections/community.crypto.git,stable-2"
[sessions]
[sessions.docs_check]
validate_collection_refs="all"
[sessions.license_check]
[sessions.extra_checks]
run_no_unwanted_files = true
no_unwanted_files_module_extensions = [".py"]
no_unwanted_files_yaml_extensions = [".yml"]
run_action_groups = true
[[sessions.extra_checks.action_groups_config]]
name = "consul"
pattern = "^consul_.*$"
exclusions = [
"consul_acl",
"consul_acl_bootstrap",
"consul_kv",
]
doc_fragment = "community.general.consul.actiongroup_consul"
[[sessions.extra_checks.action_groups_config]]
name = "proxmox"
pattern = "^proxmox(_.*)?$"
exclusions = []
doc_fragment = "community.general.proxmox.actiongroup_proxmox"
[sessions.build_import_check]
run_galaxy_importer = true
[sessions.ansible_test_sanity]
include_devel = true
[sessions.ansible_test_units]
include_devel = true

View File

@@ -1563,3 +1563,165 @@ releases:
- 9578-redhat_subscription-no-remove-on-unregister.yml
- 9621-keycloak_client-sanitize-saml-encryption-key.yml
release_date: '2025-01-27'
9.5.5:
changes:
bugfixes:
- apache2_mod_proxy - make compatible with Python 3 (https://github.com/ansible-collections/community.general/pull/9762).
- apache2_mod_proxy - passing the cluster's page as referer for the member's
pages. This makes the module actually work again for halfway modern Apache
versions. According to some comments founds on the net the referer was required
since at least 2019 for some versions of Apache 2 (https://github.com/ansible-collections/community.general/pull/9762).
- cloudflare_dns - fix crash when deleting a DNS record or when updating a
record with ``solo=true`` (https://github.com/ansible-collections/community.general/issues/9652,
https://github.com/ansible-collections/community.general/pull/9649).
- 'elasticsearch_plugin - fix ``ERROR: D is not a recognized option`` issue
when configuring proxy settings (https://github.com/ansible-collections/community.general/pull/9774,
https://github.com/ansible-collections/community.general/issues/9773).'
- keycloak_client - fix and improve existing tests. The module showed a diff
without actual changes, solved by improving the ``normalise_cr()`` function
(https://github.com/ansible-collections/community.general/pull/9644).
- keycloak_client - in check mode, detect whether the lists in before client
(for example redirect URI list) contain items that the lists in the desired
client do not contain (https://github.com/ansible-collections/community.general/pull/9739).
- passwordstore lookup plugin - fix subkey creation even when ``create=false``
(https://github.com/ansible-collections/community.general/issues/9105, https://github.com/ansible-collections/community.general/pull/9106).
- 'proxmox inventory plugin - plugin did not update cache correctly after
``meta: refresh_inventory`` (https://github.com/ansible-collections/community.general/issues/9710,
https://github.com/ansible-collections/community.general/pull/9760).'
- 'redhat_subscription - use the "enable_content" option (when available)
when
registering using D-Bus, to ensure that subscription-manager enables the
content on registration; this is particular important on EL 10+ and Fedora
41+
(https://github.com/ansible-collections/community.general/pull/9778).
'
- xml - ensure file descriptor is closed (https://github.com/ansible-collections/community.general/pull/9695).
release_summary: Regular bugfix release.
fragments:
- 9.5.5.yml
- 9106-passwordstore-fix-subkey-creation-even-when-create-==-false.yml
- 9644-kc_client-test-improvement-and-fix.yaml
- 9649-cloudflare_dns-fix-crash-when-deleting-record.yml
- 9695-xml-close-file.yml
- 9739-keycloak_client-compare-before-desired-directly.yml
- 9760-proxmox-inventory.yml
- 9762-apache2_mod_proxy.yml
- 9774-fix-elasticsearch_plugin-proxy-settings.yml
- 9778-redhat_subscription-ensure-to-enable-content.yml
release_date: '2025-02-24'
9.5.6:
changes:
bugfixes:
- cloudlare_dns - handle exhausted response stream in case of HTTP errors
to show nice error message to the user (https://github.com/ansible-collections/community.general/issues/9782,
https://github.com/ansible-collections/community.general/pull/9818).
- dnf_versionlock - add support for dnf5 (https://github.com/ansible-collections/community.general/issues/9556).
- homebrew_cask - handle unusual brew version strings (https://github.com/ansible-collections/community.general/issues/8432,
https://github.com/ansible-collections/community.general/pull/9881).
- ipa_host - module revoked existing host certificates even if ``user_certificate``
was not given (https://github.com/ansible-collections/community.general/pull/9694).
- nmcli - enable changing only the order of DNS servers or search suffixes
(https://github.com/ansible-collections/community.general/issues/8724, https://github.com/ansible-collections/community.general/pull/9880).
- proxmox_vm_info - the module no longer expects that the key ``template``
exists in a dictionary returned by Proxmox (https://github.com/ansible-collections/community.general/issues/9875,
https://github.com/ansible-collections/community.general/pull/9910).
- sudoers - display stdout and stderr raised while failed validation (https://github.com/ansible-collections/community.general/issues/9674,
https://github.com/ansible-collections/community.general/pull/9871).
minor_changes:
- consul_token - fix idempotency when ``policies`` or ``roles`` are supplied
by name (https://github.com/ansible-collections/community.general/issues/9841,
https://github.com/ansible-collections/community.general/pull/9845).
release_summary: Regular bugfix release.
fragments:
- 9.5.6.yml
- 9694-ipa-host-certificate-revoked.yml
- 9818-cloudflare-dns-exhausted-response.yml
- 9845-consul_token_idempotency.yml
- 9875-proxmox-dont-expect-key-template-to-exist.yml
- 9880-nmcli-fix-reorder-same-dns-nameservers-search-suffixes.yml
- dnf_versionlock.yml
- homebrew_cask.yml
- sudoers.yml
release_date: '2025-03-24'
9.5.7:
changes:
bugfixes:
- dependent look plugin - make compatible with ansible-core's Data Tagging
feature (https://github.com/ansible-collections/community.general/pull/9833).
- diy callback plugin - make compatible with ansible-core's Data Tagging feature
(https://github.com/ansible-collections/community.general/pull/9833).
- "github_deploy_key - check that key really exists on 422\_to avoid masking\
\ other errors (https://github.com/ansible-collections/community.general/issues/6718,\
\ https://github.com/ansible-collections/community.general/pull/10011)."
- hashids and unicode_normalize filter plugins - avoid deprecated ``AnsibleFilterTypeError``
on ansible-core 2.19 (https://github.com/ansible-collections/community.general/pull/9992).
- keycloak_authentication - fix authentification config duplication for Keycloak
< 26.2.0 (https://github.com/ansible-collections/community.general/pull/9987).
- keycloak_client - fix the idempotency regression by normalizing the Keycloak
response for ``after_client`` (https://github.com/ansible-collections/community.general/issues/9905,
https://github.com/ansible-collections/community.general/pull/9976).
- proxmox inventory plugin - fix ``ansible_host`` staying empty for certain
Proxmox nodes (https://github.com/ansible-collections/community.general/issues/5906,
https://github.com/ansible-collections/community.general/pull/9952).
- proxmox_disk - fail gracefully if ``storage`` is required but not provided
by the user (https://github.com/ansible-collections/community.general/issues/9941,
https://github.com/ansible-collections/community.general/pull/9963).
- reveal_ansible_type filter plugin and ansible_type test plugin - make compatible
with ansible-core's Data Tagging feature (https://github.com/ansible-collections/community.general/pull/9833).
- sysrc - no longer always reporting ``changed=true`` when ``state=absent``.
This fixes the method ``exists()`` (https://github.com/ansible-collections/community.general/issues/10004,
https://github.com/ansible-collections/community.general/pull/10005).
- yaml callback plugin - use ansible-core internals to avoid breakage with
Data Tagging (https://github.com/ansible-collections/community.general/pull/9833).
known_issues:
- reveal_ansible_type filter plugin and ansible_type test plugin - note that
ansible-core's Data Tagging feature implements new aliases, such as ``_AnsibleTaggedStr``
for ``str``, ``_AnsibleTaggedInt`` for ``int``, and ``_AnsibleTaggedFloat``
for ``float`` (https://github.com/ansible-collections/community.general/pull/9833).
minor_changes:
- apache2_module - added workaround for new PHP module name, from ``php7_module``
to ``php_module`` (https://github.com/ansible-collections/community.general/pull/9951).
release_summary: Regular bugfix release.
fragments:
- 10005-fix-method-exists-in-sysrc.yml
- 10011-github_deploy_key-check-key-present.yml
- 9.5.7.yml
- 9833-data-tagging.yml
- 9951-mod-php-identifier.yml
- 9952-proxmox-inventory-plugin-improve-ansible_host.yml
- 9963-proxmox_disk-storage.yml
- 9976-keycloak_client-fix-idempotency-regression.yml
- 9987-keycloak-auth-flow-fix-config.yaml
- 9992-filtertypeerror.yml
release_date: '2025-04-21'
9.5.8:
changes:
bugfixes:
- cobbler_system - fix bug with Cobbler >= 3.4.0 caused by giving more than
2 positional arguments to ``CobblerXMLRPCInterface.get_system_handle()``
(https://github.com/ansible-collections/community.general/issues/8506, https://github.com/ansible-collections/community.general/pull/10145).
- kdeconfig - allow option values beginning with a dash (https://github.com/ansible-collections/community.general/issues/10127,
https://github.com/ansible-collections/community.general/pull/10128).
- keycloak_user_rolemapping - fix ``--diff`` mode (https://github.com/ansible-collections/community.general/issues/10067,
https://github.com/ansible-collections/community.general/pull/10075).
- pickle cache plugin - avoid extra JSON serialization with ansible-core >=
2.19 (https://github.com/ansible-collections/community.general/pull/10136).
- rundeck_acl_policy - ensure that project ACLs are sent to the correct endpoint
(https://github.com/ansible-collections/community.general/pull/10097).
- sysrc - split the output of ``sysrc -e -a`` on the first ``=`` only (https://github.com/ansible-collections/community.general/issues/10120,
https://github.com/ansible-collections/community.general/pull/10121).
release_summary: Regular bugfix release.
fragments:
- 10075-keycloak_user_rolemapping-diff.yml
- 10097-fix-rundeck_acl_policy-project-endpoint.yml
- 10121-sysrc-fix-split-first-separator.yml
- 10128-mark-end-of-options.yml
- 10136-cache-pickle-json.yml
- 10145-fix-typeerror-cobbler-xmlrpc.yml
- 9.5.8.yml
release_date: '2025-05-19'

View File

@@ -65,7 +65,7 @@ All three statements are equivalent and give:
.. note:: Be aware that in most cases, filter calls without any argument require ``flatten=true``, otherwise the input is returned as result. The reason for this is, that the input is considered as a variable argument and is wrapped by an additional outer list. ``flatten=true`` ensures that this list is removed before the input is processed by the filter logic.
The filters ansplugin:`community.general.lists_difference#filter` or :ansplugin:`community.general.lists_symmetric_difference#filter` can be used in the same way as the filters in the examples above. They calculate the difference or the symmetric difference between two or more lists and preserve the item order.
The filters :ansplugin:`community.general.lists_difference#filter` or :ansplugin:`community.general.lists_symmetric_difference#filter` can be used in the same way as the filters in the examples above. They calculate the difference or the symmetric difference between two or more lists and preserve the item order.
For example, the symmetric difference of ``A``, ``B`` and ``C`` may be written as:

View File

@@ -124,7 +124,7 @@ To get a hash map with all ports and names of a cluster:
var: item
loop: "{{ domain_definition | community.general.json_query(server_name_cluster1_query) }}"
vars:
server_name_cluster1_query: "domain.server[?cluster=='cluster2'].{name: name, port: port}"
server_name_cluster1_query: "domain.server[?cluster=='cluster1'].{name: name, port: port}"
To extract ports from all clusters with name starting with 'server1':

View File

@@ -5,7 +5,7 @@
namespace: community
name: general
version: 9.5.4
version: 9.5.8
readme: README.md
authors:
- Ansible (https://github.com/ansible)

38
noxfile.py Normal file
View File

@@ -0,0 +1,38 @@
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2025 Felix Fontein <felix@fontein.de>
# /// script
# dependencies = ["nox>=2025.02.09", "antsibull-nox"]
# ///
import sys
import nox
try:
import antsibull_nox
except ImportError:
print("You need to install antsibull-nox in the same Python environment as nox.")
sys.exit(1)
antsibull_nox.load_antsibull_nox_toml()
@nox.session(name="aliases", python=False, default=True)
def aliases(session: nox.Session) -> None:
session.run("python", "tests/sanity/extra/aliases.py")
@nox.session(name="botmeta", default=True)
def botmeta(session: nox.Session) -> None:
session.install("PyYAML", "voluptuous")
session.run("python", "tests/sanity/extra/botmeta.py")
# Allow to run the noxfile with `python noxfile.py`, `pipx run noxfile.py`, or similar.
# Requires nox >= 2025.02.09
if __name__ == "__main__":
nox.main()

View File

@@ -57,6 +57,7 @@ class CacheModule(BaseFileCacheModule):
"""
A caching module backed by pickle files.
"""
_persistent = False # prevent unnecessary JSON serialization and key munging
def _load(self, filepath):
# Pickle is a binary format

View File

@@ -786,6 +786,12 @@ from ansible.vars.manager import VariableManager
from ansible.plugins.callback.default import CallbackModule as Default
from ansible.module_utils.common.text.converters import to_text
try:
from ansible.template import trust_as_template # noqa: F401, pylint: disable=unused-import
SUPPORTS_DATA_TAGGING = True
except ImportError:
SUPPORTS_DATA_TAGGING = False
class DummyStdout(object):
def flush(self):
@@ -839,7 +845,10 @@ class CallbackModule(Default):
return _ret
def _using_diy(self, spec):
return (spec['msg'] is not None) and (spec['msg'] != spec['vars']['omit'])
sentinel = object()
omit = spec['vars'].get('omit', sentinel)
# With Data Tagging, omit is sentinel
return (spec['msg'] is not None) and (spec['msg'] != omit or omit is sentinel)
def _parent_has_callback(self):
return hasattr(super(CallbackModule, self), sys._getframe(1).f_code.co_name)
@@ -895,7 +904,7 @@ class CallbackModule(Default):
)
_ret.update(_all)
_ret.update(_ret.get(self.DIY_NS, {self.DIY_NS: CallbackDIYDict()}))
_ret.update(_ret.get(self.DIY_NS, {self.DIY_NS: {} if SUPPORTS_DATA_TAGGING else CallbackDIYDict()}))
_ret[self.DIY_NS].update({'playbook': {}})
_playbook_attributes = ['entries', 'file_name', 'basedir']

View File

@@ -49,29 +49,77 @@ def should_use_block(value):
return False
class MyDumper(AnsibleDumper):
def represent_scalar(self, tag, value, style=None):
"""Uses block style for multi-line strings"""
if style is None:
if should_use_block(value):
style = '|'
# we care more about readable than accuracy, so...
# ...no trailing space
value = value.rstrip()
# ...and non-printable characters
value = ''.join(x for x in value if x in string.printable or ord(x) >= 0xA0)
# ...tabs prevent blocks from expanding
value = value.expandtabs()
# ...and odd bits of whitespace
value = re.sub(r'[\x0b\x0c\r]', '', value)
# ...as does trailing space
value = re.sub(r' +\n', '\n', value)
else:
style = self.default_style
node = yaml.representer.ScalarNode(tag, value, style=style)
if self.alias_key is not None:
self.represented_objects[self.alias_key] = node
return node
try:
class MyDumper(AnsibleDumper): # pylint: disable=inherit-non-class
def represent_scalar(self, tag, value, style=None):
"""Uses block style for multi-line strings"""
if style is None:
if should_use_block(value):
style = '|'
# we care more about readable than accuracy, so...
# ...no trailing space
value = value.rstrip()
# ...and non-printable characters
value = ''.join(x for x in value if x in string.printable or ord(x) >= 0xA0)
# ...tabs prevent blocks from expanding
value = value.expandtabs()
# ...and odd bits of whitespace
value = re.sub(r'[\x0b\x0c\r]', '', value)
# ...as does trailing space
value = re.sub(r' +\n', '\n', value)
else:
style = self.default_style
node = yaml.representer.ScalarNode(tag, value, style=style)
if self.alias_key is not None:
self.represented_objects[self.alias_key] = node
return node
except: # noqa: E722, pylint: disable=bare-except
# This happens with Data Tagging, see https://github.com/ansible/ansible/issues/84781
# Until there is a better solution we'll resort to using ansible-core internals.
from ansible._internal._yaml import _dumper
import typing as t
class MyDumper(_dumper._BaseDumper):
# This code is mostly taken from ansible._internal._yaml._dumper
@classmethod
def _register_representers(cls) -> None:
cls.add_multi_representer(_dumper.AnsibleTaggedObject, cls.represent_ansible_tagged_object)
cls.add_multi_representer(_dumper.Tripwire, cls.represent_tripwire)
cls.add_multi_representer(_dumper.c.Mapping, _dumper.SafeRepresenter.represent_dict)
cls.add_multi_representer(_dumper.c.Sequence, _dumper.SafeRepresenter.represent_list)
def represent_ansible_tagged_object(self, data):
if ciphertext := _dumper.VaultHelper.get_ciphertext(data, with_tags=False):
return self.represent_scalar('!vault', ciphertext, style='|')
return self.represent_data(_dumper.AnsibleTagHelper.as_native_type(data)) # automatically decrypts encrypted strings
def represent_tripwire(self, data: _dumper.Tripwire) -> t.NoReturn:
data.trip()
# The following function is the same as in the try/except
def represent_scalar(self, tag, value, style=None):
"""Uses block style for multi-line strings"""
if style is None:
if should_use_block(value):
style = '|'
# we care more about readable than accuracy, so...
# ...no trailing space
value = value.rstrip()
# ...and non-printable characters
value = ''.join(x for x in value if x in string.printable or ord(x) >= 0xA0)
# ...tabs prevent blocks from expanding
value = value.expandtabs()
# ...and odd bits of whitespace
value = re.sub(r'[\x0b\x0c\r]', '', value)
# ...as does trailing space
value = re.sub(r' +\n', '\n', value)
else:
style = self.default_style
node = yaml.representer.ScalarNode(tag, value, style=style)
if self.alias_key is not None:
self.represented_objects[self.alias_key] = node
return node
class CallbackModule(Default):

View File

@@ -10,12 +10,16 @@ __metaclass__ = type
from ansible.errors import (
AnsibleError,
AnsibleFilterError,
AnsibleFilterTypeError,
)
from ansible.module_utils.common.text.converters import to_native
from ansible.module_utils.common.collections import is_sequence
try:
from ansible.errors import AnsibleTypeError
except ImportError:
from ansible.errors import AnsibleFilterTypeError as AnsibleTypeError
try:
from hashids import Hashids
HAS_HASHIDS = True
@@ -64,7 +68,7 @@ def hashids_encode(nums, salt=None, alphabet=None, min_length=None):
try:
hashid = hashids.encode(*nums)
except TypeError as e:
raise AnsibleFilterTypeError(
raise AnsibleTypeError(
"Data to encode must by a tuple or list of ints: %s" % to_native(e)
)

View File

@@ -23,93 +23,107 @@ DOCUMENTATION = '''
type: dictionary
'''
EXAMPLES = '''
# Substitution converts str to AnsibleUnicode
# -------------------------------------------
EXAMPLES = r"""
# Substitution converts str to AnsibleUnicode or _AnsibleTaggedStr
# ----------------------------------------------------------------
# String. AnsibleUnicode.
data: "abc"
result: '{{ data | community.general.reveal_ansible_type }}'
# result => AnsibleUnicode
# String. AnsibleUnicode or _AnsibleTaggedStr.
- data: "abc"
result: '{{ data | community.general.reveal_ansible_type }}'
# result => AnsibleUnicode (or _AnsibleTaggedStr)
# String. AnsibleUnicode alias str.
alias: {"AnsibleUnicode": "str"}
data: "abc"
result: '{{ data | community.general.reveal_ansible_type(alias) }}'
# String. AnsibleUnicode/_AnsibleTaggedStr alias str.
- alias: {"AnsibleUnicode": "str", "_AnsibleTaggedStr": "str"}
data: "abc"
result: '{{ data | community.general.reveal_ansible_type(alias) }}'
# result => str
# List. All items are AnsibleUnicode.
data: ["a", "b", "c"]
result: '{{ data | community.general.reveal_ansible_type }}'
# result => list[AnsibleUnicode]
# List. All items are AnsibleUnicode/_AnsibleTaggedStr.
- data: ["a", "b", "c"]
result: '{{ data | community.general.reveal_ansible_type }}'
# result => list[AnsibleUnicode] or list[_AnsibleTaggedStr]
# Dictionary. All keys are AnsibleUnicode. All values are AnsibleUnicode.
data: {"a": "foo", "b": "bar", "c": "baz"}
result: '{{ data | community.general.reveal_ansible_type }}'
# result => dict[AnsibleUnicode, AnsibleUnicode]
# Dictionary. All keys and values are AnsibleUnicode/_AnsibleTaggedStr.
- data: {"a": "foo", "b": "bar", "c": "baz"}
result: '{{ data | community.general.reveal_ansible_type }}'
# result => dict[AnsibleUnicode, AnsibleUnicode] or dict[_AnsibleTaggedStr, _AnsibleTaggedStr]
# No substitution and no alias. Type of strings is str
# ----------------------------------------------------
# String
result: '{{ "abc" | community.general.reveal_ansible_type }}'
- result: '{{ "abc" | community.general.reveal_ansible_type }}'
# result => str
# Integer
result: '{{ 123 | community.general.reveal_ansible_type }}'
- result: '{{ 123 | community.general.reveal_ansible_type }}'
# result => int
# Float
result: '{{ 123.45 | community.general.reveal_ansible_type }}'
- result: '{{ 123.45 | community.general.reveal_ansible_type }}'
# result => float
# Boolean
result: '{{ true | community.general.reveal_ansible_type }}'
- result: '{{ true | community.general.reveal_ansible_type }}'
# result => bool
# List. All items are strings.
result: '{{ ["a", "b", "c"] | community.general.reveal_ansible_type }}'
- result: '{{ ["a", "b", "c"] | community.general.reveal_ansible_type }}'
# result => list[str]
# List of dictionaries.
result: '{{ [{"a": 1}, {"b": 2}] | community.general.reveal_ansible_type }}'
- result: '{{ [{"a": 1}, {"b": 2}] | community.general.reveal_ansible_type }}'
# result => list[dict]
# Dictionary. All keys are strings. All values are integers.
result: '{{ {"a": 1} | community.general.reveal_ansible_type }}'
- result: '{{ {"a": 1} | community.general.reveal_ansible_type }}'
# result => dict[str, int]
# Dictionary. All keys are strings. All values are integers.
result: '{{ {"a": 1, "b": 2} | community.general.reveal_ansible_type }}'
- result: '{{ {"a": 1, "b": 2} | community.general.reveal_ansible_type }}'
# result => dict[str, int]
# Type of strings is AnsibleUnicode or str
# ----------------------------------------
# Type of strings is AnsibleUnicode, _AnsibleTaggedStr, or str
# ------------------------------------------------------------
# Dictionary. The keys are integers or strings. All values are strings.
alias: {"AnsibleUnicode": "str"}
data: {1: 'a', 'b': 'b'}
result: '{{ data | community.general.reveal_ansible_type(alias) }}'
- alias:
AnsibleUnicode: str
_AnsibleTaggedStr: str
_AnsibleTaggedInt: int
data: {1: 'a', 'b': 'b'}
result: '{{ data | community.general.reveal_ansible_type(alias) }}'
# result => dict[int|str, str]
# Dictionary. All keys are integers. All values are keys.
alias: {"AnsibleUnicode": "str"}
data: {1: 'a', 2: 'b'}
result: '{{ data | community.general.reveal_ansible_type(alias) }}'
- alias:
AnsibleUnicode: str
_AnsibleTaggedStr: str
_AnsibleTaggedInt: int
data: {1: 'a', 2: 'b'}
result: '{{ data | community.general.reveal_ansible_type(alias) }}'
# result => dict[int, str]
# Dictionary. All keys are strings. Multiple types values.
alias: {"AnsibleUnicode": "str"}
data: {'a': 1, 'b': 1.1, 'c': 'abc', 'd': True, 'e': ['x', 'y', 'z'], 'f': {'x': 1, 'y': 2}}
result: '{{ data | community.general.reveal_ansible_type(alias) }}'
- alias:
AnsibleUnicode: str
_AnsibleTaggedStr: str
_AnsibleTaggedInt: int
_AnsibleTaggedFloat: float
data: {'a': 1, 'b': 1.1, 'c': 'abc', 'd': true, 'e': ['x', 'y', 'z'], 'f': {'x': 1, 'y': 2}}
result: '{{ data | community.general.reveal_ansible_type(alias) }}'
# result => dict[str, bool|dict|float|int|list|str]
# List. Multiple types items.
alias: {"AnsibleUnicode": "str"}
data: [1, 2, 1.1, 'abc', True, ['x', 'y', 'z'], {'x': 1, 'y': 2}]
result: '{{ data | community.general.reveal_ansible_type(alias) }}'
- alias:
AnsibleUnicode: str
_AnsibleTaggedStr: str
_AnsibleTaggedInt: int
_AnsibleTaggedFloat: float
data: [1, 2, 1.1, 'abc', true, ['x', 'y', 'z'], {'x': 1, 'y': 2}]
result: '{{ data | community.general.reveal_ansible_type(alias) }}'
# result => list[bool|dict|float|int|list|str]
'''
"""
RETURN = '''
_value:
@@ -123,6 +137,7 @@ from ansible_collections.community.general.plugins.plugin_utils.ansible_type imp
def reveal_ansible_type(data, alias=None):
"""Returns data type"""
# TODO: expose use_native_type parameter
return _ansible_type(data, alias)

View File

@@ -5,7 +5,7 @@
DOCUMENTATION:
name: to_days
short_description: Converte a duration string to days
short_description: Converts a duration string to days
version_added: 0.2.0
description:
- Parse a human readable time duration string and convert to days.

View File

@@ -5,7 +5,7 @@
DOCUMENTATION:
name: to_hours
short_description: Converte a duration string to hours
short_description: Converts a duration string to hours
version_added: 0.2.0
description:
- Parse a human readable time duration string and convert to hours.

View File

@@ -5,7 +5,7 @@
DOCUMENTATION:
name: to_milliseconds
short_description: Converte a duration string to milliseconds
short_description: Converts a duration string to milliseconds
version_added: 0.2.0
description:
- Parse a human readable time duration string and convert to milliseconds.

View File

@@ -5,7 +5,7 @@
DOCUMENTATION:
name: to_minutes
short_description: Converte a duration string to minutes
short_description: Converts a duration string to minutes
version_added: 0.2.0
description:
- Parse a human readable time duration string and convert to minutes.

View File

@@ -5,7 +5,7 @@
DOCUMENTATION:
name: to_months
short_description: Converte a duration string to months
short_description: Convert a duration string to months
version_added: 0.2.0
description:
- Parse a human readable time duration string and convert to months.

View File

@@ -5,7 +5,7 @@
DOCUMENTATION:
name: to_seconds
short_description: Converte a duration string to seconds
short_description: Converts a duration string to seconds
version_added: 0.2.0
description:
- Parse a human readable time duration string and convert to seconds.

View File

@@ -5,7 +5,7 @@
DOCUMENTATION:
name: to_time_unit
short_description: Converte a duration string to the given time unit
short_description: Converts a duration string to the given time unit
version_added: 0.2.0
description:
- Parse a human readable time duration string and convert to the given time unit.

View File

@@ -5,7 +5,7 @@
DOCUMENTATION:
name: to_weeks
short_description: Converte a duration string to weeks
short_description: Converts a duration string to weeks
version_added: 0.2.0
description:
- Parse a human readable time duration string and convert to weeks.

View File

@@ -5,7 +5,7 @@
DOCUMENTATION:
name: to_years
short_description: Converte a duration string to years
short_description: Converts a duration string to years
version_added: 0.2.0
description:
- Parse a human readable time duration string and convert to years.

View File

@@ -49,9 +49,14 @@ RETURN = '''
from unicodedata import normalize
from ansible.errors import AnsibleFilterError, AnsibleFilterTypeError
from ansible.errors import AnsibleFilterError
from ansible.module_utils.six import text_type
try:
from ansible.errors import AnsibleTypeError
except ImportError:
from ansible.errors import AnsibleFilterTypeError as AnsibleTypeError
def unicode_normalize(data, form='NFC'):
"""Applies normalization to 'unicode' strings.
@@ -66,7 +71,7 @@ def unicode_normalize(data, form='NFC'):
"""
if not isinstance(data, text_type):
raise AnsibleFilterTypeError("%s is not a valid input type" % type(data))
raise AnsibleTypeError("%s is not a valid input type" % type(data))
if form not in ('NFC', 'NFD', 'NFKC', 'NFKD'):
raise AnsibleFilterError("%s is not a valid form" % form)

View File

@@ -304,12 +304,17 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
def _get_json(self, url, ignore_errors=None):
if not self.use_cache or url not in self._cache.get(self.cache_key, {}):
data = []
has_data = False
if self.cache_key not in self._cache:
self._cache[self.cache_key] = {'url': ''}
if self.use_cache:
try:
data = self._cache[self.cache_key][url]
has_data = True
except KeyError:
self.update_cache = True
data = []
if not has_data:
s = self._get_session()
while True:
ret = s.get(url, headers=self.headers)
@@ -335,9 +340,8 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
data = data + json['data']
break
self._cache[self.cache_key][url] = data
return make_unsafe(self._cache[self.cache_key][url])
self._results[url] = data
return make_unsafe(data)
def _get_nodes(self):
return self._get_json("%s/api2/json/nodes" % self.proxmox_url)
@@ -358,11 +362,26 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
def _get_node_ip(self, node):
ret = self._get_json("%s/api2/json/nodes/%s/network" % (self.proxmox_url, node))
# sort interface by iface name to make selection as stable as possible
ret.sort(key=lambda x: x['iface'])
for iface in ret:
try:
# only process interfaces adhering to these rules
if 'active' not in iface:
self.display.vvv(f"Interface {iface['iface']} on node {node} does not have an active state")
continue
if 'address' not in iface:
self.display.vvv(f"Interface {iface['iface']} on node {node} does not have an address")
continue
if 'gateway' not in iface:
self.display.vvv(f"Interface {iface['iface']} on node {node} does not have a gateway")
continue
self.display.vv(f"Using interface {iface['iface']} on node {node} with address {iface['address']} as node ip for ansible_host")
return iface['address']
except Exception:
return None
continue
return None
def _get_lxc_interfaces(self, properties, node, vmid):
status_key = self._fact('status')
@@ -678,10 +697,14 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
self.exclude_nodes = self.get_option('exclude_nodes')
self.cache_key = self.get_cache_key(path)
self.use_cache = cache and self.get_option('cache')
self.update_cache = not cache and self.get_option('cache')
self.host_filters = self.get_option('filters')
self.group_prefix = self.get_option('group_prefix')
self.facts_prefix = self.get_option('facts_prefix')
self.strict = self.get_option('strict')
# actually populate inventory
self._results = {}
self._populate()
if self.update_cache:
self._cache[self.cache_key] = self._results

View File

@@ -130,12 +130,24 @@ from ansible.template import Templar
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
try:
from ansible.template import trust_as_template as _trust_as_template
HAS_DATATAGGING = True
except ImportError:
HAS_DATATAGGING = False
# Whether Templar has a cache, which can be controlled by Templar.template()'s cache option.
# The cache was removed for ansible-core 2.14 (https://github.com/ansible/ansible/pull/78419)
_TEMPLAR_HAS_TEMPLATE_CACHE = LooseVersion(ansible_version) < LooseVersion('2.14.0')
def _make_safe(value):
if HAS_DATATAGGING and isinstance(value, str):
return _trust_as_template(value)
return value
class LookupModule(LookupBase):
def __evaluate(self, expression, templar, variables):
"""Evaluate expression with templar.
@@ -144,10 +156,13 @@ class LookupModule(LookupBase):
``variables`` are the variables to use.
"""
templar.available_variables = variables or {}
expression = "{0}{1}{2}".format("{{", expression, "}}")
quoted_expression = "{0}{1}{2}".format("{{", expression, "}}")
if _TEMPLAR_HAS_TEMPLATE_CACHE:
return templar.template(expression, cache=False)
return templar.template(expression)
return templar.template(quoted_expression, cache=False)
if hasattr(templar, 'evaluate_expression'):
# This is available since the Data Tagging PR has been merged
return templar.evaluate_expression(_make_safe(expression))
return templar.template(quoted_expression)
def __process(self, result, terms, index, current, templar, variables):
"""Fills ``result`` list with evaluated items.

View File

@@ -578,16 +578,20 @@ class LookupModule(LookupBase):
for term in terms:
self.parse_params(term) # parse the input into paramvals
with self.opt_lock('readwrite'):
if self.check_pass(): # password exists
if self.paramvals['overwrite']:
if self.check_pass(): # password file exists
if self.paramvals['overwrite']: # if "overwrite", always update password
with self.opt_lock('write'):
result.append(self.update_password())
elif self.paramvals["subkey"] != "password" and not self.passdict.get(self.paramvals['subkey']): # password exists but not the subkey
elif (
self.paramvals["subkey"] != "password"
and not self.passdict.get(self.paramvals["subkey"])
and self.paramvals["missing"] == "create"
): # target is a subkey, this subkey is not in passdict BUT missing == create
with self.opt_lock('write'):
result.append(self.update_password())
else:
result.append(self.get_passresult())
else: # password does not exist
else: # password does not exist
if self.paramvals['missing'] == 'create':
with self.opt_lock('write'):
if self.locked == 'write' and self.check_pass(): # lookup password again if under write lock

View File

@@ -2228,6 +2228,23 @@ class KeycloakAPI(object):
except Exception as e:
self.fail_open_url(e, msg="Unable to add authenticationConfig %s: %s" % (executionId, str(e)))
def delete_authentication_config(self, configId, realm='master'):
""" Delete authenticator config
:param configId: id of authentication config
:param realm: realm of authentication config to be deleted
"""
try:
# Send a DELETE request to remove the specified authentication config from the Keycloak server.
self._request(
URL_AUTHENTICATION_CONFIG.format(
url=self.baseurl,
realm=realm,
id=configId),
method='DELETE')
except Exception as e:
self.fail_request(e, msg="Unable to delete authentication config %s: %s" % (configId, str(e)))
def create_subflow(self, subflowName, flowAlias, realm='master', flowType='basic-flow'):
""" Create new sublow on the flow

View File

@@ -18,10 +18,11 @@ description:
- Set and/or get members' attributes of an Apache httpd 2.4 mod_proxy balancer
pool, using HTTP POST and GET requests. The httpd mod_proxy balancer-member
status page has to be enabled and accessible, as this module relies on parsing
this page. This module supports ansible check_mode, and requires BeautifulSoup
python module.
this page.
extends_documentation_fragment:
- community.general.attributes
requirements:
- Python package C(BeautifulSoup) on Python 2, C(beautifulsoup4) on Python 3.
attributes:
check_mode:
support: full
@@ -207,12 +208,16 @@ import re
import traceback
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
from ansible.module_utils.common.text.converters import to_text
from ansible.module_utils.urls import fetch_url
from ansible.module_utils.six import iteritems
from ansible.module_utils.six import iteritems, PY2
BEAUTIFUL_SOUP_IMP_ERR = None
try:
from BeautifulSoup import BeautifulSoup
if PY2:
from BeautifulSoup import BeautifulSoup
else:
from bs4 import BeautifulSoup
except ImportError:
BEAUTIFUL_SOUP_IMP_ERR = traceback.format_exc()
HAS_BEAUTIFULSOUP = False
@@ -220,9 +225,15 @@ else:
HAS_BEAUTIFULSOUP = True
# balancer member attributes extraction regexp:
EXPRESSION = r"(b=([\w\.\-]+)&w=(https?|ajp|wss?|ftp|[sf]cgi)://([\w\.\-]+):?(\d*)([/\w\.\-]*)&?[\w\-\=]*)"
EXPRESSION = to_text(r"(b=([\w\.\-]+)&w=(https?|ajp|wss?|ftp|[sf]cgi)://([\w\.\-]+):?(\d*)([/\w\.\-]*)&?[\w\-\=]*)")
# Apache2 server version extraction regexp:
APACHE_VERSION_EXPRESSION = r"SERVER VERSION: APACHE/([\d.]+)"
APACHE_VERSION_EXPRESSION = to_text(r"SERVER VERSION: APACHE/([\d.]+)")
def find_all(where, what):
if PY2:
return where.findAll(what)
return where.find_all(what)
def regexp_extraction(string, _regexp, groups=1):
@@ -262,7 +273,7 @@ class BalancerMember(object):
def get_member_attributes(self):
""" Returns a dictionary of a balancer member's attributes."""
balancer_member_page = fetch_url(self.module, self.management_url)
balancer_member_page = fetch_url(self.module, self.management_url, headers={'Referer': self.management_url})
if balancer_member_page[1]['status'] != 200:
self.module.fail_json(msg="Could not get balancer_member_page, check for connectivity! " + balancer_member_page[1])
@@ -272,11 +283,11 @@ class BalancerMember(object):
except TypeError as exc:
self.module.fail_json(msg="Cannot parse balancer_member_page HTML! " + str(exc))
else:
subsoup = soup.findAll('table')[1].findAll('tr')
keys = subsoup[0].findAll('th')
subsoup = find_all(find_all(soup, 'table')[1], 'tr')
keys = find_all(subsoup[0], 'th')
for valuesset in subsoup[1::1]:
if re.search(pattern=self.host, string=str(valuesset)):
values = valuesset.findAll('td')
values = find_all(valuesset, 'td')
return {keys[x].string: values[x].string for x in range(0, len(keys))}
def get_member_status(self):
@@ -300,9 +311,9 @@ class BalancerMember(object):
values_url = "".join("{0}={1}".format(url_param, 1 if values[mode] else 0) for mode, url_param in iteritems(values_mapping))
request_body = "{0}{1}".format(request_body, values_url)
response = fetch_url(self.module, self.management_url, data=request_body)
response = fetch_url(self.module, self.management_url, data=request_body, headers={'Referer': self.management_url})
if response[1]['status'] != 200:
self.module.fail_json(msg="Could not set the member status! " + self.host + " " + response[1]['status'])
self.module.fail_json(msg="Could not set the member status! {host} {status}".format(host=self.host, status=response[1]['status']))
attributes = property(get_member_attributes)
status = property(get_member_status, set_member_status)
@@ -329,11 +340,15 @@ class Balancer(object):
if page[1]['status'] != 200:
self.module.fail_json(msg="Could not get balancer page! HTTP status response: " + str(page[1]['status']))
else:
content = page[0].read()
content = to_text(page[0].read())
apache_version = regexp_extraction(content.upper(), APACHE_VERSION_EXPRESSION, 1)
if apache_version:
if not re.search(pattern=r"2\.4\.[\d]*", string=apache_version):
self.module.fail_json(msg="This module only acts on an Apache2 2.4+ instance, current Apache2 version: " + str(apache_version))
self.module.fail_json(
msg="This module only acts on an Apache2 2.4+ instance, current Apache2 version: {version}".format(
version=apache_version
)
)
return content
else:
self.module.fail_json(msg="Could not get the Apache server version from the balancer-manager")
@@ -345,7 +360,8 @@ class Balancer(object):
except TypeError:
self.module.fail_json(msg="Cannot parse balancer page HTML! " + str(self.page))
else:
for element in soup.findAll('a')[1::1]:
elements = find_all(soup, 'a')
for element in elements[1::1]:
balancer_member_suffix = str(element.get('href'))
if not balancer_member_suffix:
self.module.fail_json(msg="Argument 'balancer_member_suffix' is empty!")

View File

@@ -196,6 +196,7 @@ def create_apache_identifier(name):
# re expressions to extract subparts of names
re_workarounds = [
('php8', re.compile(r'^(php)[\d\.]+')),
('php', re.compile(r'^(php\d)\.')),
]

View File

@@ -511,6 +511,9 @@ class CloudflareAPI(object):
try:
content = resp.read()
except AttributeError:
content = None
if not content:
if info['body']:
content = info['body']
else:
@@ -645,6 +648,7 @@ class CloudflareAPI(object):
else:
search_value = content
zone_id = self._get_zone_id(params['zone'])
records = self.get_dns_records(params['zone'], params['type'], search_record, search_value)
for rr in records:
@@ -652,11 +656,11 @@ class CloudflareAPI(object):
if not ((rr['type'] == params['type']) and (rr['name'] == search_record) and (rr['content'] == content)):
self.changed = True
if not self.module.check_mode:
result, info = self._cf_api_call('/zones/{0}/dns_records/{1}'.format(rr['zone_id'], rr['id']), 'DELETE')
result, info = self._cf_api_call('/zones/{0}/dns_records/{1}'.format(zone_id, rr['id']), 'DELETE')
else:
self.changed = True
if not self.module.check_mode:
result, info = self._cf_api_call('/zones/{0}/dns_records/{1}'.format(rr['zone_id'], rr['id']), 'DELETE')
result, info = self._cf_api_call('/zones/{0}/dns_records/{1}'.format(zone_id, rr['id']), 'DELETE')
return self.changed
def ensure_dns_record(self, **kwargs):

View File

@@ -162,6 +162,8 @@ from ansible.module_utils.common.text.converters import to_text
from ansible_collections.community.general.plugins.module_utils.datetime import (
now,
)
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
IFPROPS_MAPPING = dict(
bondingopts='bonding_opts',
@@ -279,7 +281,11 @@ def main():
if system:
# Update existing entry
system_id = conn.get_system_handle(name, token)
system_id = None
if LooseVersion(str(conn.version())) >= LooseVersion('3.4.0'):
system_id = conn.get_system_handle(name)
else:
system_id = conn.get_system_handle(name, token)
for key, value in iteritems(module.params['properties']):
if key not in system:

View File

@@ -225,7 +225,7 @@ def normalize_link_obj(api_obj, module_obj, key):
for obj in module_objs:
identifier = obj.get("ID")
name = obj.get("Name)")
name = obj.get("Name")
if identifier and not name and identifier in id_to_name:
obj["Name"] = id_to_name[identifier]
if not identifier and name and name in name_to_id:

View File

@@ -78,6 +78,13 @@ EXAMPLES = r"""
community.general.copr:
state: absent
name: '@copr/integration_tests'
- name: Install Caddy
community.general.copr:
name: '@caddy/caddy'
chroot: fedora-rawhide-{{ ansible_facts.architecture }}
includepkgs:
- caddy
"""
RETURN = r"""

View File

@@ -77,7 +77,7 @@ EXAMPLES = r'''
state: opts_present
opts: discard
loop: '{{ ansible_mounts }}'
when: "'/dev/mapper/luks-' in {{ item.device }}"
when: "'/dev/mapper/luks-' in item.device"
'''
import os

View File

@@ -235,6 +235,43 @@ def get_packages(module, patterns, only_installed=False):
return packages_available_map_name_evrs
def get_package_mgr():
for bin_path in (DNF_BIN,):
if os.path.exists(bin_path):
return "dnf5" if os.path.realpath(bin_path) == "/usr/bin/dnf5" else "dnf"
# fallback to dnf
return "dnf"
def get_package_list(module, package_mgr="dnf"):
if package_mgr == "dnf":
return do_versionlock(module, "list").split()
package_list = []
if package_mgr == "dnf5":
stanza_start = False
package_name = None
for line in do_versionlock(module, "list").splitlines():
if line.startswith(("#", " ")):
continue
if line.startswith("Package name:"):
stanza_start = True
dummy, name = line.split(":", 1)
name = name.strip()
pkg_name = get_packages(module, patterns=[name])
package_name = "%s-%s.*" % (name, pkg_name[name].pop())
if package_name and package_name not in package_list:
package_list.append(package_name)
if line.startswith("evr"):
dummy, package_version = line.split("=", 1)
package_version = package_version.strip()
if stanza_start:
if package_name and package_name not in package_list:
package_list.append(package_name)
stanza_start = False
return package_list
def main():
module = AnsibleModule(
argument_spec=dict(
@@ -253,9 +290,10 @@ def main():
msg = ""
# Check module pre-requisites.
if not os.path.exists(DNF_BIN):
module.fail_json(msg="%s was not found" % DNF_BIN)
if not os.path.exists(VERSIONLOCK_CONF):
global DNF_BIN
DNF_BIN = module.get_bin_path('dnf', True)
package_mgr = get_package_mgr()
if package_mgr == "dnf" and not os.path.exists(VERSIONLOCK_CONF):
module.fail_json(msg="plugin versionlock is required")
# Check incompatible options.
@@ -264,7 +302,7 @@ def main():
if state != "clean" and not patterns:
module.fail_json(msg="name list is required for %s state" % state)
locklist_pre = do_versionlock(module, "list").split()
locklist_pre = get_package_list(module, package_mgr=package_mgr)
specs_toadd = []
specs_todelete = []
@@ -343,7 +381,7 @@ def main():
"specs_todelete": specs_todelete
}
if not module.check_mode:
response["locklist_post"] = do_versionlock(module, "list").split()
response["locklist_post"] = get_package_list(module, package_mgr=package_mgr)
else:
if state == "clean":
response["locklist_post"] = []

View File

@@ -166,33 +166,38 @@ def parse_error(string):
def install_plugin(module, plugin_bin, plugin_name, version, src, url, proxy_host, proxy_port, timeout, force):
cmd_args = [plugin_bin, PACKAGE_STATE_MAP["present"]]
cmd = [plugin_bin, PACKAGE_STATE_MAP["present"]]
is_old_command = (os.path.basename(plugin_bin) == 'plugin')
# Timeout and version are only valid for plugin, not elasticsearch-plugin
if is_old_command:
if timeout:
cmd_args.append("--timeout %s" % timeout)
cmd.append("--timeout")
cmd.append(timeout)
if version:
plugin_name = plugin_name + '/' + version
cmd_args[2] = plugin_name
cmd[2] = plugin_name
if proxy_host and proxy_port:
cmd_args.append("-DproxyHost=%s -DproxyPort=%s" % (proxy_host, proxy_port))
java_opts = ["-Dhttp.proxyHost=%s" % proxy_host,
"-Dhttp.proxyPort=%s" % proxy_port,
"-Dhttps.proxyHost=%s" % proxy_host,
"-Dhttps.proxyPort=%s" % proxy_port]
module.run_command_environ_update = dict(CLI_JAVA_OPTS=" ".join(java_opts), # Elasticsearch 8.x
ES_JAVA_OPTS=" ".join(java_opts)) # Older Elasticsearch versions
# Legacy ES 1.x
if url:
cmd_args.append("--url %s" % url)
cmd.append("--url")
cmd.append(url)
if force:
cmd_args.append("--batch")
cmd.append("--batch")
if src:
cmd_args.append(src)
cmd.append(src)
else:
cmd_args.append(plugin_name)
cmd = " ".join(cmd_args)
cmd.append(plugin_name)
if module.check_mode:
rc, out, err = 0, "check mode", ""
@@ -207,9 +212,7 @@ def install_plugin(module, plugin_bin, plugin_name, version, src, url, proxy_hos
def remove_plugin(module, plugin_bin, plugin_name):
cmd_args = [plugin_bin, PACKAGE_STATE_MAP["absent"], parse_plugin_repo(plugin_name)]
cmd = " ".join(cmd_args)
cmd = [plugin_bin, PACKAGE_STATE_MAP["absent"], parse_plugin_repo(plugin_name)]
if module.check_mode:
rc, out, err = 0, "check mode", ""

View File

@@ -259,7 +259,12 @@ class GithubDeployKey(object):
key_id = response_body["id"]
self.module.exit_json(changed=True, msg="Deploy key successfully added", id=key_id)
elif status_code == 422:
self.module.exit_json(changed=False, msg="Deploy key already exists")
# there might be multiple reasons for a 422
# so we must check if the reason is that the key already exists
if self.get_existing_key():
self.module.exit_json(changed=False, msg="Deploy key already exists")
else:
self.handle_error(method="POST", info=info)
else:
self.handle_error(method="POST", info=info)

View File

@@ -425,10 +425,7 @@ class HomebrewCask(object):
cmd = base_opts + [self.current_cask]
rc, out, err = self.module.run_command(cmd)
if rc == 0:
return True
else:
return False
return rc == 0
def _get_brew_version(self):
if self.brew_version:
@@ -436,11 +433,13 @@ class HomebrewCask(object):
cmd = [self.brew_path, '--version']
rc, out, err = self.module.run_command(cmd, check_rc=True)
dummy, out, dummy = self.module.run_command(cmd, check_rc=True)
# get version string from first line of "brew --version" output
version = out.split('\n')[0].split(' ')[1]
self.brew_version = version
pattern = r"Homebrew (.*)(\d+\.\d+\.\d+)(-dirty)?"
rematch = re.search(pattern, out)
if not rematch:
self.module.fail_json(msg="Failed to match regex to get brew version", stdout=out)
self.brew_version = rematch.groups()[1]
return self.brew_version
def _brew_cask_command_is_deprecated(self):

View File

@@ -72,7 +72,7 @@ EXAMPLES = r"""
- name: Remove the foo service (equivalent to `brew services stop foo`)
community.general.homebrew_services:
name: foo
service_state: absent
state: absent
"""
RETURN = r"""

View File

@@ -272,6 +272,10 @@ def ensure(module, client):
data = {}
for key in diff:
data[key] = module_host.get(key)
if "usercertificate" not in data:
data["usercertificate"] = [
cert['__base64__'] for cert in ipa_host.get("usercertificate", [])
]
ipa_host_show = client.host_show(name=name)
if ipa_host_show.get('has_keytab', True) and (state == 'disabled' or module.params.get('random_password')):
client.host_disable(name=name)

View File

@@ -144,7 +144,7 @@ def run_kwriteconfig(module, cmd, path, groups, key, value):
else:
args.append('false')
else:
args.append(value)
args.extend(['--', value])
module.run_command(args, check_rc=True)

View File

@@ -308,6 +308,8 @@ def create_or_update_executions(kc, config, realm='master'):
}
# add the execution configuration
if new_exec["authenticationConfig"] is not None:
if "authenticationConfig" in execution and "id" in execution["authenticationConfig"]:
kc.delete_authentication_config(execution["authenticationConfig"]["id"], realm=realm)
kc.add_authenticationConfig_to_execution(updated_exec["id"], new_exec["authenticationConfig"], realm=realm)
for key in new_exec:
# remove unwanted key for the next API call

View File

@@ -782,7 +782,7 @@ end_state:
'''
from ansible_collections.community.general.plugins.module_utils.identity.keycloak.keycloak import KeycloakAPI, camel, \
keycloak_argument_spec, get_token, KeycloakError, is_struct_included
keycloak_argument_spec, get_token, KeycloakError
from ansible.module_utils.basic import AnsibleModule
import copy
@@ -820,12 +820,30 @@ def normalise_cr(clientrep, remove_ids=False):
if remove_ids:
mapper.pop('id', None)
# Convert bool to string
if 'config' in mapper:
for key, value in mapper['config'].items():
if isinstance(value, bool):
mapper['config'][key] = str(value).lower()
# Set to a default value.
mapper['consentRequired'] = mapper.get('consentRequired', False)
if 'attributes' in clientrep:
for key, value in clientrep['attributes'].items():
if isinstance(value, bool):
clientrep['attributes'][key] = str(value).lower()
clientrep['attributes'].pop('client.secret.creation.time', None)
return clientrep
def normalize_kc_resp(clientrep):
# kc drops the variable 'authorizationServicesEnabled' if set to false
# to minimize diff/changes we set it to false if not set by kc
if clientrep and 'authorizationServicesEnabled' not in clientrep:
clientrep['authorizationServicesEnabled'] = False
def sanitize_cr(clientrep):
""" Removes probably sensitive details from a client representation.
@@ -1015,6 +1033,8 @@ def main():
else:
before_client = kc.get_client_by_id(cid, realm=realm)
normalize_kc_resp(before_client)
if before_client is None:
before_client = {}
@@ -1086,7 +1106,7 @@ def main():
if module._diff:
result['diff'] = dict(before=sanitize_cr(before_norm),
after=sanitize_cr(desired_norm))
result['changed'] = not is_struct_included(desired_norm, before_norm, CLIENT_META_DATA)
result['changed'] = desired_norm != before_norm
module.exit_json(**result)
@@ -1094,6 +1114,8 @@ def main():
kc.update_client(cid, desired_client, realm=realm)
after_client = kc.get_client_by_id(cid, realm=realm)
normalize_kc_resp(after_client)
if before_client == after_client:
result['changed'] = False
if module._diff:

View File

@@ -369,7 +369,7 @@ def main():
# Assign roles
result['changed'] = True
if module._diff:
result['diff'] = dict(before=assigned_roles_before, after=update_roles)
result['diff'] = dict(before={"roles": assigned_roles_before}, after={"roles": update_roles})
if module.check_mode:
module.exit_json(**result)
kc.add_user_rolemapping(uid=uid, cid=cid, role_rep=update_roles, realm=realm)
@@ -384,7 +384,7 @@ def main():
# Remove mapping of role
result['changed'] = True
if module._diff:
result['diff'] = dict(before=assigned_roles_before, after=update_roles)
result['diff'] = dict(before={"roles": assigned_roles_before}, after={"roles": update_roles})
if module.check_mode:
module.exit_json(**result)
kc.delete_user_rolemapping(uid=uid, cid=cid, role_rep=update_roles, realm=realm)

View File

@@ -1335,7 +1335,7 @@ EXAMPLES = r'''
community.general.nmcli:
conn_name: my-eth1
state: up
reload: true
conn_reload: true
- name: Add second ip4 address
community.general.nmcli:
@@ -2416,9 +2416,11 @@ class Nmcli(object):
if isinstance(current_value, list) and isinstance(value, list):
# compare values between two lists
if key in ('ipv4.addresses', 'ipv6.addresses'):
if key in ('ipv4.addresses', 'ipv6.addresses', 'ipv4.dns', 'ipv6.dns', 'ipv4.dns-search', 'ipv6.dns-search'):
# The order of IP addresses matters because the first one
# is the default source address for outbound connections.
# Similarly, the order of DNS nameservers and search
# suffixes is important.
changed |= current_value != value
else:
changed |= sorted(current_value) != sorted(value)

View File

@@ -567,6 +567,8 @@ class ProxmoxDiskAnsible(ProxmoxAnsible):
ok_str = "CD-ROM was created on %s bus in VM %s"
else:
config_str = self.module.params["storage"]
if not config_str:
self.module.fail_json(msg="The storage option must be specified.")
if self.module.params.get("media") != "cdrom":
config_str += ":%s" % (self.module.params["size"])
ok_str = "Disk %s created in VM %s"

View File

@@ -201,7 +201,7 @@ class ProxmoxVmInfoAnsible(ProxmoxAnsible):
if desired_vm:
desired_vm.update(detected_vm)
desired_vm["vmid"] = this_vm_id
desired_vm["template"] = proxmox_to_ansible_bool(desired_vm["template"])
desired_vm["template"] = proxmox_to_ansible_bool(desired_vm.get("template", 0))
# When user wants to retrieve the VM configuration
if config != "none":
# pending = 0, current = 1

View File

@@ -589,6 +589,45 @@ class Rhsm(object):
(distro_version[0] == 9 and distro_version[1] >= 2) or
distro_version[0] > 9)):
dbus_force_option_works = True
# We need to use the 'enable_content' D-Bus option to ensure that
# content is enabled; sadly the option is available depending on the
# version of the distro, and also depending on which API/method is used
# for registration.
dbus_has_enable_content_option = False
if activationkey:
def supports_enable_content_for_activation_keys():
# subscription-manager in Fedora >= 41 has the new option.
if distro_id == 'fedora' and distro_version[0] >= 41:
return True
# Assume EL distros here.
if distro_version[0] >= 10:
return True
return False
dbus_has_enable_content_option = supports_enable_content_for_activation_keys()
else:
def supports_enable_content_for_credentials():
# subscription-manager in any supported Fedora version
# has the new option.
if distro_id == 'fedora':
return True
# Check for RHEL 8 >= 8.6, or RHEL >= 9.
if distro_id == 'rhel' and \
((distro_version[0] == 8 and distro_version[1] >= 6) or
distro_version[0] >= 9):
return True
# CentOS: similar checks as for RHEL, with one extra bit:
# if the 2nd part of the version is empty, it means it is
# CentOS Stream, and thus we can assume it has the latest
# version of subscription-manager.
if distro_id == 'centos' and \
((distro_version[0] == 8 and
(distro_version[1] >= 6 or distro_version_parts[1] == '')) or
distro_version[0] >= 9):
return True
# Unknown or old distro: assume it does not support
# the new option.
return False
dbus_has_enable_content_option = supports_enable_content_for_credentials()
if force_register and not dbus_force_option_works and was_registered:
self.unregister()
@@ -661,6 +700,8 @@ class Rhsm(object):
register_opts[environment_key] = environment
if force_register and dbus_force_option_works and was_registered:
register_opts['force'] = True
if dbus_has_enable_content_option:
register_opts['enable_content'] = "1"
# Wrap it as proper D-Bus dict
register_opts = dbus.Dictionary(register_opts, signature='sv', variant_level=1)

View File

@@ -130,11 +130,18 @@ from ansible_collections.community.general.plugins.module_utils.rundeck import (
class RundeckACLManager:
def __init__(self, module):
self.module = module
if module.params.get("project"):
self.endpoint = "project/%s/acl/%s.aclpolicy" % (
self.module.params["project"],
self.module.params["name"],
)
else:
self.endpoint = "system/acl/%s.aclpolicy" % self.module.params["name"]
def get_acl(self):
resp, info = api_request(
module=self.module,
endpoint="system/acl/%s.aclpolicy" % self.module.params["name"],
endpoint=self.endpoint,
)
return resp
@@ -148,7 +155,7 @@ class RundeckACLManager:
resp, info = api_request(
module=self.module,
endpoint="system/acl/%s.aclpolicy" % self.module.params["name"],
endpoint=self.endpoint,
method="POST",
data={"contents": self.module.params["policy"]},
)
@@ -172,7 +179,7 @@ class RundeckACLManager:
resp, info = api_request(
module=self.module,
endpoint="system/acl/%s.aclpolicy" % self.module.params["name"],
endpoint=self.endpoint,
method="PUT",
data={"contents": self.module.params["policy"]},
)
@@ -195,7 +202,7 @@ class RundeckACLManager:
if not self.module.check_mode:
api_request(
module=self.module,
endpoint="system/acl/%s.aclpolicy" % self.module.params["name"],
endpoint=self.endpoint,
method="DELETE",
)

View File

@@ -246,7 +246,7 @@ class Sudoers(object):
rc, stdout, stderr = self.module.run_command(check_command, data=self.content())
if rc != 0:
raise Exception('Failed to validate sudoers rule:\n{stdout}'.format(stdout=stdout))
self.module.fail_json(msg='Failed to validate sudoers rule:\n{stdout}'.format(stdout=stdout or stderr), stdout=stdout, stderr=stderr)
def run(self):
if self.state == 'absent':

View File

@@ -122,14 +122,19 @@ class Sysrc(object):
return err.find("unknown variable") > 0 or out.find("unknown variable") > 0
def exists(self):
# sysrc doesn't really use exit codes
(rc, out, err) = self.run_sysrc(self.name)
"""
Tests whether the name is in the file. If parameter value is defined,
then tests whether name=value is in the file. These tests are necessary
because sysrc doesn't use exit codes. Instead, let sysrc read the
file's content and create a dictionary comprising the configuration.
Use this dictionary to preform the tests.
"""
(rc, out, err) = self.run_sysrc('-e', '-a')
conf = dict([i.split('=', 1) for i in out.splitlines()])
if self.value is None:
regex = "%s: " % re.escape(self.name)
return self.name in conf
else:
regex = "%s: %s$" % (re.escape(self.name), re.escape(self.value))
return not self.has_unknown_variable(out, err) and re.match(regex, out) is not None
return self.name in conf and conf[self.name] == '"%s"' % self.value
def contains(self):
(rc, out, err) = self.run_sysrc('-n', self.name)
@@ -142,13 +147,10 @@ class Sysrc(object):
if self.exists():
return
if self.module.check_mode:
self.changed = True
return
if not self.module.check_mode:
(rc, out, err) = self.run_sysrc("%s=%s" % (self.name, self.value))
(rc, out, err) = self.run_sysrc("%s=%s" % (self.name, self.value))
if out.find("%s:" % self.name) == 0 and re.search("-> %s$" % re.escape(self.value), out) is not None:
self.changed = True
self.changed = True
def absent(self):
if not self.exists():

View File

@@ -923,29 +923,34 @@ def main():
elif LooseVersion('.'.join(to_native(f) for f in etree.LXML_VERSION)) < LooseVersion('3.0.0'):
module.warn('Using lxml version lower than 3.0.0 does not guarantee predictable element attribute order.')
# Check if the file exists
if xml_string:
infile = BytesIO(to_bytes(xml_string, errors='surrogate_or_strict'))
elif os.path.isfile(xml_file):
infile = open(xml_file, 'rb')
else:
module.fail_json(msg="The target XML source '%s' does not exist." % xml_file)
# Parse and evaluate xpath expression
if xpath is not None:
try:
etree.XPath(xpath)
except etree.XPathSyntaxError as e:
module.fail_json(msg="Syntax error in xpath expression: %s (%s)" % (xpath, e))
except etree.XPathEvalError as e:
module.fail_json(msg="Evaluation error in xpath expression: %s (%s)" % (xpath, e))
# Try to parse in the target XML file
infile = None
try:
parser = etree.XMLParser(remove_blank_text=pretty_print, strip_cdata=strip_cdata_tags)
doc = etree.parse(infile, parser)
except etree.XMLSyntaxError as e:
module.fail_json(msg="Error while parsing document: %s (%s)" % (xml_file or 'xml_string', e))
# Check if the file exists
if xml_string:
infile = BytesIO(to_bytes(xml_string, errors='surrogate_or_strict'))
elif os.path.isfile(xml_file):
infile = open(xml_file, 'rb')
else:
module.fail_json(msg="The target XML source '%s' does not exist." % xml_file)
# Parse and evaluate xpath expression
if xpath is not None:
try:
etree.XPath(xpath)
except etree.XPathSyntaxError as e:
module.fail_json(msg="Syntax error in xpath expression: %s (%s)" % (xpath, e))
except etree.XPathEvalError as e:
module.fail_json(msg="Evaluation error in xpath expression: %s (%s)" % (xpath, e))
# Try to parse in the target XML file
try:
parser = etree.XMLParser(remove_blank_text=pretty_print, strip_cdata=strip_cdata_tags)
doc = etree.parse(infile, parser)
except etree.XMLSyntaxError as e:
module.fail_json(msg="Error while parsing document: %s (%s)" % (xml_file or 'xml_string', e))
finally:
if infile:
infile.close()
# Ensure we have the original copy to compare
global orig_doc

View File

@@ -16,7 +16,8 @@ DOCUMENTATION = '''
module: yarn
short_description: Manage node.js packages with Yarn
description:
- Manage node.js packages with the Yarn package manager (https://yarnpkg.com/)
- Manage Node.js packages with the Yarn package manager U(https://yarnpkg.com/).
- Note that at the moment, this module B(only works with Yarn Classic).
author:
- "David Gunter (@verkaufer)"
- "Chris Hoffman (@chrishoffman), creator of NPM Ansible module)"
@@ -85,7 +86,7 @@ options:
default: present
choices: [ "present", "absent", "latest" ]
requirements:
- Yarn installed in bin path (typically /usr/local/bin)
- Yarn Classic installed in bin path (typically C(/usr/local/bin))
'''
EXAMPLES = '''

View File

@@ -8,17 +8,31 @@ __metaclass__ = type
from ansible.errors import AnsibleFilterError
from ansible.module_utils.common._collections_compat import Mapping
try:
# Introduced with Data Tagging (https://github.com/ansible/ansible/pull/84621):
from ansible.module_utils.datatag import native_type_name as _native_type_name
except ImportError:
_native_type_name = None
def _atype(data, alias):
def _atype(data, alias, *, use_native_type: bool = False):
"""
Returns the name of the type class.
"""
data_type = type(data).__name__
if use_native_type and _native_type_name:
data_type = _native_type_name(data)
else:
data_type = type(data).__name__
# The following types were introduced with Data Tagging (https://github.com/ansible/ansible/pull/84621):
if data_type == "_AnsibleLazyTemplateDict":
data_type = "dict"
elif data_type == "_AnsibleLazyTemplateList":
data_type = "list"
return alias.get(data_type, data_type)
def _ansible_type(data, alias):
def _ansible_type(data, alias, *, use_native_type: bool = False):
"""
Returns the Ansible data type.
"""
@@ -30,16 +44,16 @@ def _ansible_type(data, alias):
msg = "The argument alias must be a dictionary. %s is %s"
raise AnsibleFilterError(msg % (alias, type(alias)))
data_type = _atype(data, alias)
data_type = _atype(data, alias, use_native_type=use_native_type)
if data_type == 'list' and len(data) > 0:
items = [_atype(i, alias) for i in data]
items = [_atype(i, alias, use_native_type=use_native_type) for i in data]
items_type = '|'.join(sorted(set(items)))
return ''.join((data_type, '[', items_type, ']'))
if data_type == 'dict' and len(data) > 0:
keys = [_atype(i, alias) for i in data.keys()]
vals = [_atype(i, alias) for i in data.values()]
keys = [_atype(i, alias, use_native_type=use_native_type) for i in data.keys()]
vals = [_atype(i, alias, use_native_type=use_native_type) for i in data.values()]
keys_type = '|'.join(sorted(set(keys)))
vals_type = '|'.join(sorted(set(vals)))
return ''.join((data_type, '[', keys_type, ', ', vals_type, ']'))

View File

@@ -28,30 +28,36 @@ DOCUMENTATION = '''
EXAMPLES = '''
# Substitution converts str to AnsibleUnicode
# -------------------------------------------
# Substitution converts str to AnsibleUnicode or _AnsibleTaggedStr
# ----------------------------------------------------------------
# String. AnsibleUnicode.
dtype: AnsibleUnicode
# String. AnsibleUnicode or _AnsibleTaggedStr.
dtype:
- AnsibleUnicode
- _AnsibleTaggedStr
data: "abc"
result: '{{ data is community.general.ansible_type(dtype) }}'
# result => true
# String. AnsibleUnicode alias str.
alias: {"AnsibleUnicode": "str"}
# String. AnsibleUnicode/_AnsibleTaggedStr alias str.
alias: {"AnsibleUnicode": "str", "_AnsibleTaggedStr": "str"}
dtype: str
data: "abc"
result: '{{ data is community.general.ansible_type(dtype, alias) }}'
# result => true
# List. All items are AnsibleUnicode.
dtype: list[AnsibleUnicode]
# List. All items are AnsibleUnicode/_AnsibleTaggedStr.
dtype:
- list[AnsibleUnicode]
- list[_AnsibleTaggedStr]
data: ["a", "b", "c"]
result: '{{ data is community.general.ansible_type(dtype) }}'
# result => true
# Dictionary. All keys are AnsibleUnicode. All values are AnsibleUnicode.
dtype: dict[AnsibleUnicode, AnsibleUnicode]
# Dictionary. All keys and values are AnsibleUnicode/_AnsibleTaggedStr.
dtype:
- dict[AnsibleUnicode, AnsibleUnicode]
- dict[_AnsibleTaggedStr, _AnsibleTaggedStr]
data: {"a": "foo", "b": "bar", "c": "baz"}
result: '{{ data is community.general.ansible_type(dtype) }}'
# result => true
@@ -99,32 +105,46 @@ dtype: dict[str, int]
result: '{{ {"a": 1, "b": 2} is community.general.ansible_type(dtype) }}'
# result => true
# Type of strings is AnsibleUnicode or str
# ----------------------------------------
# Type of strings is AnsibleUnicode, _AnsibleTaggedStr, or str
# ------------------------------------------------------------
# Dictionary. The keys are integers or strings. All values are strings.
alias: {"AnsibleUnicode": "str"}
alias:
AnsibleUnicode: str
_AnsibleTaggedStr: str
_AnsibleTaggedInt: int
dtype: dict[int|str, str]
data: {1: 'a', 'b': 'b'}
result: '{{ data is community.general.ansible_type(dtype, alias) }}'
# result => true
# Dictionary. All keys are integers. All values are keys.
alias: {"AnsibleUnicode": "str"}
alias:
AnsibleUnicode: str
_AnsibleTaggedStr: str
_AnsibleTaggedInt: int
dtype: dict[int, str]
data: {1: 'a', 2: 'b'}
result: '{{ data is community.general.ansible_type(dtype, alias) }}'
# result => true
# Dictionary. All keys are strings. Multiple types values.
alias: {"AnsibleUnicode": "str"}
alias:
AnsibleUnicode: str
_AnsibleTaggedStr: str
_AnsibleTaggedInt: int
_AnsibleTaggedFloat: float
dtype: dict[str, bool|dict|float|int|list|str]
data: {'a': 1, 'b': 1.1, 'c': 'abc', 'd': True, 'e': ['x', 'y', 'z'], 'f': {'x': 1, 'y': 2}}
result: '{{ data is community.general.ansible_type(dtype, alias) }}'
# result => true
# List. Multiple types items.
alias: {"AnsibleUnicode": "str"}
alias:
AnsibleUnicode: str
_AnsibleTaggedStr: str
_AnsibleTaggedInt: int
_AnsibleTaggedFloat: float
dtype: list[bool|dict|float|int|list|str]
data: [1, 2, 1.1, 'abc', True, ['x', 'y', 'z'], {'x': 1, 'y': 2}]
result: '{{ data is community.general.ansible_type(dtype, alias) }}'
@@ -133,20 +153,20 @@ result: '{{ data is community.general.ansible_type(dtype, alias) }}'
# Option dtype is list
# --------------------
# AnsibleUnicode or str
dtype: ['AnsibleUnicode', 'str']
# AnsibleUnicode, _AnsibleTaggedStr, or str
dtype: ['AnsibleUnicode', '_AnsibleTaggedStr', 'str']
data: abc
result: '{{ data is community.general.ansible_type(dtype) }}'
# result => true
# float or int
dtype: ['float', 'int']
dtype: ['float', 'int', "_AnsibleTaggedInt", "_AnsibleTaggedFloat"]
data: 123
result: '{{ data is community.general.ansible_type(dtype) }}'
# result => true
# float or int
dtype: ['float', 'int']
dtype: ['float', 'int', "_AnsibleTaggedInt", "_AnsibleTaggedFloat"]
data: 123.45
result: '{{ data is community.general.ansible_type(dtype) }}'
# result => true
@@ -155,14 +175,22 @@ result: '{{ data is community.general.ansible_type(dtype) }}'
# --------------
# int alias number
alias: {"int": "number", "float": "number"}
alias:
int: number
float: number
_AnsibleTaggedInt: number
_AnsibleTaggedFloat: float
dtype: number
data: 123
result: '{{ data is community.general.ansible_type(dtype, alias) }}'
# result => true
# float alias number
alias: {"int": "number", "float": "number"}
alias:
int: number
float: number
_AnsibleTaggedInt: number
_AnsibleTaggedFloat: float
dtype: number
data: 123.45
result: '{{ data is community.general.ansible_type(dtype, alias) }}'
@@ -192,6 +220,7 @@ def ansible_type(data, dtype, alias=None):
else:
data_types = dtype
# TODO: expose use_native_type parameter
return _ansible_type(data, alias) in data_types

View File

@@ -0,0 +1,7 @@
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
azp/posix/3
destructive
skip/aix

View File

@@ -0,0 +1,8 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
dependencies:
- setup_remote_constraints
- setup_apache2

View File

@@ -0,0 +1,253 @@
---
####################################################################
# WARNING: These are designed specifically for Ansible tests #
# and should not be used as examples of how to write Ansible roles #
####################################################################
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
- meta: end_play
when: ansible_os_family not in ['Debian', 'Suse']
- name: Enable mod_proxy
community.general.apache2_module:
state: present
name: "{{ item }}"
loop:
- status
- proxy
- proxy_http
- proxy_balancer
- lbmethod_byrequests
- name: Add port 81
lineinfile:
path: "/etc/apache2/{{ 'ports.conf' if ansible_os_family == 'Debian' else 'listen.conf' }}"
line: Listen 81
- name: Set up virtual host
copy:
dest: "/etc/apache2/{{ 'sites-available' if ansible_os_family == 'Debian' else 'vhosts.d' }}/000-apache2_mod_proxy-test.conf"
content: |
<VirtualHost *:81>
<Proxy balancer://mycluster>
BalancerMember http://127.0.0.1:8080
BalancerMember http://127.0.0.1:8081
</Proxy>
<IfModule mod_evasive20.c>
DOSBlockingPeriod 0
DOSWhiteList 127.0.0.1
DOSWhiteList ::1
</IfModule>
<Location "/app/">
ProxyPreserveHost On
ProxyPass balancer://mycluster/
ProxyPassReverse balancer://mycluster/
</Location>
<Location "/balancer-manager">
SetHandler balancer-manager
Require all granted
</Location>
</VirtualHost>
- name: Enable virtual host
file:
src: /etc/apache2/sites-available/000-apache2_mod_proxy-test.conf
dest: /etc/apache2/sites-enabled/000-apache2_mod_proxy-test.conf
owner: root
group: root
state: link
when: ansible_os_family not in ['Suse']
- name: Restart Apache
service:
name: apache2
state: restarted
- name: Install BeautifulSoup
pip:
name: "{{ 'BeautifulSoup' if ansible_python_version is version('3', '<') else 'BeautifulSoup4' }}"
extra_args: "-c {{ remote_constraints }}"
- name: Get all current balancer pool members attributes
community.general.apache2_mod_proxy:
balancer_vhost: localhost:81
register: result
- assert:
that:
- result is not changed
- result.members | length == 2
- result.members[0].port in ["8080", "8081"]
- result.members[0].balancer_url == "http://localhost:81/balancer-manager/"
- result.members[0].host == "127.0.0.1"
- result.members[0].path is none
- result.members[0].protocol == "http"
- result.members[1].port in ["8080", "8081"]
- result.members[1].balancer_url == "http://localhost:81/balancer-manager/"
- result.members[1].host == "127.0.0.1"
- result.members[1].path is none
- result.members[1].protocol == "http"
- name: Enable member
community.general.apache2_mod_proxy:
balancer_vhost: localhost:81
member_host: 127.0.0.1
state: present
register: result
- assert:
that:
- result is not changed
- name: Get all current balancer pool members attributes
community.general.apache2_mod_proxy:
balancer_vhost: localhost:81
register: result
- assert:
that:
- result is not changed
- result.members | length == 2
- result.members[0].port in ["8080", "8081"]
- result.members[0].balancer_url == "http://localhost:81/balancer-manager/"
- result.members[0].host == "127.0.0.1"
- result.members[0].path is none
- result.members[0].protocol == "http"
- result.members[0].status.disabled == false
- result.members[0].status.drained == false
- result.members[0].status.hot_standby == false
- result.members[0].status.ignore_errors == false
- result.members[1].port in ["8080", "8081"]
- result.members[1].balancer_url == "http://localhost:81/balancer-manager/"
- result.members[1].host == "127.0.0.1"
- result.members[1].path is none
- result.members[1].protocol == "http"
- result.members[1].status.disabled == false
- result.members[1].status.drained == false
- result.members[1].status.hot_standby == false
- result.members[1].status.ignore_errors == false
- name: Drain member
community.general.apache2_mod_proxy:
balancer_vhost: localhost:81
member_host: 127.0.0.1
state: drained
register: result
- assert:
that:
- result is changed
# Note that since both members are on the same host, this always affects **both** members!
- name: Get all current balancer pool members attributes
community.general.apache2_mod_proxy:
balancer_vhost: localhost:81
register: result
- assert:
that:
- result is not changed
- result.members | length == 2
- result.members[0].port in ["8080", "8081"]
- result.members[0].balancer_url == "http://localhost:81/balancer-manager/"
- result.members[0].host == "127.0.0.1"
- result.members[0].path is none
- result.members[0].protocol == "http"
- result.members[0].status.disabled == false
- result.members[0].status.drained == true
- result.members[0].status.hot_standby == false
- result.members[0].status.ignore_errors == false
- result.members[1].port in ["8080", "8081"]
- result.members[1].balancer_url == "http://localhost:81/balancer-manager/"
- result.members[1].host == "127.0.0.1"
- result.members[1].path is none
- result.members[1].protocol == "http"
- result.members[1].status.disabled == false
- result.members[1].status.drained == true
- result.members[1].status.hot_standby == false
- result.members[1].status.ignore_errors == false
- name: Disable member
community.general.apache2_mod_proxy:
balancer_vhost: localhost:81
member_host: 127.0.0.1
state: absent
register: result
- assert:
that:
- result is changed
- name: Get all current balancer pool members attributes
community.general.apache2_mod_proxy:
balancer_vhost: localhost:81
register: result
- assert:
that:
- result is not changed
- result.members | length == 2
- result.members[0].port in ["8080", "8081"]
- result.members[0].balancer_url == "http://localhost:81/balancer-manager/"
- result.members[0].host == "127.0.0.1"
- result.members[0].path is none
- result.members[0].protocol == "http"
- result.members[0].status.disabled == true
- result.members[0].status.drained == false
- result.members[0].status.hot_standby == false
- result.members[0].status.ignore_errors == false
- result.members[1].port in ["8080", "8081"]
- result.members[1].balancer_url == "http://localhost:81/balancer-manager/"
- result.members[1].host == "127.0.0.1"
- result.members[1].path is none
- result.members[1].protocol == "http"
- result.members[1].status.disabled == true
- result.members[1].status.drained == false
- result.members[1].status.hot_standby == false
- result.members[1].status.ignore_errors == false
- name: Enable member
community.general.apache2_mod_proxy:
balancer_vhost: localhost:81
member_host: 127.0.0.1
state: present
register: result
- assert:
that:
- result is changed
- name: Get all current balancer pool members attributes
community.general.apache2_mod_proxy:
balancer_vhost: localhost:81
register: result
- assert:
that:
- result is not changed
- result.members | length == 2
- result.members[0].port in ["8080", "8081"]
- result.members[0].balancer_url == "http://localhost:81/balancer-manager/"
- result.members[0].host == "127.0.0.1"
- result.members[0].path is none
- result.members[0].protocol == "http"
- result.members[0].status.disabled == false
- result.members[0].status.drained == false
- result.members[0].status.hot_standby == false
- result.members[0].status.ignore_errors == false
- result.members[1].port in ["8080", "8081"]
- result.members[1].balancer_url == "http://localhost:81/balancer-manager/"
- result.members[1].host == "127.0.0.1"
- result.members[1].path is none
- result.members[1].protocol == "http"
- result.members[1].status.disabled == false
- result.members[1].status.drained == false
- result.members[1].status.hot_standby == false
- result.members[1].status.ignore_errors == false

View File

@@ -0,0 +1,7 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
dependencies:
- setup_apache2

View File

@@ -8,21 +8,6 @@
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
- name: install apache via apt
apt:
name: "{{item}}"
state: present
when: "ansible_os_family == 'Debian'"
with_items:
- apache2
- libapache2-mod-evasive
- name: install apache via zypper
community.general.zypper:
name: apache2
state: present
when: "ansible_os_family == 'Suse'"
- name: test apache2_module
block:
- name: get list of enabled modules

View File

@@ -0,0 +1,54 @@
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from ansible.module_utils.six import string_types
def callback_results_extractor(outputs_results):
results = []
for result in outputs_results:
differences = []
expected_output = result['test']['expected_output']
stdout_lines = result['stdout_lines']
for i in range(max(len(expected_output), len(stdout_lines))):
line = "line_%s" % (i + 1)
test_line = stdout_lines[i] if i < len(stdout_lines) else None
expected_lines = expected_output[i] if i < len(expected_output) else None
if not isinstance(expected_lines, string_types) and expected_lines is not None:
if test_line not in expected_lines:
differences.append({
'line': {
'expected_one_of': expected_lines,
'got': test_line,
}
})
else:
if test_line != expected_lines:
differences.append({
'line': {
'expected': expected_lines,
'got': test_line,
}
})
results.append({
'name': result['test']['name'],
'output': {
'differences': differences,
'expected': expected_output,
'got': stdout_lines,
},
})
return results
class FilterModule:
''' Jinja2 compat filters '''
def filters(self):
return {
'callback_results_extractor': callback_results_extractor,
}

View File

@@ -50,44 +50,11 @@
- name: Assert test output equals expected output
assert:
that: result.output.differences | length == 0
loop: "{{ results }}"
loop: "{{ outputs.results | callback_results_extractor }}"
loop_control:
loop_var: result
label: "{{ result.name }}"
register: assertions
vars:
results: >-
{%- set results = [] -%}
{%- for result in outputs.results -%}
{%- set differences = [] -%}
{%- for i in range([result.test.expected_output | count, result.stdout_lines | count] | max) -%}
{%- set line = "line_%s" | format(i+1) -%}
{%- set test_line = result.stdout_lines[i] | default(none) -%}
{%- set expected_lines = result.test.expected_output[i] | default(none) -%}
{%- if expected_lines is not string and expected_lines is not none -%}
{%- if test_line not in expected_lines -%}
{{- differences.append({
line: {
'expected_one_of': expected_lines,
'got': test_line }}) -}}
{%- endif -%}
{%- else -%}
{%- if expected_lines != test_line -%}
{{- differences.append({
line: {
'expected': expected_lines,
'got': test_line }}) -}}
{%- endif -%}
{%- endif -%}
{%- endfor -%}
{{- results.append({
'name': result.test.name,
'output': {
'differences': differences,
'expected': result.test.expected_output,
'got': result.stdout_lines }}) -}}
{%- endfor -%}
{{- results -}}
always:
- name: Remove temporary playbooks

View File

@@ -17,5 +17,5 @@ ansible-playbook ping_log.yml -v "$@"
# now force it to fail
export ANSIBLE_LOG_FOLDER="logit.file"
touch "${ANSIBLE_LOG_FOLDER}"
ansible-playbook ping_log.yml -v "$@" 2>&1| grep 'Failure using method (v2_runner_on_ok) in callback plugin'
ansible-playbook ping_log.yml -v "$@" 2>&1| grep -E "(Failure using method \(v2_runner_on_ok\) in callback plugin|Callback dispatch 'v2_runner_on_ok' failed for plugin)"
[[ ! -f "${ANSIBLE_LOG_FOLDER}/localhost" ]]

View File

@@ -67,7 +67,7 @@
ANSIBLE_NOCOLOR: 'true'
ANSIBLE_FORCE_COLOR: 'false'
ANSIBLE_STDOUT_CALLBACK: community.general.yaml
playbook: |
playbook: !unsafe |
- hosts: testhost
gather_facts: false
vars:
@@ -78,9 +78,7 @@
tasks:
- name: Test to_yaml
debug:
msg: "{{ '{{' }}'{{ '{{' }}'{{ '}}' }} data | to_yaml {{ '{{' }}'{{ '}}' }}'{{ '}}' }}"
# The above should be: msg: "{{ data | to_yaml }}"
# Unfortunately, the way Ansible handles templating, we need to do some funny 'escaping' tricks...
msg: "{{ data | to_yaml }}"
expected_output: [
"",
"PLAY [testhost] ****************************************************************",

View File

@@ -20,4 +20,4 @@
environment: "{{ cargo_environment }}"
when: has_cargo | default(false)
- import_tasks: test_rustup_cargo.yml
when: rustup_cargo_bin | default(false)
when: (rustup_cargo_bin | default(false)) is truthy

View File

@@ -9,6 +9,12 @@ from ansible.errors import AnsibleError
from ansible.playbook.conditional import Conditional
from ansible.plugins.action import ActionBase
try:
from ansible.utils.datatag import trust_value as _trust_value
except ImportError:
def _trust_value(input):
return input
class ActionModule(ActionBase):
''' Fail with custom message '''
@@ -36,12 +42,16 @@ class ActionModule(ActionBase):
thats = self._task.args['that']
cond = Conditional(loader=self._loader)
result['_ansible_verbose_always'] = True
for that in thats:
cond.when = [str(self._make_safe(that))]
test_result = cond.evaluate_conditional(templar=self._templar, all_vars=task_vars)
if hasattr(self._templar, 'evaluate_conditional'):
trusted_that = _trust_value(that) if _trust_value else that
test_result = self._templar.evaluate_conditional(conditional=trusted_that)
else:
cond = Conditional(loader=self._loader)
cond.when = [str(self._make_safe(that))]
test_result = cond.evaluate_conditional(templar=self._templar, all_vars=task_vars)
if not test_result:
result['failed'] = True
result['evaluated_to'] = test_result

View File

@@ -7,6 +7,8 @@
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import traceback
DOCUMENTATION = ""
@@ -43,15 +45,18 @@ def main():
arg_formats[arg] = func(*args)
runner = CmdRunner(module, [module.params["cmd"], '--'], arg_formats=arg_formats, path_prefix=module.params["path_prefix"])
try:
runner = CmdRunner(module, [module.params["cmd"], '--'], arg_formats=arg_formats, path_prefix=module.params["path_prefix"])
with runner.context(p['arg_order'], check_mode_skip=p['check_mode_skip']) as ctx:
result = ctx.run(**p['arg_values'])
info = ctx.run_info
check = "check"
rc, out, err = result if result is not None else (None, None, None)
with runner.context(p['arg_order'], check_mode_skip=p['check_mode_skip']) as ctx:
result = ctx.run(**p['arg_values'])
info = ctx.run_info
check = "check"
rc, out, err = result if result is not None else (None, None, None)
module.exit_json(rc=rc, out=out, err=err, info=info)
module.exit_json(rc=rc, out=out, err=err, info=info)
except Exception as exc:
module.fail_json(rc=1, module_stderr=traceback.format_exc(), msg="Module crashed with exception")
if __name__ == '__main__':

View File

@@ -33,7 +33,7 @@
that:
- result is changed
- result.binding_rule.AuthMethod == 'test'
- result.binding.Description == 'test-binding: my description'
- "result.binding_rule.Description == 'test-binding: my description'"
- result.operation == 'create'
- name: Update a binding rule
@@ -46,7 +46,7 @@
- assert:
that:
- result is changed
- result.binding.Description == 'test-binding: my description'
- "result.binding_rule.Description == 'test-binding: my description'"
- result.operation == 'update'
- name: Update a binding rule (noop)
@@ -58,7 +58,7 @@
- assert:
that:
- result is not changed
- result.binding.Description == 'test-binding: my description'
- "result.binding_rule.Description == 'test-binding: my description'"
- result.operation is not defined
- name: Delete a binding rule

View File

@@ -22,7 +22,7 @@
- assert:
that:
- simple_create_result is changed
- simple_create_result.token.AccessorID
- simple_create_result.token.AccessorID is truthy
- simple_create_result.operation == 'create'
- name: Create token
@@ -67,7 +67,7 @@
state: present
accessor_id: 07a7de84-c9c7-448a-99cc-beaf682efd21
policies:
- id: "{{ create_result.token.Policies[-1].ID }}"
- name: foo-access2
register: result
- assert:
@@ -84,5 +84,5 @@
- assert:
that:
- result is changed
- not result.token
- result.token is falsy
- result.operation == 'remove'

View File

@@ -123,11 +123,12 @@
register: releases_path
- stat: path={{ deploy_helper.shared_path }}
register: shared_path
when: deploy_helper.shared_path is truthy
- name: Assert State=present with shared_path set to False
assert:
that:
- "releases_path.stat.exists"
- "not shared_path.stat.exists"
- "deploy_helper.shared_path is falsy or not shared_path.stat.exists"
# Setup older releases for tests
- file: path={{ deploy_helper.releases_path }}/{{ item }} state=directory

View File

@@ -7,7 +7,6 @@
- include_tasks: install.yml
- include_tasks: lock_bash.yml
- include_tasks: lock_updates.yml
when: (ansible_distribution == 'Fedora' and ansible_distribution_major_version is version('23', '>=') and ansible_distribution_major_version is version('41', '<')) or
when: (ansible_distribution == 'Fedora' and ansible_distribution_major_version is version('23', '>=')) or
(ansible_distribution in ['RedHat', 'CentOS'] and ansible_distribution_major_version is version('8', '>='))
# TODO: Fix on Fedora 41, apparently the output changed!
...

View File

@@ -59,6 +59,8 @@
item.0.key == "reiserfs")'
# reiserfs packages apparently not available with Alpine
- 'not (ansible_distribution == "Alpine" and item.0.key == "reiserfs")'
# reiserfsprogs packages no longer available with Arch Linux
- 'not (ansible_distribution == "Archlinux" and item.0.key == "reiserfs")'
# ocfs2 only available on Debian based distributions
- 'not (item.0.key == "ocfs2" and ansible_os_family != "Debian")'
# Tests use losetup which can not be used inside unprivileged container

View File

@@ -75,7 +75,7 @@
state: present
when:
- ansible_system == 'Linux'
- ansible_os_family not in ['Suse', 'RedHat', 'Alpine']
- ansible_os_family not in ['Suse', 'RedHat', 'Alpine', 'Archlinux']
- name: "Install reiserfs progs (FreeBSD)"
ansible.builtin.package:

View File

@@ -26,7 +26,7 @@
assert:
that:
- res is failed
- res.msg is match('Argument for community.general.counter must be a sequence')
- res.msg is search('Argument for community.general.counter must be a sequence')
- name: test fail element not hashable
debug:
@@ -38,4 +38,4 @@
assert:
that:
- res is failed
- res.msg is match('community.general.counter needs a sequence with hashable elements')
- res.msg is search('community.general.counter needs a sequence with hashable elements')

View File

@@ -51,4 +51,4 @@
assert:
that:
- _invalid_csv_strict_true is failed
- _invalid_csv_strict_true.msg is match('Unable to process file:.*')
- _invalid_csv_strict_true.msg is search('Unable to process file:.*')

View File

@@ -16,7 +16,7 @@
- assert:
that:
- result.msg == 'Input is not a sequence'
- result.msg is search('Input is not a sequence')
- name: 'Test error: list element not a mapping'
set_fact:
@@ -26,7 +26,7 @@
- assert:
that:
- "result.msg == 'Sequence element #0 is not a mapping'"
- "result.msg is search('Sequence element #0 is not a mapping')"
- name: 'Test error: list element does not have attribute'
set_fact:
@@ -36,7 +36,7 @@
- assert:
that:
- "result.msg == 'Attribute not contained in element #1 of sequence'"
- "result.msg is search('Attribute not contained in element #1 of sequence')"
- name: 'Test error: attribute collision'
set_fact:
@@ -46,4 +46,4 @@
- assert:
that:
- result.msg == "Multiple sequence entries have attribute value 'a'" or result.msg == "Multiple sequence entries have attribute value u'a'"
- result.msg is search("Multiple sequence entries have attribute value u?'a'")

View File

@@ -31,7 +31,7 @@
- name: Register result of invalid salt
debug:
var: "invalid_input | community.general.hashids_encode(salt=10)"
var: "single_int | community.general.hashids_encode(salt=10)"
register: invalid_salt_message
ignore_errors: true
@@ -42,7 +42,7 @@
- name: Register result of invalid alphabet
debug:
var: "invalid_input | community.general.hashids_encode(alphabet='abc')"
var: "single_int | community.general.hashids_encode(alphabet='abc')"
register: invalid_alphabet_message
ignore_errors: true
@@ -53,7 +53,7 @@
- name: Register result of invalid min_length
debug:
var: "invalid_input | community.general.hashids_encode(min_length='foo')"
var: "single_int | community.general.hashids_encode(min_length='foo')"
register: invalid_min_length_message
ignore_errors: true

View File

@@ -6,7 +6,7 @@
- name: Debug ansible_version
ansible.builtin.debug:
var: ansible_version
when: not quite_test | d(true) | bool
when: not (quiet_test | default(true) | bool)
tags: ansible_version
- name: Tests
@@ -19,13 +19,13 @@
fail_msg: |
[ERR] result:
{{ result | to_yaml }}
quiet: "{{ quiet_test | d(true) | bool }}"
quiet: "{{ quiet_test | default(true) | bool }}"
loop: "{{ tests | subelements('group') }}"
loop_control:
loop_var: i
label: "{{ i.1.mp | d('default') }}: {{ i.1.tt }}"
label: "{{ i.1.mp | default('default') }}: {{ i.1.tt }}"
vars:
input: "{{ i.0.input }}"
target: "{{ i.1.tt }}"
mp: "{{ i.1.mp | d('default') }}"
mp: "{{ i.1.mp | default('default') }}"
result: "{{ lookup('template', i.0.template) }}"

View File

@@ -16,7 +16,7 @@
{{ my_list|to_nice_yaml|indent(2) }}
my_list|difference(result101):
{{ my_list|difference(result101)|to_nice_yaml|indent(2) }}
when: debug_test|d(false)|bool
when: debug_test|default(false)|bool
- name: Merge 2 lists by attribute name. list_merge='keep'. assert
assert:
that: my_list | difference(result101) | length == 0
@@ -35,7 +35,7 @@
{{ my_list|to_nice_yaml|indent(2) }}
my_list|difference(result102):
{{ my_list|difference(result102)|to_nice_yaml|indent(2) }}
when: debug_test|d(false)|bool
when: debug_test|default(false)|bool
- name: Merge 2 lists by attribute name. list_merge='append'. assert
assert:
that: my_list | difference(result102) | length == 0
@@ -54,7 +54,7 @@
{{ my_list|to_nice_yaml|indent(2) }}
my_list|difference(result103):
{{ my_list|difference(result103)|to_nice_yaml|indent(2) }}
when: debug_test|d(false)|bool
when: debug_test|default(false)|bool
- name: Merge 2 lists by attribute name. list_merge='prepend'. assert
assert:
that: my_list | difference(result103) | length == 0
@@ -73,7 +73,7 @@
{{ my_list|to_nice_yaml|indent(2) }}
my_list|difference(result104):
{{ my_list|difference(result104)|to_nice_yaml|indent(2) }}
when: debug_test|d(false)|bool
when: debug_test|default(false)|bool
- name: Merge 2 lists by attribute name. list_merge='append_rp'. assert
assert:
that: my_list | difference(result104) | length == 0
@@ -92,7 +92,7 @@
{{ my_list|to_nice_yaml|indent(2) }}
my_list|difference(result105):
{{ my_list|difference(result105)|to_nice_yaml|indent(2) }}
when: debug_test|d(false)|bool
when: debug_test|default(false)|bool
- name: Merge 2 lists by attribute name. list_merge='prepend_rp'. assert
assert:
that: my_list | difference(result105) | length == 0
@@ -115,7 +115,7 @@
{{ my_list|to_nice_yaml|indent(2) }}
my_list|difference(result200):
{{ my_list|difference(result200)|to_nice_yaml|indent(2) }}
when: debug_test|d(false)|bool
when: debug_test|default(false)|bool
- name: Merge by name. recursive=True list_merge='append_rp'. assert
assert:
that: my_list | difference(result200) | length == 0
@@ -136,7 +136,7 @@
{{ my_list|to_nice_yaml|indent(2) }}
my_list|difference(result201):
{{ my_list|difference(result201)|to_nice_yaml|indent(2) }}
when: debug_test|d(false)|bool
when: debug_test|default(false)|bool
- name: Merge by name. recursive=False list_merge='append_rp'. assert
assert:
that: my_list | difference(result201) | length == 0

View File

@@ -6,7 +6,7 @@
- name: Debug ansible_version
debug:
var: ansible_version
when: debug_test|d(false)|bool
when: debug_test|default(false)|bool
tags: t0
- name: 1. Test lists merged by attribute name
@@ -14,7 +14,7 @@
- name: Test lists merged by attribute name debug
debug:
msg: "{{ list1 | community.general.lists_mergeby(list2, 'name') }}"
when: debug_test|d(false)|bool
when: debug_test|default(false)|bool
- name: Test lists merged by attribute name assert
assert:
that:
@@ -27,7 +27,7 @@
- name: Test list1 empty debug
debug:
msg: "{{ [] | community.general.lists_mergeby(list2, 'name') }}"
when: debug_test|d(false)|bool
when: debug_test|default(false)|bool
- name: Test list1 empty assert
assert:
that:
@@ -40,7 +40,7 @@
- name: Test all lists empty debug
debug:
msg: "{{ [] | community.general.lists_mergeby([], 'name') }}"
when: debug_test|d(false)|bool
when: debug_test|default(false)|bool
- name: Test all lists empty assert
assert:
that:
@@ -58,7 +58,7 @@
- name: First argument must be list debug
debug:
var: my_list
when: debug_test|d(false)|bool
when: debug_test|default(false)|bool
- name: First argument must be list assert
assert:
that:
@@ -76,7 +76,7 @@
- name: Second argument must be list set debug
debug:
var: my_list
when: debug_test|d(false)|bool
when: debug_test|default(false)|bool
- name: Second argument must be list set assert
assert:
that:
@@ -94,7 +94,7 @@
- name: First arguments after the lists must be string debug
debug:
var: my_list
when: debug_test|d(false)|bool
when: debug_test|default(false)|bool
- name: First arguments after the lists must be string assert
assert:
that:
@@ -112,7 +112,7 @@
- name: Elements of list must be dictionaries debug
debug:
var: my_list
when: debug_test|d(false)|bool
when: debug_test|default(false)|bool
- name: Elements of list must be dictionaries assert
assert:
that:
@@ -128,7 +128,7 @@
- name: Merge 3 lists by attribute name. 1 list in params. debug
debug:
var: my_list
when: debug_test|d(false)|bool
when: debug_test|default(false)|bool
- name: Merge 3 lists by attribute name. 1 list in params. assert
assert:
that: my_list | difference(result1) | length == 0
@@ -142,7 +142,7 @@
- name: Merge 3 lists by attribute name. No list in the params. debug
debug:
var: my_list
when: debug_test|d(false)|bool
when: debug_test|default(false)|bool
- name: Merge 3 lists by attribute name. No list in the params. asset
assert:
that: my_list | difference(result1) | length == 0
@@ -162,7 +162,7 @@
{{ my_list|to_nice_yaml|indent(2) }}
my_list|difference(result100):
{{ my_list|difference(result100)|to_nice_yaml|indent(2) }}
when: debug_test|d(false)|bool
when: debug_test|default(false)|bool
- name: Merge 2 lists by attribute name. list_merge='replace'. assert
assert:
that: my_list | difference(result100) | length == 0

View File

@@ -19,7 +19,7 @@
assert:
that:
- _bad_random_mac_filter is failed
- "_bad_random_mac_filter.msg is match('Invalid value type (.*int.*) for random_mac .*')"
- "_bad_random_mac_filter.msg is search('Invalid value type (.*int.*) for random_mac .*')"
- name: Test random_mac filter bad argument value
debug:
@@ -31,7 +31,7 @@
assert:
that:
- _bad_random_mac_filter is failed
- "_bad_random_mac_filter.msg is match('Invalid value (.*) for random_mac: .* not hexa byte')"
- "_bad_random_mac_filter.msg is search('Invalid value (.*) for random_mac: .* not hexa byte')"
- name: Test random_mac filter prefix too big
debug:
@@ -43,7 +43,7 @@
assert:
that:
- _bad_random_mac_filter is failed
- "_bad_random_mac_filter.msg is match('Invalid value (.*) for random_mac: 5 colon.* separated items max')"
- "_bad_random_mac_filter.msg is search('Invalid value (.*) for random_mac: 5 colon.* separated items max')"
- name: Verify random_mac filter
assert:

View File

@@ -6,7 +6,7 @@
- name: Debug ansible_version
ansible.builtin.debug:
var: ansible_version
when: not quite_test | d(true) | bool
when: not (quiet_test | default(true) | bool)
tags: ansible_version
- name: Tests
@@ -19,13 +19,13 @@
fail_msg: |
[ERR] result:
{{ result | to_yaml }}
quiet: "{{ quiet_test | d(true) | bool }}"
quiet: "{{ quiet_test | default(true) | bool }}"
loop: "{{ tests | subelements('group') }}"
loop_control:
loop_var: i
label: "{{ i.1.mp | d('default') }}: {{ i.1.tt }}"
label: "{{ i.1.mp | default('default') }}: {{ i.1.tt }}"
vars:
input: "{{ i.0.input }}"
target: "{{ i.1.tt }}"
mp: "{{ i.1.mp | d('default') }}"
mp: "{{ i.1.mp | default('default') }}"
result: "{{ lookup('template', i.0.template) }}"

View File

@@ -6,7 +6,7 @@
- name: Debug ansible_version
ansible.builtin.debug:
var: ansible_version
when: not quite_test | d(true) | bool
when: not (quiet_test | default(true) | bool)
tags: ansible_version
- name: Tests
@@ -19,13 +19,13 @@
fail_msg: |
[ERR] result:
{{ result | to_yaml }}
quiet: "{{ quiet_test | d(true) | bool }}"
quiet: "{{ quiet_test | default(true) | bool }}"
loop: "{{ tests | subelements('group') }}"
loop_control:
loop_var: i
label: "{{ i.1.mp | d('default') }}: {{ i.1.tt }}"
label: "{{ i.1.mp | default('default') }}: {{ i.1.tt }}"
vars:
input: "{{ i.0.input }}"
target: "{{ i.1.tt }}"
mp: "{{ i.1.mp | d('default') }}"
mp: "{{ i.1.mp | default('default') }}"
result: "{{ lookup('template', i.0.template) }}"

View File

@@ -2,53 +2,60 @@
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
# Substitution converts str to AnsibleUnicode
# -------------------------------------------
# Substitution converts str to AnsibleUnicode/_AnsibleTaggedStr
# -------------------------------------------------------------
- name: String. AnsibleUnicode.
- name: String. AnsibleUnicode/_AnsibleTaggedStr.
assert:
that: result == dtype
success_msg: '"abc" is {{ dtype }}'
fail_msg: '"abc" is {{ result }}'
quiet: '{{ quiet_test | d(true) | bool }}'
that: result in dtype
success_msg: '"abc" is one of {{ dtype }}'
fail_msg: '"abc" is {{ result }}, not one of {{ dtype }}'
quiet: '{{ quiet_test | default(true) | bool }}'
vars:
data: "abc"
result: '{{ data | community.general.reveal_ansible_type }}'
dtype: 'AnsibleUnicode'
dtype:
- 'AnsibleUnicode'
- '_AnsibleTaggedStr'
- name: String. AnsibleUnicode alias str.
- name: String. AnsibleUnicode/_AnsibleTaggedStr alias str.
assert:
that: result == dtype
success_msg: '"abc" is {{ dtype }}'
fail_msg: '"abc" is {{ result }}'
quiet: '{{ quiet_test | d(true) | bool }}'
that: result in dtype
success_msg: '"abc" is one of {{ dtype }}'
fail_msg: '"abc" is {{ result }}, not one of {{ dtype }}'
quiet: '{{ quiet_test | default(true) | bool }}'
vars:
alias: {"AnsibleUnicode": "str"}
alias: {"AnsibleUnicode": "str", "_AnsibleTaggedStr": "str"}
data: "abc"
result: '{{ data | community.general.reveal_ansible_type(alias) }}'
dtype: 'str'
dtype:
- 'str'
- name: List. All items are AnsibleUnicode.
- name: List. All items are AnsibleUnicode/_AnsibleTaggedStr.
assert:
that: result == dtype
success_msg: '["a", "b", "c"] is {{ dtype }}'
fail_msg: '["a", "b", "c"] is {{ result }}'
quiet: '{{ quiet_test | d(true) | bool }}'
that: result in dtype
success_msg: '["a", "b", "c"] is one of {{ dtype }}'
fail_msg: '["a", "b", "c"] is {{ result }}, not one of {{ dtype }}'
quiet: '{{ quiet_test | default(true) | bool }}'
vars:
data: ["a", "b", "c"]
result: '{{ data | community.general.reveal_ansible_type }}'
dtype: 'list[AnsibleUnicode]'
dtype:
- 'list[AnsibleUnicode]'
- 'list[_AnsibleTaggedStr]'
- name: Dictionary. All keys are AnsibleUnicode. All values are AnsibleUnicode.
- name: Dictionary. All keys and values are AnsibleUnicode/_AnsibleTaggedStr.
assert:
that: result == dtype
success_msg: '{"a": "foo", "b": "bar", "c": "baz"} is {{ dtype }}'
fail_msg: '{"a": "foo", "b": "bar", "c": "baz"} is {{ result }}'
quiet: '{{ quiet_test | d(true) | bool }}'
that: result in dtype
success_msg: '{"a": "foo", "b": "bar", "c": "baz"} is one of {{ dtype }}'
fail_msg: '{"a": "foo", "b": "bar", "c": "baz"} is {{ result }}, not one of {{ dtype }}'
quiet: '{{ quiet_test | default(true) | bool }}'
vars:
data: {"a": "foo", "b": "bar", "c": "baz"}
result: '{{ data | community.general.reveal_ansible_type }}'
dtype: 'dict[AnsibleUnicode, AnsibleUnicode]'
dtype:
- 'dict[AnsibleUnicode, AnsibleUnicode]'
- 'dict[_AnsibleTaggedStr, _AnsibleTaggedStr]'
# No substitution and no alias. Type of strings is str
# ----------------------------------------------------
@@ -57,8 +64,8 @@
assert:
that: result == dtype
success_msg: '"abc" is {{ dtype }}'
fail_msg: '"abc" is {{ result }}'
quiet: '{{ quiet_test | d(true) | bool }}'
fail_msg: '"abc" is {{ result }}, not {{ dtype }}'
quiet: '{{ quiet_test | default(true) | bool }}'
vars:
result: '{{ "abc" | community.general.reveal_ansible_type }}'
dtype: str
@@ -67,8 +74,8 @@
assert:
that: result == dtype
success_msg: '123 is {{ dtype }}'
fail_msg: '123 is {{ result }}'
quiet: '{{ quiet_test | d(true) | bool }}'
fail_msg: '123 is {{ result }}, not {{ dtype }}'
quiet: '{{ quiet_test | default(true) | bool }}'
vars:
result: '{{ 123 | community.general.reveal_ansible_type }}'
dtype: int
@@ -77,8 +84,8 @@
assert:
that: result == dtype
success_msg: '123.45 is {{ dtype }}'
fail_msg: '123.45 is {{ result }}'
quiet: '{{ quiet_test | d(true) | bool }}'
fail_msg: '123.45 is {{ result }}, not {{ dtype }}'
quiet: '{{ quiet_test | default(true) | bool }}'
vars:
result: '{{ 123.45 | community.general.reveal_ansible_type }}'
dtype: float
@@ -87,8 +94,8 @@
assert:
that: result == dtype
success_msg: 'true is {{ dtype }}'
fail_msg: 'true is {{ result }}'
quiet: '{{ quiet_test | d(true) | bool }}'
fail_msg: 'true is {{ result }}, not {{ dtype }}'
quiet: '{{ quiet_test | default(true) | bool }}'
vars:
result: '{{ true | community.general.reveal_ansible_type }}'
dtype: bool
@@ -97,8 +104,8 @@
assert:
that: result == dtype
success_msg: '["a", "b", "c"] is {{ dtype }}'
fail_msg: '["a", "b", "c"] is {{ result }}'
quiet: '{{ quiet_test | d(true) | bool }}'
fail_msg: '["a", "b", "c"] is {{ result }}, not {{ dtype }}'
quiet: '{{ quiet_test | default(true) | bool }}'
vars:
result: '{{ ["a", "b", "c"] | community.general.reveal_ansible_type }}'
dtype: list[str]
@@ -107,8 +114,8 @@
assert:
that: result == dtype
success_msg: '[{"a": 1}, {"b": 2}] is {{ dtype }}'
fail_msg: '[{"a": 1}, {"b": 2}] is {{ result }}'
quiet: '{{ quiet_test | d(true) | bool }}'
fail_msg: '[{"a": 1}, {"b": 2}] is {{ result }}, not {{ dtype }}'
quiet: '{{ quiet_test | default(true) | bool }}'
vars:
result: '{{ [{"a": 1}, {"b": 2}] | community.general.reveal_ansible_type }}'
dtype: list[dict]
@@ -117,8 +124,8 @@
assert:
that: result == dtype
success_msg: '{"a": 1} is {{ dtype }}'
fail_msg: '{"a": 1} is {{ result }}'
quiet: '{{ quiet_test | d(true) | bool }}'
fail_msg: '{"a": 1} is {{ result }}, not {{ dtype }}'
quiet: '{{ quiet_test | default(true) | bool }}'
vars:
result: '{{ {"a": 1} | community.general.reveal_ansible_type }}'
dtype: dict[str, int]
@@ -127,23 +134,23 @@
assert:
that: result == dtype
success_msg: '{"a": 1, "b": 2} is {{ dtype }}'
fail_msg: '{"a": 1, "b": 2} is {{ result }}'
quiet: '{{ quiet_test | d(true) | bool }}'
fail_msg: '{"a": 1, "b": 2} is {{ result }}, not {{ dtype }}'
quiet: '{{ quiet_test | default(true) | bool }}'
vars:
result: '{{ {"a": 1, "b": 2} | community.general.reveal_ansible_type }}'
dtype: dict[str, int]
# Type of strings is AnsibleUnicode or str
# ----------------------------------------
# Type of strings is AnsibleUnicode/_AnsibleTaggedStr or str
# ----------------------------------------------------------
- name: Dictionary. The keys are integers or strings. All values are strings.
assert:
that: result == dtype
success_msg: 'data is {{ dtype }}'
fail_msg: 'data is {{ result }}'
quiet: '{{ quiet_test | d(true) | bool }}'
fail_msg: 'data is {{ result }}, not {{ dtype }}'
quiet: '{{ quiet_test | default(true) | bool }}'
vars:
alias: {"AnsibleUnicode": "str"}
alias: {"AnsibleUnicode": "str", "_AnsibleTaggedStr": "str", "_AnsibleTaggedInt": "int"}
data: {1: 'a', 'b': 'b'}
result: '{{ data | community.general.reveal_ansible_type(alias) }}'
dtype: dict[int|str, str]
@@ -152,10 +159,10 @@
assert:
that: result == dtype
success_msg: 'data is {{ dtype }}'
fail_msg: 'data is {{ result }}'
quiet: '{{ quiet_test | d(true) | bool }}'
fail_msg: 'data is {{ result }}, not {{ dtype }}'
quiet: '{{ quiet_test | default(true) | bool }}'
vars:
alias: {"AnsibleUnicode": "str"}
alias: {"AnsibleUnicode": "str", "_AnsibleTaggedStr": "str", "_AnsibleTaggedInt": "int"}
data: {1: 'a', 2: 'b'}
result: '{{ data | community.general.reveal_ansible_type(alias) }}'
dtype: dict[int, str]
@@ -164,10 +171,10 @@
assert:
that: result == dtype
success_msg: 'data is {{ dtype }}'
fail_msg: 'data is {{ result }}'
quiet: '{{ quiet_test | d(true) | bool }}'
fail_msg: 'data is {{ result }}, not {{ dtype }}'
quiet: '{{ quiet_test | default(true) | bool }}'
vars:
alias: {"AnsibleUnicode": "str"}
alias: {"AnsibleUnicode": "str", "_AnsibleTaggedStr": "str", "_AnsibleTaggedInt": "int", "_AnsibleTaggedFloat": "float"}
data: {'a': 1, 'b': 1.1, 'c': 'abc', 'd': True, 'e': ['x', 'y', 'z'], 'f': {'x': 1, 'y': 2}}
result: '{{ data | community.general.reveal_ansible_type(alias) }}'
dtype: dict[str, bool|dict|float|int|list|str]
@@ -176,10 +183,10 @@
assert:
that: result == dtype
success_msg: 'data is {{ dtype }}'
fail_msg: 'data is {{ result }}'
quiet: '{{ quiet_test | d(true) | bool }}'
fail_msg: 'data is {{ result }}, not {{ dtype }}'
quiet: '{{ quiet_test | default(true) | bool }}'
vars:
alias: {"AnsibleUnicode": "str"}
alias: {"AnsibleUnicode": "str", "_AnsibleTaggedStr": "str", "_AnsibleTaggedInt": "int", "_AnsibleTaggedFloat": "float"}
data: [1, 2, 1.1, 'abc', True, ['x', 'y', 'z'], {'x': 1, 'y': 2}]
result: '{{ data | community.general.reveal_ansible_type(alias) }}'
dtype: list[bool|dict|float|int|list|str]

View File

@@ -3,5 +3,6 @@
# SPDX-License-Identifier: GPL-3.0-or-later
azp/posix/2
skip/python3
skip/aix
skip/macos
disabled # TODO osdn.net is out of business, so cloning a repo from there does not work

View File

@@ -6,3 +6,4 @@
dependencies:
- setup_pkg_mgr
- setup_remote_tmp_dir
- setup_epel

View File

@@ -26,6 +26,12 @@
shell: apt-get -y update && apt-get -y install mercurial
when: ansible_facts.pkg_mgr == 'apt'
- name: install packages (apk)
package:
name: mercurial
state: present
when: ansible_facts.pkg_mgr in ['apk', 'community.general.apk']
- name: install mercurial (dnf)
dnf:
name: mercurial
@@ -36,6 +42,11 @@
name: mercurial
when: ansible_facts.pkg_mgr == 'yum'
- name: install mercurial (pacman)
package:
name: mercurial
when: ansible_facts.pkg_mgr in ['pacman', 'community.general.pacman']
- name: install mercurial (pkgng)
package:
name: mercurial

View File

@@ -16,6 +16,12 @@
line: "#!{{ stat_hg_interpreter.stat.path }}"
when: stat_hg_interpreter.stat.islnk
- name: uninstall packages which were not originally installed (apk)
package:
name: mercurial
state: absent
when: ansible_facts.pkg_mgr in ['apk', 'community.general.apk']
# using the apt module prevents autoremove from working, so call apt-get via shell instead
- name: uninstall packages which were not originally installed (apt)
shell: apt-get -y remove mercurial && apt-get -y autoremove
@@ -33,6 +39,12 @@
shell: yum -y autoremove mercurial
when: ansible_facts.pkg_mgr == 'yum'
- name: uninstall packages which were not originally installed (pacman)
package:
name: mercurial
state: absent
when: ansible_facts.pkg_mgr in ['pacman', 'community.general.pacman']
- name: uninstall packages which were not originally installed (pkgng)
package:
name: mercurial

View File

@@ -7,3 +7,5 @@ skip/aix
skip/freebsd
skip/rhel
skip/docker
skip/macos14.3
skip/macos13.2

View File

@@ -253,7 +253,7 @@
path: "{{ output_file }}"
section: mysqld
option: "{{ item.o }}"
value: "{{ item.v | d(omit) }}"
value: "{{ item.v | default(omit) }}"
allow_no_value: true
loop:
- { o: "skip-name-resolve" }
@@ -512,10 +512,10 @@
- name: test-value 20 - Tests with empty strings
ini_file:
path: "{{ output_file }}"
section: "{{ item.section | d('extensions') }}"
section: "{{ item.section | default('extensions') }}"
option: "{{ item.option }}"
value: ""
allow_no_value: "{{ item.no_value | d(omit) }}"
allow_no_value: "{{ item.no_value | default(omit) }}"
loop:
- option: evolve
- option: regress

Some files were not shown because too many files have changed in this diff Show More