Compare commits

..

302 Commits

Author SHA1 Message Date
Felix Fontein
06bce0dbf4 Release 8.6.2. 2024-06-17 19:36:22 +02:00
patchback[bot]
4bfb832f0d [PR #8476/2612ceee backport][stable-8] Fix launchd check-mode to report changed correctly (#8528)
Fix launchd check-mode to report changed correctly (#8476)

* Fix launchd check-mode to report changed correctly

* Update changelog fragment.

---------

Co-authored-by: Strahinja Kustudic <strahinjak@nordeus.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 2612ceee37)

Co-authored-by: Strahinja Kustudic <kustodian@gmail.com>
2024-06-17 07:55:46 +02:00
patchback[bot]
9032b14610 [PR #8503/3314d5c8 backport][stable-8] proxmox_kvm: document that force requires archive (#8525)
proxmox_kvm: document that force requires archive (#8503)

* proxmox_kvm: document that force requires archive

As per `qm(1)`, the force option requires `archive`. Add this
information in the `proxmox_kvm` module so one will know they have to
define `archive` when using `force`.

* fix: parameter is an option O(archive)

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

---------

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

Co-authored-by: Bruno Travouillon <devel@travouillon.fr>
2024-06-17 07:19:57 +02:00
patchback[bot]
444fbe8710 [PR #8514/df7fe19b backport][stable-8] pacman: do not fail if there is nothing to do (#8522)
pacman: do not fail if there is nothing to do (#8514)

Do not fail if there is nothing to do.

(cherry picked from commit df7fe19bbe)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-06-17 07:19:48 +02:00
patchback[bot]
68fb96480c [PR #8496/fd2cd5f2 backport][stable-8] keycloak_clientscope: add normalizations for attributes and protocol_mappers (#8520)
keycloak_clientscope: add normalizations for attributes and protocol_mappers (#8496)

Signed-off-by: Eike Waldt <waldt@b1-systems.de>
(cherry picked from commit fd2cd5f28c)

Co-authored-by: Eike Waldt <waldt@b1-systems.de>
2024-06-16 22:24:43 +02:00
patchback[bot]
b901fa7463 [PR #8489/3716187f backport][stable-8] Fix OpenNebula inventory crash when NIC does not have IP (#8518)
Fix OpenNebula inventory crash when NIC does not have IP (#8489)

* Fix OpenNebula inventory crash when NIC does not have IP

Match IPv6 behaviour.

When a NIC does not have an IP:
  File "ansible/inventory/manager.py", line 292, in parse_source
    plugin.parse(self._inventory, self._loader, source, cache=cache)
  File "ansible-cm/plugins/inventory/opennebula.py", line 263, in parse
    self._populate()
  File "ansible-cm/plugins/inventory/opennebula.py", line 226, in _populate
    servers = self._retrieve_servers(filter_by_label)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "ansible-cm/plugins/inventory/opennebula.py", line 210, in _retrieve_servers
    server['v4_first_ip'] = self._get_vm_ipv4(vm)
                            ^^^^^^^^^^^^^^^^^^^^^
  File "ansible-cm/plugins/inventory/opennebula.py", line 154, in _get_vm_ipv4
    return net['IP']

* Update to call to match IPv6 and add changelog fragment

* Update changelog fragment.

---------

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

Co-authored-by: Tom Paine <github@aioue.net>
2024-06-16 22:24:30 +02:00
Felix Fontein
f73b3bb2a2 Prepare 8.6.2 release. 2024-06-16 21:12:49 +02:00
patchback[bot]
6ee0141964 [PR #8500/49e2a863 backport][stable-8] Add Python 3.13 to CI (#8501)
Add Python 3.13 to CI (#8500)

Add Python 3.13 to CI.

(cherry picked from commit 49e2a8633e)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-06-14 07:12:17 +02:00
patchback[bot]
9315a7bb56 [PR #8497/f0940d82 backport][stable-8] homectl, udm_user: guard crypt imports (#8498)
homectl, udm_user: guard crypt imports (#8497)

Guard crypt import.

(cherry picked from commit f0940d82dc)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-06-13 22:01:30 +02:00
patchback[bot]
4f37a931a0 [PR #8475/8f60f3ae backport][stable-8] Update docs lists_mergeby (#8494)
Update docs lists_mergeby (#8475)

* Fix #8474. Complete examples and documentation of lists_mergeby

* Fix docs syntax O(_input)

* Update docs.

* Update plugins/filter/lists_mergeby.py

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

* Update plugins/filter/lists_mergeby.py

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

* Update plugins/filter/lists_mergeby.py

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

* Update plugins/filter/lists_mergeby.py

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

---------

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

Co-authored-by: Vladimir Botka <vbotka@gmail.com>
2024-06-13 07:47:59 +02:00
patchback[bot]
b756728718 [PR #8477/ac3c0435 backport][stable-8] Update docsite chapter "Merging lists of dictionaries" (#8491)
Update docsite chapter "Merging lists of dictionaries" (#8477)

* Update docs 'Merging lists of dictionaries'

* Adding links to module and plugin options in
  docs/docsite/helper/lists_mergeby
* Add subsections and improve formatting.
* Add example-009 'Merge single list'

* Fix licenses.

* Fix variables.

* Update docs/docsite/helper/lists_mergeby/filter_guide_abstract_informations_merging_lists_of_dictionaries.rst.j2

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

* Update docs/docsite/rst/filter_guide_abstract_informations_merging_lists_of_dictionaries.rst

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

---------

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

Co-authored-by: Vladimir Botka <vbotka@gmail.com>
2024-06-13 07:19:09 +02:00
patchback[bot]
9183c5aea0 [PR #8483/1ae6c825 backport][stable-8] CI: Bump Azure test container to 6.0.0 (#8485)
CI: Bump Azure test container to 6.0.0 (#8483)

Bump Azure test container to 6.0.0.

(cherry picked from commit 1ae6c82558)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-06-10 21:02:23 +02:00
patchback[bot]
7e0f2e1f42 [PR #8452/2a3819a6 backport][stable-8] git_config: fix state=absent if value is present (#8465)
git_config: fix state=absent if value is present (#8452)

* Fix state=absent if value is present.

* Update changelog fragment.

(cherry picked from commit 2a3819a696)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-06-06 13:18:57 +02:00
Felix Fontein
a808b3d7ce [stable-8] fix(opentelemetry): remove request from the logs (#8430) (#8461)
fix(opentelemetry): remove request from the logs (#8430)

* fix(opentelemetry): remove request from the logs

* add changelog

* filter by task

* add new bugfix

* rename

* support legacy and shortcat ansible tasks

* Update plugins/callback/opentelemetry.py

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

---------

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

Co-authored-by: Victor Martinez <victormartinezrubio@gmail.com>
2024-06-04 06:28:38 +02:00
Felix Fontein
03d944be9a [stable-8] Fix the homebrew module failing because of warnings (#8406) (#8429)
Fix the homebrew module failing because of warnings (#8406)

Instead of checking if there is an error message, which can also be a
warning, we now check the return code.

This commit fixes #8229 #7044

Co-authored-by: Strahinja Kustudic <strahinjak@nordeus.com>
(cherry picked from commit 43cb5a0d54)

Co-authored-by: Strahinja Kustudic <kustodian@gmail.com>
2024-06-01 21:32:38 +02:00
patchback[bot]
4c6d439a13 [PR #8403/572caeaa backport][stable-8] keycloak_client: avoid TypeError if result["attributes"] is a list (#8426)
keycloak_client: avoid TypeError if `result["attributes"]` is a list (#8403)

* fix(keycloak_client): avoid TypeError if attributes is a list

As sanitize_cr might be executed after normalise_cr, result['attributes'] can be of type list and we
run into:

TypeError: list indices must be integers or slices, not str

* Update changelog fragment.

---------

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

Co-authored-by: Thomas Bach <63091663+thomasbach-dev@users.noreply.github.com>
2024-05-26 21:17:34 +02:00
patchback[bot]
2ea8850f2d [PR #8309/d96b2642 backport][stable-8] Update lxd_container.py documentation. (#8421)
Update lxd_container.py documentation. (#8309)

remove dead link from debian example

(cherry picked from commit d96b2642bc)

Co-authored-by: Herschdorfer <herschdorfer@gmail.com>
2024-05-26 14:08:30 +02:00
Felix Fontein
cbaac1ca17 [stable-8] docs: add seealso and notes for yaml callback plugin (#8396) (#8398)
docs: add seealso and notes for yaml callback plugin (#8396)

* docs: add seealso and notes for yaml callback plugin

* docs: correct links to parameters

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

* docs: shorten the long lines

---------

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

Co-authored-by: kurokobo <kuro664@gmail.com>
2024-05-20 15:06:02 +00:00
Felix Fontein
0d234ad3f6 Update CI cron schedules.
(cherry picked from commit 95e509753e)
2024-05-20 12:36:21 +02:00
Felix Fontein
195ccc47a1 Next expected release is 8.6.2. 2024-05-20 11:21:10 +02:00
Felix Fontein
5b37e1d204 Release 8.6.1. 2024-05-20 09:04:50 +02:00
patchback[bot]
c323be1ed5 [PR #8392/704a5acc backport][stable-8] From now on automatically add period to new plugins in changelog, and use FQCNs (#8394)
* From now on automatically add period to new plugins in changelog, and use FQCNs (#8392)

From now on automatically add period to new plugins in changelog, and use FQCNs.

(cherry picked from commit 704a5acc63)

* Update changelogs.

---------

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-05-20 09:02:56 +02:00
Felix Fontein
0a0e132d80 [stabe-8] fix(opentelemetry): avoid storing inmemory if logs are disabled (#8373) (#8390)
fix(opentelemetry): avoid storing inmemory if logs are disabled (#8373)

* fix(opentelemetry): avoid storing inmemory if logs are disabled

* changelog

* fix syntax

* refactor

* chore

* chore

* chore

* fix

(cherry picked from commit d87b9fe0dc)

Co-authored-by: Victor Martinez <victormartinezrubio@gmail.com>
2024-05-19 21:57:27 +02:00
patchback[bot]
eff8ca8d9b [PR #8367/03240ad7 backport][stable-8] fix(opentelemetry): close span even if no logs are sent (#8389)
fix(opentelemetry): close span even if no logs are sent (#8367)

* fix(opentelemetry): close span even if no logs are sent

* changelog

(cherry picked from commit 03240ad7dc)

Co-authored-by: Victor Martinez <victormartinezrubio@gmail.com>
2024-05-19 21:32:06 +02:00
Felix Fontein
711c5f3eb5 Prepare 8.6.1 release. 2024-05-18 16:34:02 +02:00
patchback[bot]
ff8a3ca2e6 [PR #8377/da8b133a backport][stable-8] add clarifying notes to scope description (#8386)
add clarifying notes to scope description (#8377)

(cherry picked from commit da8b133a73)

Co-authored-by: Jay Hendren <3742215+jayhendren@users.noreply.github.com>
2024-05-18 16:30:30 +02:00
patchback[bot]
b5f1c6adf6 [PR #8365/cd01a928 backport][stable-8] Add REUSE badge (#8376)
Add REUSE badge (#8365)

Add REUSE badge.

(cherry picked from commit cd01a928ab)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-05-15 21:11:53 +02:00
patchback[bot]
a0f79d6d07 [PR #8355/fabf6263 backport][stable-8] Fix sanitize for keycloak_identitiy_provider. (#8371)
Fix sanitize for keycloak_identitiy_provider. (#8355)

* Fix sanitize for keycloak_identitiy_provider.

* Apply suggestions from code review

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

---------

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

Co-authored-by: Florian Apolloner <florian@apolloner.eu>
2024-05-15 19:59:44 +02:00
patchback[bot]
2ff60c1485 [PR #8345/7aa118b9 backport][stable-8] Add test for unsafe plugin util (#8348)
Add test for unsafe plugin util (#8345)

Add test for unsafe plugin util.

(cherry picked from commit 7aa118b957)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-05-12 01:01:11 +02:00
patchback[bot]
9ef7dd4d79 [PR #8341/b774435d backport][stable-8] Pass codecov token to ansible-test-gh-action (#8344)
Pass codecov token to ansible-test-gh-action (#8341)

Pass codecov token to ansible-test-gh-action.

(cherry picked from commit b774435d8d)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-05-11 21:47:39 +02:00
patchback[bot]
0537e1d81e [PR #8320/a71e1913 backport][stable-8] keycloak_user_federation: fix diff of empty krbPrincipalAttribute (#8340)
keycloak_user_federation: fix diff of empty `krbPrincipalAttribute` (#8320)

keycloak_user_federation: fix diff of empty `krbPrincipalAttribute` (#8320)

(cherry picked from commit a71e19130d)

Co-authored-by: Eike Waldt <waldt@b1-systems.de>
2024-05-11 17:11:27 +02:00
patchback[bot]
01a54bba2f [PR #8303/136419c5 backport][stable-8] bug(lookup/merge_variables): Fix rendering foreign variables (#8338)
bug(lookup/merge_variables): Fix rendering foreign variables (#8303)

* manually prepare variables of foreign host including hostvars property

* render variables from context of current host

* add integration test for cross host merge

* lint fixes

* adjust cross host merge unit tests to provide a tiny bit of the HostVars Class API

* add license information

* lint

* add changelog fragment

* Update tests/integration/targets/lookup_merge_variables/test_cross_host_merge_play.yml

Okay

Co-authored-by: Mark <40321020+m-a-r-k-e@users.noreply.github.com>

* Update tests/integration/targets/lookup_merge_variables/test_cross_host_merge_play.yml

Okay

Co-authored-by: Mark <40321020+m-a-r-k-e@users.noreply.github.com>

* Update tests/integration/targets/lookup_merge_variables/test_cross_host_merge_play.yml

Okay

Co-authored-by: Mark <40321020+m-a-r-k-e@users.noreply.github.com>

* rename _HostVars to HostVarsMock

* removing unnecessary task

---------

Co-authored-by: Gitlab CI <alexander.petrenz@posteo.de>
Co-authored-by: Mark <40321020+m-a-r-k-e@users.noreply.github.com>
(cherry picked from commit 136419c5c0)

Co-authored-by: Alexander Petrenz <petrenz.a@gmail.com>
2024-05-11 17:11:18 +02:00
patchback[bot]
4c39295b97 [PR #8322/bc7ad0f0 backport][stable-8] CONTRIBUTING.md: update link for changelog fragments, and add more text on them (#8336)
CONTRIBUTING.md: update link for changelog fragments, and add more text on them (#8322)

Update link for changelog fragments, and add more text on them.

(cherry picked from commit bc7ad0f0ea)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-05-10 16:21:29 +02:00
patchback[bot]
e9977935a4 [PR #8310/cb985b31 backport][stable-8] docs(gitlab_runner): improve docs and add examples (#8333)
docs(gitlab_runner): improve docs and add examples (#8310)

(cherry picked from commit cb985b31f9)

Co-authored-by: Léo GATELLIER <26511053+lgatellier@users.noreply.github.com>
2024-05-10 15:31:12 +02:00
patchback[bot]
f1d865f318 [PR #8325/feb443d2 backport][stable-8] Fix django_manage tests (#8328)
Fix django_manage tests (#8325)

Ensure that manage.py is executable.

(cherry picked from commit feb443d260)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-05-07 08:24:34 +02:00
patchback[bot]
c2900e7dec [PR #8313/bc609d74 backport][stable-8] Disable ejabberd tests on Arch Linux (#8319)
Disable ejabberd tests on Arch Linux (#8313)

Disable ejabberd tests on Arch Linux.

(cherry picked from commit bc609d74a0)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-05-05 20:42:52 +02:00
patchback[bot]
c1b1fc6c04 [PR #8312/4bd68ac1 backport][stable-8] Disable cpanm tests for RHEL 7 and CentOS 7 (#8317)
Disable cpanm tests for RHEL 7 and CentOS 7 (#8312)

Disable cpanm tests for RHEL 7 and CentOS 7.

(cherry picked from commit 4bd68ac153)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-05-05 20:42:40 +02:00
patchback[bot]
6341e0a44a [PR #8291/fc2024d8 backport][stable-8] CI: Arch Linux switched to Python 3.12 (#8293)
CI: Arch Linux switched to Python 3.12 (#8291)

Arch Linux switched to Python 3.12.

(cherry picked from commit fc2024d837)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-04-28 19:07:35 +02:00
patchback[bot]
df38c95524 [PR #8237/45c2e0f8 backport][stable-8] use smaller snap, add disabled to aliases (#8284)
use smaller snap, add disabled to aliases (#8237)

* use smaller snap, add disabled to aliases

* rollback tag disabled in aliases

* comment out the test_dangerous as it takes too long

* comment out the test_dangerous as it takes too long

* Update tests/integration/targets/snap/tasks/main.yml

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

---------

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

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2024-04-26 21:09:48 +02:00
Felix Fontein
8fea58c51b The next release will be 8.6.1. 2024-04-22 18:50:32 +02:00
Felix Fontein
1f0e255a9d Release 8.6.0. 2024-04-22 18:24:25 +02:00
patchback[bot]
0299b31416 [PR #8263/17e11d7d backport][stable-8] apt_rpm: fix package install check (#8270)
apt_rpm: fix package install check (#8263)

Fix package install check.

(cherry picked from commit 17e11d7d7e)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-04-22 06:51:56 +02:00
patchback[bot]
0486389f8e [PR #8247/211688ef backport][stable-8] apt_rpm: add new states 'latest' and 'present_not_latest' (#8268)
apt_rpm: add new states 'latest' and 'present_not_latest' (#8247)

* Add new states 'latest' and 'present_not_latest'.

* Improve documentation.

(cherry picked from commit 211688ef1b)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-04-21 21:16:28 +02:00
patchback[bot]
b4e61a554f [PR #8221/07356563 backport][stable-8] Add support for state=latest to flatpak module (#8265)
Add support for state=latest to flatpak module (#8221)

Fixes #6563 by extending the allowed values of the `state` parameter to
include `latest`. To do this, the `update_flat()` function is introduced
which borrows the majority of its implementation from both the existing
`install_flat()` and `remove_flat()` functions. The documentation and
examples have been expanded describing what to expect when using
`state=latest`.

(cherry picked from commit 0735656319)

Co-authored-by: Kenneth Benzie (Benie) <k.benzie83@gmail.com>
2024-04-21 20:39:55 +02:00
patchback[bot]
aa384be6fe [PR #8252/a5697da2 backport][stable-8] Keycloak client role scope (#8266)
Keycloak client role scope (#8252)

* first commit

* minor update

* fixe Copyright

* fixe sanity

* Update plugins/modules/keycloak_client_rolescope.py

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

* fixe sanity 2

* Update plugins/modules/keycloak_client_rolescope.py

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

---------

Co-authored-by: Andre Desrosiers <andre.desrosiers@ssss.gouv.qc.ca>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit a5697da29c)

Co-authored-by: desand01 <desrosiers.a@hotmail.com>
2024-04-21 20:39:47 +02:00
patchback[bot]
bc829f64bc [PR #8257/af1c5dd7 backport][stable-8] Add accept-new as valid option for ssh_config host key checking (#8267)
Add accept-new as valid option for ssh_config host key checking (#8257)

* Add accept-new as valid option for host key checking

* Add changelog fragment for #8257

* Apply suggestions from code review

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

---------

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

Co-authored-by: Maxopoly <max@dermax.org>
2024-04-21 20:39:32 +02:00
patchback[bot]
07953bb995 [PR #8236/be11d0d4 backport][stable-8] Add an explicit select option to portage module (#8259)
Add an explicit `select` option to `portage` module (#8236)

* Add an explicit `select` option to `portage` module

This is a fix for #6226

* Apply suggestions from code review

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

* Default `select` option to None, making it more retrocompatible

* Add changelog fragment for the PR

* Update changelogs/fragments/8236-portage-select-feature.yml

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

---------

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

Co-authored-by: Thomas Langé <thomas.lange.oss@gmail.com>
2024-04-21 15:10:14 +02:00
patchback[bot]
111593f794 [PR #8238/a05a5982 backport][stable-8] bitwarden_secrets_manager: implement rate limit retry with backoff (#8261)
bitwarden_secrets_manager: implement rate limit retry with backoff (#8238)

* bitwarden_secrets_manager: implement rate limit retry with backoff (#8230)

* bitwarden_secrets_manager: add changelog fragment for 90cd2d61 (#8238)

* bitwarden_secrets_manager: clarify "Too many requests" is an error condition (#8238)

* bitwarden_secrets_manager: avoid an extra _run_with_retry execution after the last (very long) delay

* bitwarden_secrets_manager: changelog fragment key and reference issue url

(cherry picked from commit a05a5982a6)

Co-authored-by: Matt Adams <matt@4dk.me>
2024-04-21 15:10:07 +02:00
patchback[bot]
9ff5e6f757 [PR #8153/8f98ba91 backport][stable-8] java_cert: add cert_content argument (#8262)
java_cert: add cert_content argument (#8153)

* add cert_content arg (#8034)

* add changelog fragment (#8034)

* Update plugins/modules/java_cert.py

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

---------

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

Co-authored-by: Denis Borisov <dborisov86@gmail.com>
2024-04-21 15:10:00 +02:00
patchback[bot]
a64098cd76 [PR #8224/9d66a1dc backport][stable-8] keycloak_realm: add normalizations for enabledEventTypes, and supportedLocales (#8256)
keycloak_realm: add normalizations for enabledEventTypes, and supportedLocales (#8224)

keycloak_realm: add nomalizations for enabledEventTypes, and supportedLocales

Signed-off-by: Eike Waldt <waldt@b1-systems.de>
(cherry picked from commit 9d66a1dc1e)

Co-authored-by: Eike Waldt <waldt@b1-systems.de>
2024-04-21 09:10:39 +02:00
patchback[bot]
dd74e29558 [PR #8223/f55342d8 backport][stable-8] keycloak_client: add sorted defaultClientScopes and optionalClientScopes to normalizations (#8254)
keycloak_client: add sorted defaultClientScopes and optionalClientScopes to normalizations (#8223)

keycloak_client: add sorted defaultClientScopes and optionalClientScopes
to normalizations

Signed-off-by: Eike Waldt <waldt@b1-systems.de>
(cherry picked from commit f55342d8af)

Co-authored-by: Eike Waldt <waldt@b1-systems.de>
2024-04-21 09:10:29 +02:00
patchback[bot]
d19b4f958b [PR #8126/486c26b2 backport][stable-8] filesystem: add bcachefs support (#8251)
filesystem: add bcachefs support (#8126)

Signed-off-by: Stijn Tintel <stijn@linux-ipv6.be>
(cherry picked from commit 486c26b224)

Co-authored-by: Stijn Tintel <stijn@linux-ipv6.be>
2024-04-20 14:29:42 +02:00
patchback[bot]
6c4020e48b [PR #8188/865de5ba backport][stable-8] bitwarden - add support for filtering by organization_id (#8249)
bitwarden - add support for filtering by organization_id (#8188)

* bitwarden - add support for filtering by organization_id

* Update changelogs/fragments/8188-bitwarden-add-organization_id.yml

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

* implement PR discussion result on wording

* rewrite search_field filtering

To correctly handle organization_id and collection_id by passing both to bw.
Tests needed to be extended to filter organizations / collections and
the testdata needed changes to reflect that a collection always belongs to a
single organizaion

---------

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

Co-authored-by: Kai <github@sistason.de>
2024-04-20 14:29:33 +02:00
patchback[bot]
60e4269024 [PR #7505/be4d5b7d backport][stable-8] ini_file - add feature 'section_has_values' (#8250)
ini_file - add feature 'section_has_values' (#7505)

* insert new code

* add changelog

* add argument_spec

* sanity check

* docstring version_added

* version-added-must-be-major-or-minor

* Update plugins/modules/ini_file.py

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

* check for default value  `None`

* typo in example

* add integration test and rename option

* add license

* update "version added" in docstring

* insert new code

* remove whitespace

* update examples

* support exclusive, allow_no_value, multiple values in section_has_values

* prefer Todd's variable naming in loops

* resolve number clash in file names

* pass sanity test validate-modules

* Documentation updates

---------

Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Todd Lewis <todd_lewis@unc.edu>
(cherry picked from commit be4d5b7dc4)

Co-authored-by: Jakob Lund <jakob@avforlaget.dk>
2024-04-20 14:29:24 +02:00
patchback[bot]
4832100d76 [PR #8222/524d5883 backport][stable-8] Avoid deprecated utcnow() (#8243)
Avoid deprecated utcnow() (#8222)

Avoid deprecated utcnow().

(cherry picked from commit 524d5883b8)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-04-20 10:21:02 +02:00
patchback[bot]
83738f21a3 [PR #8001/1b8e6bc9 backport][stable-8] puppet_utils: Do not force lang for cmd (#8242)
puppet_utils: Do not force lang for cmd (#8001)

puppet_utils: Add option to set LANG for puppet execution

Add option `environment_lang` to force the LANG when executing the
puppet agent. The default is the `C` LANG

(cherry picked from commit 1b8e6bc95b)

Co-authored-by: Niklas Schwarz <schwarz.niklas@hotmail.de>
2024-04-20 10:20:55 +02:00
patchback[bot]
6f60692dd1 [PR #8189/1bbef588 backport][stable-8] Deprecate hipchat callback (#8240)
Deprecate hipchat callback (#8189)

* Deprecate hipchat callback.

* Avoid duplicate 'callback' key.

(cherry picked from commit 1bbef58844)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-04-20 10:20:48 +02:00
patchback[bot]
3e67b6cc8b [PR #8216/a5b2b5ce backport][stable-8] Add support for docker-v2 protocol in Keycloak modules (#8239)
Add support for docker-v2 protocol in Keycloak modules (#8216)

* Add support for docker-v2 protocol in Keycloak modules

* use dash instead of underscore for the docker-v2

* Update documentation

* Add changelog fragment

* fix missing whitespace around operator

* Update changelogs/fragments/8215-add-docker-v2-protocol.yml

Update changelog fragment to reviewers suggestion, add refrence to issue and pull request

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

* Add documentation about adding docker-v2 value in community general 8.6.0

---------

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

Co-authored-by: Anders Stiksrud Helmen <anders.s.helmen@gmail.com>
2024-04-20 10:20:41 +02:00
patchback[bot]
7791fd28ab [PR #8225/7fd37ea2 backport][stable-8] inventory plugins: make wrapping variables as unsafe smarter to avoid triggering an AWX bug (#8246)
inventory plugins: make wrapping variables as unsafe smarter to avoid triggering an AWX bug (#8225)

Make wrapping variables as unsafe smarter to avoid triggering an AWX bug.

(cherry picked from commit 7fd37ea247)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-04-20 10:20:32 +02:00
patchback[bot]
9e7371a510 [PR #8234/12b76ead backport][stable-8] Include changelog in docsite (#8235)
Include changelog in docsite (#8234)

Include changelog in docsite.

(cherry picked from commit 12b76ead29)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-04-18 12:39:42 +02:00
Felix Fontein
b54f07d27f Prepare 8.6.0 release. 2024-04-18 07:59:14 +02:00
patchback[bot]
5a0282a8ba [PR #8166/da29ea15 backport][stable-8] passwordstore: Add missing_subkey parameter (#8233)
passwordstore: Add missing_subkey parameter (#8166)

* passwordstore: Add missing_subkey parameter

Add ability to trigger error or warning when a subkey is missing in pass file.
By default the behavior is unchanged (if subkey is missing, None is returned).
This option can also be set in ansible.cfg

* passwordstore - missing_subkey: Update changelog/fragments file with PR number

* Apply suggestions from code review

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

---------

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

Co-authored-by: Manuel Luzarreta <mluzarreta.pro@pm.me>
2024-04-17 23:45:38 +02:00
patchback[bot]
6b81091de6 [PR #8211/bafad8ec backport][stable-8] Support newer 'riak admin' sub-command beside legacy 'riak-admin' command (#8232)
Support newer 'riak admin' sub-command beside legacy 'riak-admin' command (#8211)

* Support newer 'riak admin' sub-command

* Added changelog for riak admin sub-command

* Added blank line

* Apply suggestions from code review

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

* replaced string commands with lists

added white space

removed white space

removed parenthesis

* Update changelogs/fragments/8211-riak-admin-sub-command-support.yml

Co-authored-by: Don Naro <dnaro@redhat.com>

---------

Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Don Naro <dnaro@redhat.com>
(cherry picked from commit bafad8ecd4)

Co-authored-by: tobixx <tobixx@directbox.com>
2024-04-17 23:45:26 +02:00
patchback[bot]
f312d2af5e [PR #8195/6c8f949b backport][stable-8] Redfish: add Multipart bool return value to FirmwareUpdateCapabilities (#8218)
Redfish: add `Multipart` bool return value to `FirmwareUpdateCapabilities` (#8195)

* Redfish: add Multipart bool return value to FirmwareUpdateCapabilities

Fixes #8194

Signed-off-by: Boris Glimcher <Boris.Glimcher@emc.com>

* Update changelogs/fragments/8194-redfish-add-multipart-to-capabilities.yml

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

---------

Signed-off-by: Boris Glimcher <Boris.Glimcher@emc.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 6c8f949ba9)

Co-authored-by: Boris Glimcher <36732377+glimchb@users.noreply.github.com>
2024-04-13 13:59:00 +02:00
patchback[bot]
66200a5da5 [PR #8185/9307b76e backport][stable-8] fix: Ensuring interpolation is disabled for ConfigParser (#8210)
fix: Ensuring interpolation is disabled for ConfigParser (#8185)

* fix: Ensuring interpolation is disabled for ConfigParser

This PR disables interpolation of ConfigParser and adds test coverage for that.

* Adding changelog fragment

* Fixing missing extension of changelog fragment

* Adding issue link to changelog fragment

* Update changelogs/fragments/8183-from_ini_to_ini.yml

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

---------

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

Co-authored-by: Steffen Scheib <37306894+sscheib@users.noreply.github.com>
2024-04-09 12:28:37 +02:00
patchback[bot]
39dd596e67 [PR #8176/8491bf7b backport][stable-8] fix(aix_filesystem): remove extra param from running lsvg (#8209)
fix(aix_filesystem): remove extra param from running lsvg (#8176)

* fix(aix_filesystem): remove extra param from running lsvg

* chore: add new line to changlog file

* Update 8151-fix-lsvg_cmd-failed.yml

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

---------

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

Co-authored-by: Peter Shen <xianpeng.shen@gmail.com>
2024-04-09 08:01:28 +02:00
patchback[bot]
2cf6fdf2c3 [PR #8175/b674f94f backport][stable-8] module_utils/ipa.py: fix regex when parsing version (#8206)
module_utils/ipa.py: fix regex when parsing version (#8175)

* module_utils/ipa.py: fix regex when parsing version

* add changelog fragments

* Update changelogs/fragments/8175-get_ipa_version_regex.yml

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

---------

Co-authored-by: Dmitriy Usachev <dmitrii.usachev@hyperus.team>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit b674f94f64)

Co-authored-by: Dmitriy Usachev <diman-110@list.ru>
2024-04-09 08:01:16 +02:00
patchback[bot]
1fd2bd6046 [PR #8154/39ef949f backport][stable-8] Update nmcli.py to support OVS commands (#8207)
Update nmcli.py to support OVS commands (#8154)

* Update nmcli.py to support OVS commands

Adding Openvswitch command support and documentation to the nmcli module

* Fixed versioning and documentation, added changelog fragment

* Update changelogs/fragments/8154-add-ovs-commands-to-nmcli-module.yml

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

* Update plugins/modules/nmcli.py

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

---------

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

Co-authored-by: Codey Schoettle <165081359+c-cschoettle@users.noreply.github.com>
2024-04-09 08:01:00 +02:00
patchback[bot]
cec99472d9 [PR #8173/bc2ff24f backport][stable-8] Add check_type option, to allow defaults type changes (#8203)
Add check_type option, to allow defaults type changes (#8173)

* Add check_type option, to allow defaults type changes

* Add changelog fragment

* Changelog fragments are yaml, not markdown

* Update changelogs/fragments/8173-osx_defaults-check_type.yml

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

* Update plugins/modules/osx_defaults.py

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

---------

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

Co-authored-by: Kris Matthews <krismatthews@users.noreply.github.com>
2024-04-09 07:41:48 +02:00
patchback[bot]
2bbc531354 [PR #8168/610ecf9b backport][stable-8] updated lxd_container.py docs (#8197)
updated lxd_container.py docs (#8168)

linuxcontainer.org has phased out LXC/LXD support.
This edit reflects part of it in the docs.

(cherry picked from commit 610ecf9bf5)

Co-authored-by: Herschdorfer <herschdorfer@gmail.com>
2024-04-08 22:06:20 +02:00
patchback[bot]
bd230dc41c [PR #8190/13d0310e backport][stable-8] CI: ansible-core devel removed Python 3.7 support, no longer allows 'vars:' with lists (#8191)
CI: ansible-core devel removed Python 3.7 support, no longer allows 'vars:' with lists (#8190)

* Ansible-core devel removed Python 3.7 support.

* Do not use 'vars' with lists.

(cherry picked from commit 13d0310e91)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-04-05 07:17:30 +02:00
patchback[bot]
07f1e0feba [PR #8164/e4e091ac backport][stable-8] Redfish: implementing ResetToDefaults (#8182)
Redfish: implementing ResetToDefaults (#8164)

Fixing #8163

Signed-off-by: Boris Glimcher <Boris.Glimcher@emc.com>
(cherry picked from commit e4e091acca)

Co-authored-by: Boris Glimcher <36732377+glimchb@users.noreply.github.com>
2024-04-03 19:55:35 +02:00
patchback[bot]
bdd046b411 [PR #8179/48b5a7a8 backport][stable-8] CI: add stable-2.17, bump devel to 2.18, move stable-2.14 from AZP to GHA (#8181)
CI: add stable-2.17, bump devel to 2.18, move stable-2.14 from AZP to GHA (#8179)

* Add stable-2.17 to CI; add ignores for 2.18.

* Move stable-2.14 tests to GHA.

* Update README.

(cherry picked from commit 48b5a7a80a)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-04-03 08:32:39 +02:00
patchback[bot]
49fb3d7cb8 [PR #8169/b444e873 backport][stable-8] xml: make module work with lxml 5.1.1 (#8172)
xml: make module work with lxml 5.1.1 (#8169)

Make module work with lxml 5.1.1.

(cherry picked from commit b444e8739c)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-03-30 22:48:39 +01:00
patchback[bot]
45375b201f [PR #8158/b4635719 backport][stable-8] gitlab modules: do not crash if python-gitlab isn't there (#8167)
gitlab modules: do not crash if python-gitlab isn't there (#8158)

Do not crash if python-gitlab isn't there.

(cherry picked from commit b463571902)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-03-29 19:28:08 +01:00
patchback[bot]
df8208afe1 [PR #8100/b2b8fc30 backport][stable-8] HAProxy skips the wait when drain=true and the backend is down - fix issue 8092 (#8157)
HAProxy skips the wait when drain=true and the backend is down - fix issue 8092 (#8100)

* fix issue 8092

* "is not" => "!="

* moved the drain & down cause to the wait

* added changelogs for PR 8100

* fixed yaml

* fixed file type

* Apply suggestions from code review

Removed a dot from a comment

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

* Update plugins/modules/haproxy.py

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

---------

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

Co-authored-by: RayJin2000 <rayjin2000@gmail.com>
2024-03-28 12:34:51 +01:00
Felix Fontein
63f4a16006 The next expected release is 8.6.0. 2024-03-25 19:44:03 +01:00
Felix Fontein
a179f89686 Release 8.5.0. 2024-03-25 19:01:45 +01:00
patchback[bot]
9e641019be [PR #8116/4f758bfb backport][stable-8] java_cert: owner, group, mode arguments enabled (#8152)
java_cert: owner, group, mode arguments enabled (#8116)

* java_cert: owner, group, mode arguments enabled

* java_cert: sanity fix

* add changelog fragment

* remove duplication in documentation

* refactor change detection

* fix indentation

* Update changelogs/fragments/8116-java_cert-enable-owner-group-mode-args.yml

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

* Update plugins/modules/java_cert.py

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

* Update plugins/modules/java_cert.py

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

* update options

---------

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

Co-authored-by: Denis Borisov <dborisov86@gmail.com>
2024-03-25 18:51:00 +01:00
Felix Fontein
029b811c7b Add release summary. 2024-03-25 06:52:38 +01:00
patchback[bot]
df95f02c7b [PR #8098/d62fe154 backport][stable-8] inventory plugins: make data obtained from remote unsafe (#8146)
inventory plugins: make data obtained from remote unsafe (#8098)

Make data obtained from remote unsafe.

(cherry picked from commit d62fe154d2)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-03-25 06:50:08 +01:00
patchback[bot]
baa45d044c [PR #8148/609f28f7 backport][stable-8] snap: disable some tests that take way too long (#8150)
snap: disable some tests that take way too long (#8148)

* Do not install microk8s in snap tests, as it is too slow.

* Do not install cider in snap tests, as it is slow.

(cherry picked from commit 609f28f791)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-03-25 06:49:55 +01:00
patchback[bot]
8e9e989f8a [PR #8133/b389f863 backport][stable-8] Add descriptive error message to Linode inventory plugin file checkin… (#8144)
Add descriptive error message to Linode inventory plugin file checkin… (#8133)

* Add descriptive error message to Linode inventory plugin file checking, tests

* add changelog fragment

* Adjust changelog fragment.

---------

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

Co-authored-by: Gideon <soccerman.gid@gmail.com>
2024-03-24 22:51:48 +01:00
patchback[bot]
94890668a2 [PR #8038/795a855d backport][stable-8] Added startup configuration option (#8142)
Added startup configuration option (#8038)

* Added startup configuration option

Added the option to configure startup behavior of lxc containers. Works well in conjunction with onboot and allows to set startup order, startup delay and shutdown delay

* Removed trailing whitespaces in documentation

* added changelog fragment

* Updated Documentation to suggested wording

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

* Improve documentation.

* Fix changelog fragment.

---------

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

Co-authored-by: Michael Cicogna <44257895+miccico@users.noreply.github.com>
2024-03-24 22:51:37 +01:00
patchback[bot]
d2e0d04336 [PR #7880/9f5193e4 backport][stable-8] ipa_sudorule, ipa_hbacrule: change ipaenabledflag type to bool (#8139)
ipa_sudorule, ipa_hbacrule: change ipaenabledflag type to bool (#7880)

* ipa_sudorule, ipa_hbacrule: change ipaenabledflag type to bool

freeipa changed the type to bool with commit https://pagure.io/freeipa/c/6c5f2bcb301187f9844985ffe309c7d2262e16f3

* add changelog-fragment

* ipa_sudorule, ipa_hbacrule: set ipaenabledflag according to version

* ipa_sudorule, ipa_hbacrule: change version for backport

it also got backported (https://pagure.io/freeipa/c/faeb656c77adf27a49ccaceb57fc1ba44e11cc1d)

* ipa_sudorule, ipa_hbacrule: swap assigned values

* Update changelogs/fragments/7880-ipa-fix-sudo-and-hbcalrule-idempotence.yml

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

---------

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

Co-authored-by: aBUDmdBQ <135135848+aBUDmdBQ@users.noreply.github.com>
2024-03-24 18:26:40 +01:00
patchback[bot]
6e0fa9042c [PR #8118/a4b32d7b backport][stable-8] Fix bond-slave honoring MTU (#8141)
Fix bond-slave honoring MTU (#8118)

The bond-slave type should honor the request
MTU value.

(cherry picked from commit a4b32d7b9c)

Co-authored-by: Tobias Urdin <tobias.urdin@gmail.com>
2024-03-24 18:26:34 +01:00
patchback[bot]
bbd924d67c [PR #8013/f5fa16c8 backport][stable-8] feat(lookup/bitwarden): add support for fetching all items from a collection (#8140)
feat(lookup/bitwarden): add support for fetching all items from a collection (#8013)

Signed-off-by: Emilien Escalle <emilien.escalle@escemi.com>
(cherry picked from commit f5fa16c881)

Co-authored-by: Emilien Escalle <neilime@users.noreply.github.com>
2024-03-24 18:26:26 +01:00
patchback[bot]
1a77ca9b8c [PR #8029/23396e62 backport][stable-8] Fix check mode in iptables_state for incomplete iptables-save files along with integration tests (#8137)
Fix check mode in iptables_state for incomplete iptables-save files along with integration tests (#8029)

* Implement integration test to reproduce #7463

* Make new iptables_state checks async

* Add missing commit to iptable_state integration test

* Remove async when using checkmode in iptables_state integration tests

* Do per table comparison in check mode for iptables_state

* Calculate changes of iptables state per table based on result

* Output target iptables state in checkmode

* Refactor calculation of invidual table states in iptables_state

* Add missing return for table calculation

* Add missing arg to regex check

* Remove leftover debug output for target iptable state

* Parse per table state from raw state string

* Join restored state for extration of table specific rules

* Switch arguments for joining restored iptable state

* Output final ip table state

* Compare content of tables

* Complete iptables partial tables test cases

* Correct order of test iptables data

* Update docu for iptables tables_after

* Add changelog fragment

* Appease the linting gods for iptables_state

* Adjust spelling and remove tables_after from return values

(cherry picked from commit 23396e62dc)

Co-authored-by: Maxopoly <max@dermax.org>
2024-03-24 18:26:15 +01:00
patchback[bot]
7b66573df0 [PR #8075/4363f876 backport][stable-8] ini_file - support optional spaces around section names (#8135)
ini_file - support optional spaces around section names (#8075)

* ini_file - support optional spaces between section names and their surrounding brackets

Some ini files have spaces between some of their section names and the
brackets that enclose them. This is documented in the 'openssl.cnf(5)' man
page. In order to manage files such as /etc/ssl/openssl.cnf with ini_file
before now, one would have to include spaces in the section name like this:
    section: ' crypto_policy '
    option: Options
    value: UnsafeLegacyRenegotiation

This change implements matching section headers with such optional spaces.
Existing tasks using the workaround above will continue to work, even in
cases where spaces in section headers are subsequently removed.

* readability improvement in the test content expressions

---------

Co-authored-by: Todd Lewis <todd_lewis@unc.edu>
(cherry picked from commit 4363f8764b)

Co-authored-by: Todd Lewis <utoddl@gmail.com>
2024-03-24 18:26:01 +01:00
patchback[bot]
c494fe5824 [PR #7998/4947786d backport][stable-8] Adds group_by_hostgroups parameter to Icinga2 inventory (#8134)
Adds group_by_hostgroups parameter to Icinga2 inventory (#7998)

* (lots of commit messages)

---------

Co-authored-by: Gianluca Salvo <gianluca.salvo@gruppomol.it>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 4947786d36)

Co-authored-by: Gianluca Salvo <Gianlu@users.noreply.github.com>
2024-03-24 18:25:52 +01:00
patchback[bot]
dba4357b65 [PR #8130/fb67df30 backport][stable-8] Ignore pylint warnings for construct that does not work with Python 2 (#8132)
Ignore pylint warnings for construct that does not work with Python 2 (#8130)

* Ignore pylint warnings for construct that does not work with Python 2.

* Revert "Ignore pylint warnings for construct that does not work with Python 2."

This reverts commit 51d559cc94.

* Different approach: use ignore.txt since otherwise ansible-core 2.14 tests fail.

(cherry picked from commit fb67df3051)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-03-23 18:12:05 +01:00
patchback[bot]
c67f3b1e99 [PR #8127/da048aa1 backport][stable-8] CI: Move Alpine 3.18 docker to stable-2.16, add Alpine 3.19 docker, bump Alpine VM to 3.19 (#8129)
CI: Move Alpine 3.18 docker to stable-2.16, add Alpine 3.19 docker, bump Alpine VM to 3.19 (#8127)

Move Alpine 3.18 docker to stable-2.16, add Alpine 3.19 docker, bump Alpine VM to 3.19.

(cherry picked from commit da048aa12e)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-03-22 13:40:16 +01:00
patchback[bot]
fd026a195c [PR #8122/47b4cf76 backport][stable-8] CI: Add FreeBSD 13.3 and 14.0 for devel, move FreeBSD 13.2 to stable-2.16 (#8125)
CI: Add FreeBSD 13.3 and 14.0 for devel, move FreeBSD 13.2 to stable-2.16 (#8122)

* Add FreeBSD 13.3 and 14.0 for devel, move FreeBSD 13.2 to stable-2.16.

* Skip some targets.

* Skip pkgng jail tests (again :( ).

(cherry picked from commit 47b4cf766e)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-03-22 06:25:23 +01:00
patchback[bot]
f751abf81d [PR #8114/69ab5eb1 backport][stable-8] Fix plugin call in example (#8120)
Fix plugin call in example (#8114)

(cherry picked from commit 69ab5eb110)

Co-authored-by: Kristof Wevers <kwevers@users.noreply.github.com>
2024-03-20 08:30:39 +01:00
patchback[bot]
6071bbc200 [PR #8076/6298ad4f backport][stable-8] Implement usb_facts module (#8115)
Implement usb_facts module (#8076)

* First implementation of usb module

* Rename to usb_facts

* Working tests

* Appease linter

* Fix author

* Remove splitlines arg for python 2.7 compat

* indent usb test further

* indent usb test a bit less

* Remove trailing whitespace

* Update plugins/modules/usb_facts.py

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

* Update plugins/modules/usb_facts.py

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

* Apply suggestions from code review

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

* Adjust usb_facts PR based on feedback

* Add usage example and extend correct documentation fragment

* Add myself to BOTMETA.yml

* Apply suggestions from code review

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

---------

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

Co-authored-by: Maxopoly <max@dermax.org>
2024-03-19 06:39:46 +01:00
patchback[bot]
a63bb9405a [PR #8052/73b6b98e backport][stable-8] Aix filesystem crfs issue (#8112)
Aix filesystem crfs issue (#8052)

* crfs issue in aix_filesystem.py

Change the crfs logic and fields, since empty options and order seem to be an issue.

this quick fix seems to solve it

* Create aix_filesystem-crfs-issue.yml

changelog fragment

* fix

fix typo

* Update changelogs/fragments/aix_filesystem-crfs-issue.yml

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

* Refactored based on feeback and testing

Refactored the changes i did based on the comments and testing. Also changed the attribute default values because they were causing errors

* blank line whitespaces

* fix default

---------

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

Co-authored-by: Mike <mike@php-webdesign.nl>
2024-03-17 17:40:33 +01:00
patchback[bot]
e762e952d8 [PR #8103/1c4197aa backport][stable-8] Skip cloud_init_data_facts tests on OpenSuSE Leap 15 (#8109)
Skip cloud_init_data_facts tests on OpenSuSE Leap 15 (#8103)

Skip cloud_init_data_facts tests on OpenSuSE Leap 15.5.

(cherry picked from commit 1c4197aa23)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-03-17 17:17:40 +01:00
patchback[bot]
df9ff544ef [PR #8102/23fbc5e2 backport][stable-8] Fix pacman tests in CI (#8106)
Fix pacman tests in CI (#8102)

Fix pacman tests.

(cherry picked from commit 23fbc5e241)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-03-17 17:01:07 +01:00
patchback[bot]
aece6ef400 [PR #8073/09cded05 backport][stable-8] Add --diff support for ldap_attrs module (#8099)
Add --diff support for ldap_attrs module (#8073)

* Add --diff support for ldap_attrs module

* Change diff_mode support in docstring to full

* Use _attrs suffix for old and new

* Add version added to ldap_attrs diff mode

* Add fragment for ldap_attrs diff mode

* Update fragment to include link to PR and lowercase start

* Update changelogs/fragments/8073-ldap-attrs-diff.yml

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

---------

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

Co-authored-by: StopMotionCuber <ruben.simons@web.de>
2024-03-14 23:39:18 +01:00
patchback[bot]
12ab33df84 [PR #8091/67736d79 backport][stable-8] Fix consul_token usage without accessor_id. (#8097)
Fix consul_token usage without accessor_id. (#8091)

* Fix consul_token usage without accessor_id.

* Update changelogs/fragments/8091-consul-token-fixes.yaml

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

* Update plugins/modules/consul_token.py

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

---------

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

Co-authored-by: Florian Apolloner <florian@apolloner.eu>
2024-03-14 23:39:10 +01:00
patchback[bot]
c47081245c [PR #8087/22620752 backport][stable-8] Removed the redundant unicode prefixes (#8096)
Removed the redundant unicode prefixes (#8087)

* removed redundant unicode prefixes

* added changelog fragment

* Update changelogs/fragments/8087-removed-redundant-unicode-prefixes.yml

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

---------

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

Co-authored-by: ansible-dev-revbits <91919024+ansible-dev-revbits@users.noreply.github.com>
2024-03-14 22:32:44 +01:00
patchback[bot]
ead23a1f38 [PR #8081/17e275bc backport][stable-8] pacemaker_cluster: implement check mode (#8095)
pacemaker_cluster: implement check mode (#8081)

* Implement check mode for pacemaker_cluster.

* Fix restart code.

Co-authored-by: Mario Lenz <m@riolenz.de>

---------

Co-authored-by: Mario Lenz <m@riolenz.de>
(cherry picked from commit 17e275bc0b)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-03-14 22:32:35 +01:00
patchback[bot]
149759d0b0 [PR #8084/6fab4671 backport][stable-8] CI: add macOS 14.3 for devel, move 13.2 to stable-2.16 (#8086)
CI: add macOS 14.3 for devel, move 13.2 to stable-2.16 (#8084)

Add macOS 14.3 for devel, move 13.2 to stable-2.16.

(cherry picked from commit 6fab46710a)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-03-12 13:28:22 +01:00
patchback[bot]
ce4716bb6c [PR #8077/79d87552 backport][stable-8] remove code no longer used (#8079)
remove code no longer used (#8077)

(cherry picked from commit 79d87552ef)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2024-03-10 12:19:00 +01:00
patchback[bot]
c09971a671 [PR #8048/fa30b022 backport][stable-8] fix(homebrew): give correct error message when become true used (#8068)
fix(homebrew): give correct error message when become true used (#8048)

* fix(homebrew): give correct error message when become true used

This commit fixes #8047 by raising the exception coming from calling
homebrew with the `become: true` parameter set.

* chore(changelog): add changelog fragment

(cherry picked from commit fa30b02294)

Co-authored-by: Michael Wall <thewalla07@gmail.com>
2024-03-09 12:42:34 +00:00
patchback[bot]
3e235f78d1 [PR #7999/0ded1109 backport][stable-8] feat(lookup/merge_variables): Add all hosts mode to collect configuration across multiple hosts (#8069)
feat(lookup/merge_variables): Add all hosts mode to collect configuration across multiple hosts (#7999)

* Add Feature to collect variables accross different hosts

* fix merging lists

* adjust unit tests

* lint fixes

* adjusting integration tests

* remove white spaces

* Update plugins/lookup/merge_variables.py

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

* Update plugins/lookup/merge_variables.py

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

* Update plugins/lookup/merge_variables.py

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

* apply suggested changes to correctly handling the initial_value parameter, incl. additional test

* whitespace

---------

Co-authored-by: Alexander Petrenz <alexander.petrenz@posteo.de>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 0ded1109fe)

Co-authored-by: Alexander Petrenz <petrenz.a@gmail.com>
2024-03-09 12:42:22 +00:00
patchback[bot]
edcb4c67ce [PR #8057/c13bede0 backport][stable-8] pam_limits: do not create file in check mode when it does not exist (#8071)
pam_limits: do not create file in check mode when it does not exist (#8057)

Do not create file in check mode when it does not exist.

(cherry picked from commit c13bede0c5)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-03-09 12:42:12 +00:00
patchback[bot]
101e2e89ba [PR #8058/98df3440 backport][stable-8] Bump fsfe/reuse-action from 2 to 3 (#8061)
Bump fsfe/reuse-action from 2 to 3 (#8058)

Bumps [fsfe/reuse-action](https://github.com/fsfe/reuse-action) from 2 to 3.
- [Release notes](https://github.com/fsfe/reuse-action/releases)
- [Commits](https://github.com/fsfe/reuse-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: fsfe/reuse-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
(cherry picked from commit 98df344017)

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-04 19:53:42 +01:00
patchback[bot]
434ff651a3 [PR #8054/a50329d0 backport][stable-8] ejabberd_user: Fix class documentation (#8056)
ejabberd_user: Fix class documentation (#8054)

(cherry picked from commit a50329d0d5)

Co-authored-by: Melvin Keskin <melvo@olomono.de>
2024-03-03 09:02:57 +01:00
patchback[bot]
d3ef55ca2c [PR #7980/74c15c12 backport][stable-8] Updates lxd_container to support new LXD API (#8046)
Updates `lxd_container` to support new LXD API (#7980)

* feat:  adds support for /1.0/instances endpoint

* Update changelogs/fragments/lxd-instances-api-endpoint-added.yml

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

---------

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

Co-authored-by: Anthony Anderson <fnanderson93@gmail.com>
2024-02-28 22:27:21 +01:00
patchback[bot]
76d8e2d577 [PR #7953/248e2ff3 backport][stable-8] [FIX] proxmox_kvm: fetch vm status from node-specific API endpoint to ensure fresh state (#8043)
[FIX] proxmox_kvm: fetch vm status from node-specific API endpoint to ensure fresh state (#7953)

* proxmox_kvm: fetch vm status from node-specific API endpoint to ensure fresh state, fixes #7817

* changelog fragments

* Fix changelog fragment.

---------

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

Co-authored-by: nxet <nxet821@protonmail.com>
2024-02-28 22:23:32 +01:00
patchback[bot]
f379dac394 [PR #8037/05bf5ee1 backport][stable-8] Fix instruction for distro Ubuntu and Debian for htpasswd depends (#8042)
Fix instruction for distro Ubuntu and Debian for htpasswd depends (#8037)

* Fix instruction fo debian 12 for htpasswd depends

* Add range for python-passlib distro

(cherry picked from commit 05bf5ee1df)

Co-authored-by: Xavier Mitault <xavier.mitault@epitech.eu>
2024-02-28 21:35:54 +01:00
patchback[bot]
39a12074a4 [PR #8035/adb367a6 backport][stable-8] Fix missing apostrophes at proxmox.py examples (#8040)
Fix missing apostrophes at proxmox.py examples (#8035)

(cherry picked from commit adb367a6af)

Co-authored-by: Sebastián Bevacqua <sebabeva@gmail.com>
2024-02-28 12:32:30 +01:00
Felix Fontein
d83fba6b86 Next expected release is 8.5.0. 2024-02-26 20:26:26 +01:00
Felix Fontein
1955fc6a8a Release 8.4.0. 2024-02-26 20:08:30 +01:00
Felix Fontein
1d97cc4b7d Fix filename.
(cherry picked from commit 1b0d55fe31)
2024-02-26 20:07:31 +01:00
patchback[bot]
828968b0dd [PR #7790/787fa462 backport][stable-8] fix(modules/gitlab_runner): Use correct argument to list all runners (#8032)
fix(modules/gitlab_runner): Use correct argument to list all runners (#7790)

* fix(modules/gitlab_runner): Use correct argument to list all runners

python-gitlab 4.0.0 removed support for the `as_list=False` parameter.
This functionality is now available as `iterator=True`.

Without this change, the module actually only retrieves the first
20 results, which can lead to non-idempotent behavior, such as
registering a runner again.

* Add changelog entry (#7790)

* gitlab_runner: Check python-gitlab version when listing runners

* gitlab: Add list_all_kwargs variable to module_utils

* refactor(gitlab modules): use list_all_kwargs where it helps (#7790)

I did not change every instance of all=True or all=False, only those
which could obviously benefit from simplifying:

  * Code using `all=True` but then searching for any items that match a
    condition (no need to collect the full list).
  * Code that basically reimplements `all=True` with manual pagination.
    (These could be changed to `all=True`, but `list_all_kwargs` also
    sets per_page to 100, to gather data faster.)

* gitlab_instance_variable: Use list_all_kwargs

* Add new changelog entry for gitlab module changes (#7790)

(cherry picked from commit 787fa46217)

Co-authored-by: Mike Wadsten <mikewadsten@gmail.com>
2024-02-25 21:26:37 +01:00
patchback[bot]
f8666061bc [PR #7964/f6d0b35b backport][stable-8] GitLab group and project access token modules (#8031)
GitLab group and project access token modules (#7964)

* Adding gitlab group and project acess token modules

* Documentation corrections and recreate option change

* Documentation corrections

* Correcting documentation for return objects

(cherry picked from commit f6d0b35bb7)

Co-authored-by: Zoran Krleza <zoran.krleza@true-north.hr>
2024-02-25 21:26:30 +01:00
patchback[bot]
9a7a0ca526 [PR #7994/6cafd3be backport][stable-8] feat(lookup/bitwarden): add support for "session" arg (#8030)
feat(lookup/bitwarden): add support for "session" arg (#7994)

Allows pass session key instead of reading from env.

Signed-off-by: Emilien Escalle <emilien.escalle@escemi.com>
(cherry picked from commit 6cafd3bed7)

Co-authored-by: Emilien Escalle <neilime@users.noreply.github.com>
2024-02-25 21:26:23 +01:00
patchback[bot]
755ee2b4d0 [PR #7996/638a7fc1 backport][stable-8] Add templating support to Icinga2 Inventory (#8026)
Add templating support to Icinga2 Inventory (#7996)

* Add templating support to Icinga2 Inventory

* Added CHANGELOG fragment

* Linting after CI failure

* Update changelogs/fragments/7996-Add templating support to Icinga2 Inventory.yml

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

* Error in variables'name

---------

Co-authored-by: Gianluca Salvo <gianluca.salvo@gruppomol.it>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 638a7fc199)

Co-authored-by: Gianluca Salvo <Gianlu@users.noreply.github.com>
2024-02-25 07:47:37 +01:00
patchback[bot]
d9e72cf75e [PR #8005/e0dbe9c9 backport][stable-8] modprobe: Avoid FileNotFoundError when directories don't exist. (#8028)
modprobe: Avoid FileNotFoundError when directories don't exist. (#8005)

* Avoid FileNotFoundError when directories don't exist.

* Adds changelog fragment.

* Update changelogs/fragments/7717-prevent-modprobe-error.yml

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

---------

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

Co-authored-by: Nate Douglas <ndouglas@users.noreply.github.com>
2024-02-25 07:47:27 +01:00
patchback[bot]
153456f6aa [PR #8009/b5c3361b backport][stable-8] Correct apk docu to not include spaces in package name (#8024)
Correct apk docu to not include spaces in package name (#8009)

* Correct apk docu to not include spaces in package name

* Update apk name docu as suggested in PR

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

---------

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

Co-authored-by: Maxopoly <max@dermax.org>
2024-02-24 20:27:08 +00:00
patchback[bot]
432dc1eb0d [PR #7952/dd7c3ad1 backport][stable-8] Fix errors in hpe specific get methods (#8022)
Fix errors in hpe specific get methods (#7952)

* Fix errors in hpe specific get methods

* corrects reference to non existent `self.chassis_uri_list` to
  `self.chassis_uris`
* corrects syntactically incorrect dereferences
* removes an uneccessary variable assignment to `chassis_uri_list`
  in `get_psu_inventory` method
* adds changelog fragment for above indicating fix of issue #7951

* Update changelog.

---------

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

Co-authored-by: Dave Rawks <dave@rawks.io>
2024-02-24 20:26:52 +00:00
Felix Fontein
d74993cacf Prepare 8.4.0 release. 2024-02-23 21:15:42 +01:00
patchback[bot]
b0fe02d4a3 [PR #7970/9510988a backport][stable-8] cargo: use the correct path when checking installation status fixing idempotency issue. (#8019)
cargo: use the correct path when checking installation status fixing idempotency issue. (#7970)

* cargo: use the correct path when checking installation status

* Add changelog fragment

* Update changelogs/fragments/7970-fix-cargo-path-idempotency.yaml

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

---------

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

Co-authored-by: rbomze <14312790+rbomze@users.noreply.github.com>
2024-02-23 20:59:42 +01:00
patchback[bot]
6cd90d30d7 [PR #7976/beacd54b backport][stable-8] Added transactional(rollback/commit) support to mssql_script module (#8017)
Added transactional(rollback/commit) support to mssql_script module (#7976)

* Added transactional(rollback/commit) support to mssql_script module via optional boolean param 'transaction'

* Added changelog fragment

* Implemented PR Review comments by felixfontein

(cherry picked from commit beacd54b7b)

Co-authored-by: Udit Yadav <36297285+BlackHat786000@users.noreply.github.com>
2024-02-23 20:48:59 +01:00
patchback[bot]
437641d95f [PR #7985/102a0857 backport][stable-8] New filters to calculate the union, intersection, difference and symmetric difference of lists by preserving the items order (#8020)
New filters to calculate the union, intersection, difference and symmetric difference of lists by preserving the items order (#7985)

New filters lists_union, lists_intersect, lists_difference and lists_symmetric_difference added.

Signed-off-by: Christoph Fiehe <c.fiehe@eurodata.de>
Co-authored-by: Christoph Fiehe <c.fiehe@eurodata.de>
(cherry picked from commit 102a0857db)

Co-authored-by: cfiehe <cfiehe@users.noreply.github.com>
2024-02-23 20:48:50 +01:00
patchback[bot]
35fb3dd034 [PR #7971/dd25ddfb backport][stable-8] Pkgin fixes (#8016)
Pkgin fixes (#7971)

* Solve exception and spurious "changed" in pkgin

* Create changelog

* PEP 8

* Update changelogs/fragments/pkgin.yml

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

---------

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

Co-authored-by: Jesús Cea <jcea@jcea.es>
2024-02-23 20:48:29 +01:00
patchback[bot]
a7a2631333 [PR #7983/49bd9cbd backport][stable-8] Add noexec support to sudoers (#8012)
Add noexec support to sudoers (#7983)

* Add noexec support to sudoers

* Add changelog fragment #7983

* Fix yml formatting in fragment 7983

* Apply suggestions from code review

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

---------

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

Co-authored-by: adaniaud <adaniaud@users.noreply.github.com>
2024-02-23 07:08:04 +00:00
patchback[bot]
c089260c88 [PR #8004/2a8da769 backport][stable-8] Redfish: Enhanced GetUpdateStatus to allow for empty responses to accomodate possible usage of 204 No Content (#8011)
Redfish: Enhanced GetUpdateStatus to allow for empty responses to accomodate possible usage of 204 No Content (#8004)

* Added handling for 204 No Content in some circumstances

Signed-off-by: Mike Raineri <michael.raineri@dell.com>

* Correcting gzip usage; open_url does the decompression automatically

Signed-off-by: Mike Raineri <michael.raineri@dell.com>

* Changelog fragment

Signed-off-by: Mike Raineri <michael.raineri@dell.com>

* Removed imports no longer used

Signed-off-by: Mike Raineri <michael.raineri@dell.com>

* Updated data unpacking to dynamically check ansible-core version and response headers to see if gzip decompression is needed

Signed-off-by: Mike Raineri <michael.raineri@dell.com>

---------

Signed-off-by: Mike Raineri <michael.raineri@dell.com>
(cherry picked from commit 2a8da76907)

Co-authored-by: Mike Raineri <michael.raineri@dell.com>
2024-02-23 07:07:57 +00:00
patchback[bot]
bc7f952a29 [PR #7992/ffa3d158 backport][stable-8] Implement integration tests for apk (#8008)
Implement integration tests for apk (#7992)

* Implement integration tests for apk

* Add group for apk integration test

* Adjust integration tests of apk as suggested in PR

(cherry picked from commit ffa3d15881)

Co-authored-by: Maxopoly <max@dermax.org>
2024-02-22 21:03:56 +01:00
patchback[bot]
874e0bdf9e [PR #7991/551b0b9e backport][stable-8] ipa_user: add how to remove userauthtype from an user (#7995)
ipa_user: add how to remove userauthtype from an user (#7991)

(cherry picked from commit 551b0b9eea)

Co-authored-by: Parsa Yousefi <p.yousefi97@gmail.com>
2024-02-20 21:37:19 +01:00
patchback[bot]
6987a07887 [PR #7956/1dd697bd backport][stable-8] Adding releases events option to gitlab_hook module (#7982)
Adding releases events option to gitlab_hook module (#7956)

* Adding releases events option to gitlab_hook module

* Fixing typo in documentation for gitlab_hook module

* No default value for releases_events

* Adding changelog fragment

(cherry picked from commit 1dd697bdc2)

Co-authored-by: Zoran Krleza <zoran.krleza@true-north.hr>
2024-02-19 20:08:57 +01:00
patchback[bot]
359788e0cd [PR #7847/8ea58618 backport][stable-8] gitlab_issue: use search instead of title (#7977)
gitlab_issue: use search instead of title (#7847)

* gitlab_issue: use search instead of title

* Create changelog file

* Update changelogs/fragments/7847-gitlab-issue-title.yml

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

* using query_parameters

Co-authored-by: Nejc Habjan <hab.nejc@gmail.com>

* sanity checks

---------

Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Nejc Habjan <hab.nejc@gmail.com>
(cherry picked from commit 8ea58618db)

Co-authored-by: Gabriele Pongelli <gpongelli@users.noreply.github.com>
2024-02-17 22:48:48 +01:00
patchback[bot]
8eec4767bd [PR #7881/001292c7 backport][stable-8] Fixes #1226 - keycloak_client detects changes on check_mode but not in run mode (#7979)
Fixes #1226 - keycloak_client detects changes on check_mode but not in run mode (#7881)

* Fix warning integrated

* Update Keycloak version intergrated test

* Exclude metadata from diff test

* Sanity

* Add fragments

* typo

* Add test

* Update changelogs/fragments/7881-fix-keycloak-client-ckeckmode.yml

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

* Remove docker compose

* Update changelogs/fragments/7881-fix-keycloak-client-ckeckmode.yml

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

---------

Co-authored-by: Andre Desrosiers <andre.desrosiers@ssss.gouv.qc.ca>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 001292c780)

Co-authored-by: desand01 <desrosiers.a@hotmail.com>
2024-02-17 22:48:40 +01:00
patchback[bot]
01d3a106ac [PR #7919/6088e2dc backport][stable-8] fixes #7918 - onepassword lookup fails if field name contains uppercase letters and section is specified (#7975)
fixes #7918 - onepassword lookup fails if field name contains uppercase letters and section is specified (#7919)

* fix #7918

* Update plugins/lookup/onepassword.py

Co-authored-by: Sam Doran <github@samdoran.com>

* onepassword lookup: transform field ids to lowercase

* #7918: added unit tests

* #7919: add changelog fragment

* Update changelogs/fragments/7919-onepassword-fieldname-casing.yaml

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

---------

Co-authored-by: Sam Doran <github@samdoran.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 6088e2dc0f)

Co-authored-by: Benjamin Mitzkus <b.mitzkus@gmx.de>
2024-02-17 12:29:48 +01:00
patchback[bot]
820c69ba54 [PR #7963/0a35eb2d backport][stable-8] terraform: fix diff when state is absent (#7973)
terraform: fix diff when state is absent (#7963)

(cherry picked from commit 0a35eb2dda)

Co-authored-by: Parsa Yousefi <p.yousefi97@gmail.com>
2024-02-17 12:29:37 +01:00
Felix Fontein
15a46508b4 [stable-8] Add default_without_diff callback (#7949) (#7968)
Add default_without_diff callback (#7949)

* Add default_without_diff callback.

* Add examples and BOTMETA entry.

(cherry picked from commit 980fa36fac)
2024-02-15 07:16:58 +01:00
patchback[bot]
0bf514c955 [PR #7965/bc383b8f backport][stable-8] Add krauthosting as proxmox maintainer (#7966)
Add krauthosting as proxmox maintainer (#7965)

Add krauthosting as proxmox maintainer.

(cherry picked from commit bc383b8f7b)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-02-13 21:46:47 +01:00
Felix Fontein
426f9d8734 [stable-8] Add redfish_config command to set service identification (#7917) (#7957)
Add redfish_config command to set service identification (#7917)

* Update redfish_utils.py

* Update redfish_utils.py

* Update redfish_config.py

* Update redfish_config.py

* Update redfish_config.py

* Update redfish_utils.py

* Create 7916-add-redfish-set-service-identification.yml

* fix lint

* Update redfish_utils.py

* add service_id docs

* Update redfish_info.py

* Update plugins/modules/redfish_info.py

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

* fix conflict

* fix conflict

* fix conflict

* fix conflict

* Update redfish_utils.py

* Update redfish_info.py

* Update redfish_info.py

* Update plugins/modules/redfish_config.py

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

---------

Co-authored-by: dh <dh@alpha.stegosaur.org>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit eded6ebf64)

Co-authored-by: D Honig <namssa@gmail.com>
2024-02-11 13:35:33 +01:00
Felix Fontein
80f4dcb09d [stable-8] Add MarkDown changelog and use it by default (#7940)
Add MarkDown changelog and use it by default.
2024-02-09 13:08:35 +01:00
Felix Fontein
877d6d76f5 [stable-8] proxmox_kvm - new param to support unsafe updates (#7843) (#7954)
proxmox_kvm - new param to support unsafe updates (#7843)

* proxmox_kvm - new param to support unsafe updates

* changelog fragments

* Apply suggestions from code review

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

* improved docs

* updated `version_added`

---------

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

Co-authored-by: nxet <nxet821@protonmail.com>
2024-02-07 14:50:18 +01:00
Felix Fontein
f4d52cf235 [stable-8] filesize: use 2 TB instead of 4 TB in sparse file tests (#7935) (#7938)
filesize: use 2 TB instead of 4 TB in sparse file tests (#7935)

Use 2 TB instead of 4 TB.

4 TB does not work on the Alpine VMs for some reason
(File too large / cannot seek: Invalid argument).

(cherry picked from commit 549a73bd78)
2024-02-03 15:22:17 +01:00
patchback[bot]
3f66db14a3 [PR #7927/fa1f2af4 backport][stable-8] Update iso_customize.py notes section (#7930)
Update iso_customize.py notes section (#7927)

Documentation now shows support for python 3.4+

(cherry picked from commit fa1f2af460)

Co-authored-by: Chuck Milam <chuck@milams.net>
2024-02-01 17:51:55 +00:00
Felix Fontein
17abb550c3 [stable-8] fix typo: it's own -> its own (#7923) (#7928)
fix typo: it's own -> its own (#7923)

(cherry picked from commit ab6a61237a)

Co-authored-by: Thiago Perrotta <tbperrotta@gmail.com>
2024-02-01 18:33:24 +01:00
Felix Fontein
bfb18b3704 Next expected release is 8.4.0. 2024-01-29 20:49:37 +01:00
Felix Fontein
983b4d70e0 Release 8.3.0. 2024-01-29 20:16:51 +01:00
Felix Fontein
821ae9bc41 Prepare 8.3.0 release. 2024-01-29 20:16:02 +01:00
Felix Fontein
d5efd56dae [stable-8] terraform: support diff for resource_changes (#7896) (#7914)
terraform: support diff for resource_changes (#7896)

(cherry picked from commit 0dc891bf37)

Co-authored-by: Parsa Yousefi <p.yousefi97@gmail.com>
2024-01-29 19:30:16 +01:00
patchback[bot]
88ef840750 [PR #7697/a5cd4ebe backport][stable-8] Simplify regex for identifying order number in DN (#7646) (#7915)
Simplify regex for identifying order number in DN (#7646) (#7697)

Assume that if a string of digits occurs between curly braces anywhere
in the first component of the DN, that this is an order number. The
sequence does not necessarily have to occur after an equals sign.

(cherry picked from commit a5cd4ebea2)

Co-authored-by: Aaron Sowry <aeneby@users.noreply.github.com>
2024-01-29 19:30:08 +01:00
patchback[bot]
08d04a7923 [PR #7695/997e6345 backport][stable-8] Fixes #7389 - NMCLI issue with creating a wifi bridge-slave (#7912)
Fixes #7389 - NMCLI issue with creating a wifi bridge-slave (#7695)

* working mod

* added changelog fragment

* added link on fragment

* Update changelogs/fragments/7389-nmcli-issue-with-creating-a-wifi-bridge-slave.yml

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

* last fix

---------

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

Co-authored-by: Gianmarco Mameli <57061995+gianmarco-mameli@users.noreply.github.com>
2024-01-28 13:39:43 +01:00
patchback[bot]
9d0b14b239 [PR #7907/2580da97 backport][stable-8] Zuul third-party-check: disable ansible-doc part of galaxy-importer (#7910)
Zuul third-party-check: disable ansible-doc part of galaxy-importer (#7907)

Zuul third-party-check: disable ansible-doc part of galaxy-importer.

(cherry picked from commit 2580da9796)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-01-27 16:05:38 +01:00
patchback[bot]
9e83a4cb34 [PR #7901/84147081 backport][stable-8] Consul acl deprecation (#7906)
Consul acl deprecation (#7901)

Start deprecation of consul_acl.

(cherry picked from commit 84147081d4)

Co-authored-by: Florian Apolloner <florian@apolloner.eu>
2024-01-27 13:54:05 +01:00
patchback[bot]
dc5f012e52 [PR #7897/afd19888 backport][stable-8] Consul action group (#7905)
Consul action group (#7897)

Added action group for new style consul modules.

(cherry picked from commit afd1988810)

Co-authored-by: Florian Apolloner <florian@apolloner.eu>
2024-01-27 12:21:34 +01:00
Felix Fontein
210adc196e Fix changelog fragment filenames.
(cherry picked from commit f8465c692b)
2024-01-27 11:07:35 +01:00
patchback[bot]
f30fcec398 [PR #7870/be3bfd6f backport][stable-8] Detection of already installed homebrew cask (#7904)
Detection of already installed homebrew cask (#7870)

* fix: detect already installed cask

Use json output v2 to check if formulae and casks are installed

chore: add changelog fragment

* test: add homebrew cask specific tests

* refactor: change cask used in tests

* chore: apply suggestions to changelog fragment

(cherry picked from commit be3bfd6fa5)

Co-authored-by: João Victor Silva <160127815@aluno.unb.br>
2024-01-27 10:37:13 +01:00
patchback[bot]
0a904d60cd [PR #7878/29f98654 backport][stable-8] Add new consul modules and reuse code between them. (#7902)
Add new consul modules and reuse code between them. (#7878)

Refactored consul modules and added new roles.

(cherry picked from commit 29f9865497)

Co-authored-by: Florian Apolloner <florian@apolloner.eu>
2024-01-27 10:33:33 +01:00
patchback[bot]
1ee2bba140 [PR #7824/4298f2dd backport][stable-8] New module: gitlab_milestone (#7899)
New module: gitlab_milestone (#7824)

* new module gitlab_milestone

* change BOTMETA

* remove blank line

* version_added field

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

* Update plugins/modules/gitlab_milestone.py

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

* Update description with reference

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

* Dates as string type

* Removed python 2.7 requirement

* Fixes from recent PR comments.

* milestones_obj returned on success

---------

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

Co-authored-by: Gabriele Pongelli <gpongelli@users.noreply.github.com>
2024-01-27 10:23:38 +01:00
patchback[bot]
0aa9cd0e30 [PR #7872/2d3f99ec backport][stable-8] fix proxmox update when setting does not already exist (#7898)
fix proxmox update when setting does not already exist (#7872)

* fix proxmox update when setting does not already exist

* add changelog fragment

---------

Co-authored-by: Eric Trombly <etrombly@iomaxis.com>
(cherry picked from commit 2d3f99ec3a)

Co-authored-by: Eric Trombly <etrombly@yahoo.com>
2024-01-27 10:23:30 +01:00
Felix Fontein
7009a768a4 [stable-8] New module: gitlab_label (#7657) (#7900)
New module: gitlab_label (#7657)

* gitlab project label first commit

* fixes from CI run

* fixing some sanity test

* sanity checks, removing typing

* remove default for required field

* fix indentation

* improving test set

* fixes to pass test set

* reuse compliancy

* fix sanity checks

* fix: method returns group, not project

* refactor: start adding group, test still pass

* updated module and tests to handle group labels

* update name to remove 'project'

* removing default

* typo

* generic name for returned dict

* returns also label object from library invocation

* remove unused var, updated doc

* fix output object name

* version_added

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

* Remove python 2.7

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

* Missing dot

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

* Remove version_added

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

* Remove useless doc

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

* Color is a string

* Fixes from recent PR comments.

---------

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

Co-authored-by: Gabriele Pongelli <gpongelli@users.noreply.github.com>
2024-01-27 10:23:19 +01:00
patchback[bot]
2f5552da04 [PR #7873/13e3161f backport][stable-8] Refer to LXD containers/VMs as instances (#7891)
Refer to LXD containers/VMs as instances (#7873)

* plugins/connection/lxd: rename container to instance

Signed-off-by: Simon Deziel <simon.deziel@canonical.com>

* plugins/inventory/lxd: rename container to instance

It seems that a previous search and replace was done but it
missed those `containe_name` due to missing `r` in `container`.

Signed-off-by: Simon Deziel <simon.deziel@canonical.com>

---------

Signed-off-by: Simon Deziel <simon.deziel@canonical.com>
(cherry picked from commit 13e3161f2a)

Co-authored-by: Simon Deziel <simon.deziel@canonical.com>
2024-01-24 19:49:01 +01:00
Felix Fontein
145686cfe0 [stable-8] Add redfish_info command to get service identification (#7883) (#7887)
Add redfish_info command to get service identification (#7883)

* Update redfish_info.py

* Create 7882-add-redfish-get-service-identification.yml

* add get_service_identification

* Update changelogs/fragments/7882-add-redfish-get-service-identification.yml

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

* Update plugins/modules/redfish_info.py

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

---------

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

Co-authored-by: D Honig <namssa@gmail.com>
2024-01-23 07:59:06 +01:00
patchback[bot]
08239919de [PR #7875/44028060 backport][stable-8] Fix: incus connection plugin treats inventory_hostname incorrectly in remote config (#7886)
Fix: incus connection plugin treats inventory_hostname incorrectly in remote config (#7875)

* Fixes inventory_hostname treatment as a litteral instead of inventory_hostname variable. Similar problem fixed in LXD: https://github.com/ansible-collections/community.general/pull/4912

* changelog for upsream

* Update changelogs/fragments/7874-incus_connection_treats_inventory_hostname_as_literal_in_remotes.yml

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

---------

Co-authored-by: travis <travis@cypressMini.local>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 44028060c3)

Co-authored-by: Travis McCollum <travis.mccollum+github@gmail.com>
2024-01-23 07:29:23 +01:00
patchback[bot]
1ab1f8f62b [PR #7826/44679e71 backport][stable-8] Refactor of consul modules (#7877)
Refactor of consul modules (#7826)

* Extract common functionality.

* Refactor duplicated code into module_utils.

* Fixed ansible-test issues.

* Address review comments.

* Revert changes to consul_acl.

It uses deprecated APIs disabled since Consul 1.11 (which is EOL), don't
bother updating the module anymore.

* Remove unused code.

* Merge token into default doc fragment.

* JSON all the way down.

* extract validation tests into custom file and prep for requests removal.

* Removed dependency on requests.

* Initial test for consul_kv.

* fixup license headers.

* Revert changes to consul.py since it utilizes python-consul.

* Disable the lookup test for now.

* Fix python 2.7 support.

* Address review comments.

* Address review comments.

* Addec changelog fragment.

* Mark ConsulModule as private.

(cherry picked from commit 44679e71a2)

Co-authored-by: Florian Apolloner <florian@apolloner.eu>
2024-01-21 17:51:45 +00:00
patchback[bot]
13c25154b5 [PR #7855/cd77d67e backport][stable-8] Add missing id parameter into pacman_key documentation examples. (#7868)
Add missing `id` parameter into pacman_key documentation examples. (#7855)

Key ID is a mandatory parameter, and the examples which miss it are
incorrect.

(cherry picked from commit cd77d67efb)

Co-authored-by: Danila Kiver <forumdan@mail.ru>
2024-01-18 08:12:58 +01:00
patchback[bot]
d22199f82e [PR #7821/92f8bf7b backport][stable-8] mssql_script: make module Python 2 compatible (#7866)
mssql_script: make module Python 2 compatible (#7821)

Make module Python 2 compatible.

(cherry picked from commit 92f8bf7b6f)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-01-18 07:33:49 +01:00
patchback[bot]
82a07de870 [PR #7857/069b485b backport][stable-8] Use shared workflow for Galaxy import test (#7864)
Use shared workflow for Galaxy import test (#7857)

Simplifiy workflows.

(cherry picked from commit 069b485b7e)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-01-18 07:33:35 +01:00
patchback[bot]
895c1fe2a0 [PR #7858/002208f4 backport][stable-8] Make compatible with newer reuse versions (#7860)
Make compatible with newer reuse versions (#7858)

Make compatible with newer reuse versions.

(cherry picked from commit 002208f425)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-01-18 07:10:56 +01:00
patchback[bot]
3e972990cb [PR #7795/31de16ce backport][stable-8] ipa_otptoken: fix wrong return value string to bool (#7852)
ipa_otptoken: fix wrong return value string to bool (#7795)

ipa_data is return ipatokendisable in boolean format and the module expects it as a string
this behavior causes a lack of idempotency and the get_diff module will fail in the second run.

(cherry picked from commit 31de16cee3)

Co-authored-by: Parsa Yousefi <p.yousefi97@gmail.com>
2024-01-16 22:31:47 +01:00
Felix Fontein
0ac6e44566 [stable-8] Use import galaxy workflow from ansible-collections/community.docker#754 (#7842)
Use import galaxy workflow from ansible-collections/community.docker#754 (#7839)

Use import galaxy workflow from https://github.com/ansible-collections/community.docker/pull/754.

(cherry picked from commit 32ec751996)
2024-01-13 19:25:40 +01:00
Felix Fontein
1308198eae [stable-8] CI: remove ignore files for ansible-core 2.11 and 2.12 (#7838)
CI: remove ignore files for ansible-core 2.11 and 2.12 (#7837)

Remove ignore files for ansible-core 2.11 and 2.12.

(cherry picked from commit 76fde43fca)
2024-01-13 16:26:24 +01:00
Felix Fontein
d887985b46 Rewrite with PyYAML (except comments). 2024-01-13 11:20:17 +01:00
patchback[bot]
7d6e7fa5fa [PR #7831/8891f559 backport][stable-8] Disable timezone tests on Arch Linux (#7835)
Disable timezone tests on Arch Linux (#7831)

Disable timezone tests on Arch Linux.

(cherry picked from commit 8891f559ef)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-01-13 11:00:23 +01:00
patchback[bot]
b61b988b2e [PR #7827/87866477 backport][stable-8] CI: fix xml tests on RHEL 8 (#7830)
CI: fix xml tests on RHEL 8 (#7827)

* Try to fix xml installation on RHEL.

* Install python-lxml on RHEL 8. Should speed up tests considerably.

(cherry picked from commit 878664778e)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-01-13 10:11:39 +01:00
Felix Fontein
549c9e69ae [stable-8] CI: for some reason async-timeout doesn't seem to get installed on Python 3.11 (#7812)
CI: for some reason async-timeout doesn't seem to get installed on Python 3.11 (#7811)

For some reason async-timeout doesn't seem to get installed on Python 3.11.

(cherry picked from commit 9946f758af)
2024-01-05 08:53:06 +01:00
patchback[bot]
fe35cff7a4 [PR #7807/ee8b1570 backport][stable-8] Fix failing sanity and integration tests (#7809)
Fix failing sanity and integration tests (#7807)

* Remove some Shippable specific code that trips latest shellcheck.

* Rename templated shell script to .sh.j2 to avoid shellcheck disliking the templating.

* Copy on the remote, not from controller to remote.

(cherry picked from commit ee8b15708f)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-01-04 23:24:38 +01:00
Felix Fontein
cef57b044b Next expected release will be 8.3.0 2024-01-01 18:22:57 +01:00
Felix Fontein
980a9817f3 Release 8.2.0. 2024-01-01 17:52:46 +01:00
Felix Fontein
778662921f Prepare 8.2.0 release. 2024-01-01 14:38:22 +01:00
patchback[bot]
a045d088d5 [PR #7792/0bfebde5 backport][stable-8] proxmox_kvm - state:template will check if template exists first (#7791) (#7806)
proxmox_kvm - state:template will check if template exists first (#7791) (#7792)

* proxmox_kvm - state:template will check if template exists first (#7791)

* added changelog entry

* Update changelog fragment.

---------

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

Co-authored-by: aaronjohnleonard <aaronjohnleonard@gmail.com>
2024-01-01 14:36:47 +01:00
patchback[bot]
395fc1e77a [PR #7765/acddb190 backport][stable-8] mail module/callback: allow to configure the Message-ID header's domain name (#7805)
mail module/callback: allow to configure the Message-ID header's domain name (#7765)

Allow to configure the Message-ID header's domain name.

(cherry picked from commit acddb190ba)

Co-authored-by: Felix Fontein <felix@fontein.de>
2024-01-01 14:30:35 +01:00
patchback[bot]
42c65f32eb [PR #7761/33180344 backport][stable-8] Add github_app_access_token lookup plugin (#7802)
Add github_app_access_token lookup plugin (#7761)

* Add github_app_access_token lookup plugin

* Fix a typo in short_description

* Remove unused MockOpenUrl

* Fix MockJWT to be used on jwt_instance instead

* Fix a bunch of pep8 and pylint issue

* Remove JWT from requirements, also default jwt_instance and jwk_from_pem so they can be mocked

* Update version added

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

* Update git reference in doc

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

* Update plugins/lookup/github_app_access_token.py

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

* Expose token expiry as a configurable option

* Update BOTMETA.yml

* Update documentation

* Update example with var, so it is more readable

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

* Apply suggestions from code review

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

---------

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

Co-authored-by: weisheng-p <weisheng-p@users.noreply.github.com>
2023-12-31 15:44:00 +01:00
patchback[bot]
4776e7bed3 [PR #7723/6afe35d2 backport][stable-8] ipa: ipa_pwpolicy update pwpolicy module (#7801)
ipa: ipa_pwpolicy update pwpolicy module (#7723)

* ipa: ipa_pwpolicy support maxrepeat, maxsequence, dictcheck, usercheck, gracelimit

* ipa: ipa_pwdpolicy replace if statements with for loop

* ipa: ipa_pwdpolicy add changelog

(cherry picked from commit 6afe35d263)

Co-authored-by: Parsa Yousefi <p.yousefi97@gmail.com>
2023-12-31 15:43:52 +01:00
Felix Fontein
d423b27288 [stable-8] Proxmox add storage content listing (#7725) (#7803)
Proxmox add storage content listing (#7725)

Add module to list content on proxmox storage

We first add a method to list storage content for proxmox, then use that
new methode to add an Ansible module to list content on storage attached
to a proxmox node. User can also use content filtering to define what
they want to list (backup, iso, images,...).

This commit also include the integration and unit test for that new
module.

Co-authored-by: Julian Vanden Broeck <julian.vandenbroeck@dalibo.com>
(cherry picked from commit 4f92f39720)

Co-authored-by: Julian <374571+l00ptr@users.noreply.github.com>
2023-12-31 15:43:43 +01:00
patchback[bot]
89c56631c8 [PR #7789/08ece2e0 backport][stable-8] Allow custom providerId in keycloak_user_federation (#7804)
Allow custom providerId in keycloak_user_federation (#7789)

* Update keycloak_user_federation.py

* stub out changelog

* update PR reference

* remove 'choices' from documentation

* Apply suggestions from code review

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

---------

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

Co-authored-by: Clif Reeder <clifreeder@gmail.com>
2023-12-31 15:43:29 +01:00
patchback[bot]
2e34cba62c [PR #7797/8d307cb1 backport][stable-8] Remove FreeBSD 12.4 from CI (#7800)
Remove FreeBSD 12.4 from CI (#7797)

Remove FreeBSD 12.4 from CI.

(cherry picked from commit 8d307cb190)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-12-31 15:19:30 +01:00
patchback[bot]
ce5417bb73 [PR #7745/acc31730 backport][stable-8] Add dnf_config_manager module (#7794)
Add dnf_config_manager module (#7745)

* Add dnf_config_manager module

* add BOTMETA

* document return values

* improve error messages

* fix doc indent

* make regexes raw strings

* formatting improve

* fix indent

* update version_added

* Tweaks from feedback and unit testing

* fix copyright and python2.7

* remove shebang

* documentation updates

* Change return values to not have varying keys

* sort returned lists

(cherry picked from commit acc3173030)

Co-authored-by: Andrew Hyatt <4400272+ahyattdev@users.noreply.github.com>
2023-12-29 09:57:26 +01:00
patchback[bot]
bf089294b4 [PR #7689/1a3c93f8 backport][stable-8] Add proxmox_node_info module (#7793)
Add proxmox_node_info module (#7689)

* Add proxmox_node_info module - restarted PR due to erroneous update/push of my local fork.

* Used wrong user ID.

* Changes requested by felixfontein:
- Capitalization and punctuation in documentation section
- trailing comma on line 125
- Re-order BOTMETA so it is alphabetical

* Mis-copied older version of code, correcting actual call

* Add tests for proxmox_node_info module

(cherry picked from commit 1a3c93f80c)

Co-authored-by: John Berninger <john.berninger@gmail.com>
2023-12-29 09:55:53 +01:00
patchback[bot]
87a079e93c [PR #7663/f7bc6964 backport][stable-8] Add keycloak_realm_rolemapping module to map realm roles to groups (#7785)
Add keycloak_realm_rolemapping module to map realm roles to groups (#7663)

* Add keycloak_realm_rolemapping module to map realm roles to groups

* Whitespace

* Description in plain English

* Casing

* Update error reporting as per #7645

* Add agross as maintainer of keycloak_realm_rolemapping module

* cid and client_id are not used here

* Credit other authors

* mhuysamen submitted #7645
* Gaetan2907 authored keycloak_client_rolemapping.py which I took as a
  basis

* Add integration tests

* With Keycloak 23 realmRoles are only returned if assigned

* Remove debug statement

* Add test verifying that unmap works when no realm roles are assigned

* Add license to readme

* Change version number this module was added

* Document which versions of the docker images have been tested

* Downgrade version_added

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

---------

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

Co-authored-by: Alexander Groß <agross@therightstuff.de>
2023-12-28 17:28:03 +00:00
patchback[bot]
2de375eaf8 [PR #7746/98181fb8 backport][stable-8] Implemented raw_post without actions (#7786)
Implemented raw_post without actions (#7746)

* implemented raw_post without actions

* fixed identation

* added changelog fragment

* Update changelogs/fragments/7746-raw_post-without-actions.yml

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

---------

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

Co-authored-by: Andrei Sucu <70206949+AndreiSucu@users.noreply.github.com>
2023-12-28 17:27:55 +00:00
patchback[bot]
3a946bf115 [PR #7694/e99b5086 backport][stable-8] Keycloak components info (#7787)
Keycloak components info (#7694)

* Before test

* first test

* test

* Sanity ok

* Fixe readme

* Refactor

* Sanity

* Fixe doc

* version added

* refactor

* Copyright

* Sanity

* Sanity

* Fixe text

* Encode providerType

* Test for failed ic

* Update plugins/modules/keycloak_component_info.py

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

* Update plugins/modules/keycloak_component_info.py

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

* Update plugins/modules/keycloak_component_info.py

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

* Update plugins/modules/keycloak_component_info.py

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

* Update plugins/modules/keycloak_component_info.py

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

* Update plugins/modules/keycloak_component_info.py

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

* Update plugins/modules/keycloak_component_info.py

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

* Delete changelogs/fragments/7694-Keycloak-components-info.yml

---------

Co-authored-by: Andre Desrosiers <andre.desrosiers@ssss.gouv.qc.ca>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit e99b5086a8)

Co-authored-by: desand01 <desrosiers.a@hotmail.com>
2023-12-28 17:27:48 +00:00
patchback[bot]
1e3ad7f189 [PR #7767/dfb9b1b9 backport][stable-8] Update BOTMETA.yml - Remove fxfitz as maintainer of IPA (#7784)
Update BOTMETA.yml - Remove fxfitz as maintainer of IPA (#7767)

* Update BOTMETA.yml

Remove fxfitz

* Add ignore fxfitz

---------

Co-authored-by: Fran Fitzpatrick <fran.fitzpatrick@tanium.com>
(cherry picked from commit dfb9b1b9fb)

Co-authored-by: Fran Fitzpatrick <francis.x.fitzpatrick@gmail.com>
2023-12-28 17:27:39 +00:00
patchback[bot]
8c386516eb [PR #7773/56a18a02 backport][stable-8] cloudflare_dns: announce removal of SPF support (#7781)
cloudflare_dns: announce removal of SPF support (#7773)

Announce removal of SPF support.

(cherry picked from commit 56a18a029a)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-12-28 17:48:17 +01:00
patchback[bot]
058c918cad [PR #7776/e9f7f7e2 backport][stable-8] CI: python-memcached 1.60 needs Python 3.6+ (#7779)
CI: python-memcached 1.60 needs Python 3.6+ (#7776)

python-memcached 1.60 needs Python 3.6+.

(cherry picked from commit e9f7f7e2de)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-12-28 13:53:27 +01:00
patchback[bot]
a7dac117e5 [PR #7418/fd0d05d6 backport][stable-8] Bugfix: keycloak_identity_provider does not handle mapper changes properly (#7775)
Bugfix: keycloak_identity_provider does not handle mapper changes properly (#7418)

* fix keycloak_identity_provider ITs to actually pass

- wrong identityProviderAlias in mapper configuration

* kc_identity_provider: add mapper reconfiguration regression tests

* test for removing an existing mapper
* test for adding a new mapper when others already exist
* test for module idempotency when mappers not ordered by name in ascending order

* kc_identity_provider: add bugfixes for mapper reconfigurations

* removing an existing mapper
* adding a new mapper when others already exist
* module idempotency when mappers not ordered by name in ascending order

* add changelog fragment

* prevent unnecessary update_mapper calls when there is no change

* Update changelogs/fragments/7418-kc_identity_provider-mapper-reconfiguration-fixes.yml

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

* Update changelogs/fragments/7418-kc_identity_provider-mapper-reconfiguration-fixes.yml

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

* Update changelogs/fragments/7418-kc_identity_provider-mapper-reconfiguration-fixes.yml

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

* Update plugins/modules/keycloak_identity_provider.py

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

* kc_identity_provider: sort changeset mappers via name OR id to prevent potential failures in case name was not specified in playbook

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

---------

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

Co-authored-by: Jakub Danek <danekja@users.noreply.github.com>
2023-12-28 09:59:46 +01:00
patchback[bot]
9fc447dedb [PR #7744/ec12422f backport][stable-8] Adding a new filter: to_ini, which allows conversion of a dictionary to an INI formatted string (#7772)
Adding a new filter: to_ini, which allows conversion of a dictionary to an INI formatted string (#7744)

* Adding a new filter: to_ini, which allows conversion of a dictionary to an INI formatted string

* Adding to_ini maintainers into BOTMETA

* Correcting filter suffix

* Moving filter to correct path

* Adding error handling; Removing quotes from examples; Fixing RETURN documentation

* Removing the last newline char; Adding error handling for an empty dict

* Adding integration tests for to_ini

* Fixing F-String usage

* Fixing formatting

* Fixing whitespace

* Moving import statements below documentation; Adding a more generic Exception handling; Removing unused imports

* Removing not needed set_fact and replacing it with using vars:

* Replacing MutableMapping with Mapping

(cherry picked from commit ec12422fae)

Co-authored-by: Steffen Scheib <37306894+sscheib@users.noreply.github.com>
2023-12-28 09:34:13 +01:00
patchback[bot]
fc70818ee3 [PR #7737/f79940c4 backport][stable-8] ipa_dnsmodule: Add support for ns record management (#7771)
ipa_dnsmodule: Add support for ns record management (#7737)

* Add NS record type management to ipa_dnsrecord

* Add jwbernin to BOTMETA for ipa_ modules

* Add changelog fragment

* Rename changelog fragment with pull request number

* Commit changes suggested by felixfontein

(cherry picked from commit f79940c415)

Co-authored-by: John Berninger <john.berninger@gmail.com>
2023-12-28 09:33:44 +01:00
patchback[bot]
a7bbf99448 [PR #7726/6d74e0c6 backport][stable-8] Introduce an Incus connection plugin (#7770)
Introduce an Incus connection plugin (#7726)

* plugins/connection/incus: Introduce new plugin

Signed-off-by: Stéphane Graber <stgraber@stgraber.org>

* BOTMETA: Add incus connection plugin

Signed-off-by: Stéphane Graber <stgraber@stgraber.org>

* tests/integration: Add connection_incus test

Signed-off-by: Stéphane Graber <stgraber@stgraber.org>

---------

Signed-off-by: Stéphane Graber <stgraber@stgraber.org>
(cherry picked from commit 6d74e0c640)

Co-authored-by: Stéphane Graber <stgraber@stgraber.org>
2023-12-28 09:33:30 +01:00
patchback[bot]
718f88d2c7 [PR #7743/ec6dfe2f backport][stable-8] Adding a new filter: from_ini, which allows conversion of INI content to a dictionary (#7769)
Adding a new filter: from_ini, which allows conversion of INI content to a dictionary (#7743)

* Adding a new filter: from_ini, which allows conversion of INI content to a dictionary

* Adding from_ini maintainers into BOTMETA

* Adding error handling; Removing quotes from examples; Fixing RETURN documentation

* Adding integration tests

* Moving imports below documentation; Adding a more general exception handling

(cherry picked from commit ec6dfe2fcd)

Co-authored-by: Steffen Scheib <37306894+sscheib@users.noreply.github.com>
2023-12-28 09:33:18 +01:00
patchback[bot]
c596558846 [PR #7698/702dd9bb backport][stable-8] improvements to the keycloak_realm_key module (#7768)
improvements to the keycloak_realm_key module (#7698)

* add support for rsa enc key usage, more algorithms, and make certficate optional

* fix formatting

* adding changelog fragment

* made suggested code changes based on review

* fix typo and be more clear

* revert certificate to previous defined settings

(cherry picked from commit 702dd9bbda)

Co-authored-by: George Bolo <george.bolo@gmail.com>
2023-12-28 09:33:08 +01:00
patchback[bot]
21a7159472 [PR #7740/671b7ab1 backport][stable-8] mail module: add Message-ID header (#7764)
mail module: add Message-ID header (#7740)

* mail module: add Message-ID header

* Update plugins/modules/mail.py

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

---------

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

Co-authored-by: Sébastien Bocahu <sebastien+github@bocahu.name>
2023-12-27 16:00:13 +01:00
patchback[bot]
5dc20d9028 [PR #7754/4a1006ac backport][stable-8] Fixed payload format (#7763)
Fixed payload format (#7754)

* Fixed payload format

* added changelog fragment

* Update changelogs/fragments/7754-fixed-payload-format.yml

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

---------

Co-authored-by: Ed Ferguson <eferguson@nrtc.coop>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 4a1006ac34)

Co-authored-by: Ed Ferguson <5855090+eeferg@users.noreply.github.com>
2023-12-26 22:24:54 +01:00
patchback[bot]
2f47748154 [PR #7727/825bec70 backport][stable-8] Improve docs of bitwarden lookup (#7760)
Improve docs of bitwarden lookup (#7727)

* Improve docs of bitwarden lookup.

* Improve formulations.

Co-authored-by: Don Naro <dnaro@redhat.com>

* Improve formulation.

---------

Co-authored-by: Don Naro <dnaro@redhat.com>
(cherry picked from commit 825bec7053)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-12-22 21:24:06 +01:00
patchback[bot]
ddf6b13f18 [PR #7721/1fdbb50a backport][stable-8] 🔐 Load OP_SERVICE_ACCOUNT_TOKEN from ENVs (#7757)
🔐 Load `OP_SERVICE_ACCOUNT_TOKEN` from ENVs (#7721)

* 🔐 Load `OP_SERVICE_ACCOUNT_TOKEN` from ENVs

* 🚚 Move configuration to `doc_fragments`

* 📝 Add `env` to documentation

* Revert change

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

---------

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

Co-authored-by: Dov Benyomin Sohacheski <b@kloud.email>
2023-12-21 23:11:46 +01:00
patchback[bot]
293aee5648 [PR #7696/1389bba4 backport][stable-8] keycloak_user: avoid error when trying to delete a non-existing user (#7756)
keycloak_user: avoid error when trying to delete a non-existing user (#7696)

* avoid error when trying to delete a non-existing user

when force is set, but the user doesn't exist yet, this fails.

* 7696-avoid-attempt-to-delete-non-existing-user

add changelog entry

* rename changelog file

* Update changelogs/fragments/7696-avoid-attempt-to-delete-non-existing-user.yml

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

---------

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

Co-authored-by: Michiel Dethmers <michiel@phplist.com>
2023-12-21 13:20:32 +01:00
Felix Fontein
f6603d552e [stable-8] using timeout parameter within community.general.mail module (#7731) (#7752)
using timeout parameter within community.general.mail module (#7731)

* using timeout parameter within community.general.mail module

* consolidated time-out example within an existing playbook

* consolidated time-out example within an existing playbook

* Update plugins/modules/mail.py

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

---------

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

Co-authored-by: Aditya Putta <puttaa@skiff.com>
2023-12-20 08:19:43 +01:00
patchback[bot]
26dfe96ad6 [PR #7738/0b0a3028 backport][stable-8] Add documentation stubs for undocumented module options (#7750)
Add documentation stubs for undocumented module options (#7738)

Add documentation stubs for undocumented module options.

(cherry picked from commit 0b0a302855)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-12-20 07:43:34 +01:00
patchback[bot]
d7b89cde46 [PR #7685/98b2d043 backport][stable-8] Updated documentation to reflect new behaviour (#7749)
Updated documentation to reflect new behaviour (#7685)

* Updated documentation to reflect new behaviour

Per issue [6027](https://github.com/ansible-collections/community.general/issues/6027), disk and storage should not be used together, and changes to the API make it so "disk" should be formatted like "<storage>:<size in gb>".

Documentation edited to reflect this new behavior.

* Apply suggestions from code review

Change format due to referencing options.

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

---------

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

Co-authored-by: Wesley P <68830971+xhk416x@users.noreply.github.com>
2023-12-20 07:35:11 +01:00
patchback[bot]
6808f77f1a [PR #7739/097f0860 backport][stable-8] Bump github/codeql-action from 2 to 3 (#7742)
Bump github/codeql-action from 2 to 3 (#7739)

Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2 to 3.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
(cherry picked from commit 097f08608f)

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-18 19:30:12 +01:00
patchback[bot]
ec9fd625fc [PR #7703/5e5e1963 backport][stable-8] ssh_config: Add add_keys_to_agent option (#7735)
ssh_config: Add add_keys_to_agent option (#7703)

* Add ssh_config module option for add_keys_to_agent

* Add changelog fragment for 7703

---------

Co-authored-by: Michael Finney <michael.finney@tpwd.texas.gov>
(cherry picked from commit 5e5e1963c3)

Co-authored-by: mjfinney <mjfinney@gmail.com>
2023-12-17 15:43:36 +01:00
patchback[bot]
b80d408a25 [PR #7704/6c1eb77f backport][stable-8] Add ssh_config module option for identities_only (#7736)
Add ssh_config module option for identities_only (#7704)

* Add ssh_config module option for identities_only

* Add changelog fragment for 7704

* remove trailing whitespace

* Apply suggestions from code review

Documentation change suggestions from felixfontein

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

---------

Co-authored-by: Michael Finney <michael.finney@tpwd.texas.gov>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 6c1eb77f18)

Co-authored-by: mjfinney <mjfinney@gmail.com>
2023-12-17 15:43:28 +01:00
patchback[bot]
7db93a7dd3 [PR #7714/838e4e3f backport][stable-8] Add Alicloud, Online, Packet, and Scaleway scenario guides (#7719)
Add Alicloud, Online, Packet, and Scaleway scenario guides (#7714)

* Add Alicloud, Packet, and Scaleway scenario guides.

These were taken from
3f12228c79/docs/docsite/rst/scenario_guides
and adjusted to reality.

* Fix references.

* Add Online guide.

* Add BOTMETA entries.

* Use FQCN.

* Improve code formatting and indentation.

* Update BOTMETA.

(cherry picked from commit 838e4e3f02)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-12-11 19:55:05 +01:00
patchback[bot]
c79073c687 [PR #7709/0c7b9e50 backport][stable-8] Fix keytool setup on Debian Bookworm (#7712)
Fix keytool setup on Debian Bookworm (#7709)

Fix keytool setup on Debian Bookworm.

(cherry picked from commit 0c7b9e50b5)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-12-10 09:14:47 +01:00
patchback[bot]
09047058ce [PR #7705/aea238e5 backport][stable-8] Fix integration tests on Arch (#7708)
Fix integration tests on Arch (#7705)

* Fix ejabberd_user integration tests on Arch Linux.

* Fix odbc integration tests on Arch Linux.

* The old name of systemd_service is systemd.

(cherry picked from commit aea238e5d1)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-12-09 17:30:33 +01:00
patchback[bot]
7de503a2a3 [PR #7699/2b64ef2a backport][stable-8] Deactivate FreeBSD 13.1 in CI (#7702)
Deactivate FreeBSD 13.1 in CI (#7699)

Deactivate FreeBSD 13.1 in CI.

(cherry picked from commit 2b64ef2a62)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-12-08 07:10:33 +01:00
Felix Fontein
b746024c96 The next expected release is 8.2.0. 2023-12-04 21:28:06 +01:00
Felix Fontein
908a9836c0 Release 8.1.0. 2023-12-04 18:12:34 +01:00
Felix Fontein
adea41d773 [stable-8] Change tab to space in SSHFP requests (#7653) (#7682)
Change tab to space in SSHFP requests (#7653)

* Change tab to space in SSHFP requests

Cloudflare uses space and not tab when you search for SSHFP records

Cloudflare changes fingerprint to uppercase

Create 7653-fix-cloudflare-lookup.yml

* Update changelog fragment.

---------

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

Co-authored-by: Kalle Møller <git@k-moeller.dk>
2023-12-04 06:29:14 +01:00
patchback[bot]
2dd964cab3 [PR #7485/68051774 backport][stable-8] [proxmox_vm_info] Add ability to retrieve config (#7680)
[proxmox_vm_info] Add ability to retrieve config (#7485)

* feat: add ability to retrieve config

Light refactor of get_vms_from_nodes function.
Added ability to retrieve configuration for existing machines (current or pending).

* Add changelog fragment

* Add changelog fragment (newline missed)

* Update changelogs/fragments/7485-proxmox_vm_info-config.yml

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

* Apply suggestions from code review

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

* Replaced two bool options with one three-state option

* Module args for the three-state option

* Remove trailing newline

* Make use of dict instead of list. Fix uncalled 'get config for lxc'.

* Sanity tests

* A couple of unit tests fixed

* Unit tests fixed

* Unit tests for p2.7 fixed. Test for config parameter added.

---------

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

Co-authored-by: castorsky <csky57@gmail.com>
2023-12-04 06:29:02 +01:00
patchback[bot]
410101a116 [PR #7676/a599afa3 backport][stable-8] lvol: Change `pvs` argument type to list (of str) (#7681)
lvol: Change ``pvs`` argument type to list (of str) (#7676)

* lvol: Change ``pvs`` argument type to list (of str)

* Add changelog fragment

* Apply review suggestions

(cherry picked from commit a599afa384)

Co-authored-by: Laszlo Szomor <laszomor@gmail.com>
2023-12-04 06:26:57 +01:00
patchback[bot]
ec5dd70f8b [PR #7523/88d2a3a1 backport][stable-8] Feat nomad token module (#7677)
Feat nomad token module (#7523)

* Add nomad_token module

* Updatate nomad maintainers list

* Fix Example docstring

* Fix identations and Flake8 rules

* Fix  trailing whitespace

* Fix SyntaxError error

* change stringh format

* Fix Return doc string

* Fix Examples

* Fix flake8  rule W293

* Fix Doc schema

* Fix argument_spec

* Add maintainer

* Fix Example doc

* Remove token_info

* Change Doc

* Change nomad api acl token link

* Remove return whitespace

* Update plugins/modules/nomad_token.py

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

* Update plugins/modules/nomad_token.py

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

* Update plugins/modules/nomad_token.py

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

* Update plugins/modules/nomad_token.py

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

* Update plugins/modules/nomad_token.py

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

* Update plugins/modules/nomad_token.py

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

* Update plugins/modules/nomad_token.py

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

* Fix add changed state to True

* Update plugins/modules/nomad_token.py

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

* Change suport check mode

* Add unity tests

* Remove unused import

* Remove tests unused import

* Change python-nomad versions

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

* Change acl for ACL

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

* Add ACL to all docs

* Change msg to ansible common return value

* Fix flake8 W291

* Update description.

---------

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

Co-authored-by: apecnascimento <37672469+apecnascimento@users.noreply.github.com>
2023-12-03 14:12:03 +01:00
Felix Fontein
3473cb504e [stable-8] Keycloak print error msg from server (#7645) (#7675)
Keycloak print error msg from server (#7645)

* Retrive error msg

* changelog

* Update changelogs/fragments/7645-Keycloak-print-error-msg-from-server.yml

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

* test sanity

* Fixe var name

* Update plugins/module_utils/identity/keycloak/keycloak.py

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

* Update plugins/module_utils/identity/keycloak/keycloak.py

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

* Msg formating

---------

Co-authored-by: Andre Desrosiers <andre.desrosiers@ssss.gouv.qc.ca>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit e724bc5f51)

Co-authored-by: desand01 <desrosiers.a@hotmail.com>
2023-12-03 10:07:08 +01:00
patchback[bot]
c329192e82 [PR #7601/32558558 backport][stable-8] lvol: check return message in both stderr and stdout (#7674)
lvol: check return message in both stderr and stdout (#7601)

* lvol: check return message in both stderr and stdout

* add changelog frag

(cherry picked from commit 32558558c0)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2023-12-03 09:49:29 +01:00
patchback[bot]
7fe5e5f02c [PR #7260/07bac177 backport][stable-8] git_config: support multiple values for same name (#7672)
git_config: support multiple values for same name (#7260)

* Refactor the existing git_config.py

* Support multiple values for same name

(cherry picked from commit 07bac1777f)

Co-authored-by: Günther Grill <guenhter@users.noreply.github.com>
2023-12-03 09:49:20 +01:00
patchback[bot]
4482b04463 [PR #7521/b4a2e9da backport][stable-8] Lxd instance not found fix false positives (#7671)
Lxd instance not found fix false positives (#7521)

* lxd: Add lxc command execution debug statement.

* lxd: avoid false positives in "instance not found" detection

Due to changes over time in the error message which lxd printed when an
instance wasn't found, the detection logic in the lxd connection plugin
matched any "not found" string.  Unfortunately this also false triggered
on other errors e.g. "/usr/bin/python3: not found" from the payload,
giving a confusing error message "UNREACHABLE! ... instance not found"
to the ansible user.

* Update changelog fragment.

---------

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

Co-authored-by: Tim Small <tim@seoss.co.uk>
2023-12-03 09:49:10 +01:00
Felix Fontein
05608ea658 [stable-8] apt_rpm: add check if package version is upgradable (ansible-collections#7414) (#7669)
apt_rpm: add check if package version is upgradable (ansible-collections#7414) (#7577)

* apt_rpm: add check if package version is upgradable (ansible-collections#7414)

* add changelog fragment

* apt_rpm: apply the recommended changes and fix the sanity checks

---------

Co-authored-by: Nikolay Burykin <bne@altlinux.org>
(cherry picked from commit ecea4a2f38)

Co-authored-by: burykinne <67783534+burykinne@users.noreply.github.com>
2023-12-02 22:03:32 +01:00
patchback[bot]
a43132ba93 [PR #7626/30edafab backport][stable-8] add BootProgress property to redfish_info (#7668)
add BootProgress property to redfish_info (#7626)

* add BootProgress property to redfish_info

changelog

update changelog wording for end users

* Update changelog fragment.

---------

Co-authored-by: dgeorge <dgeorge@digitalocean.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 30edafabe7)

Co-authored-by: danxg87 <danxg87@gmail.com>
2023-12-02 21:26:24 +01:00
patchback[bot]
33c5e17762 [PR #7539/f4a87fdb backport][stable-8] New module: gitlab_issue.py (#7667)
New module: gitlab_issue.py (#7539)

* feat(gitlab_issue): adds module for gitlab issues management

* Apply suggestions from code review

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

* Apply suggestions from code review

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

* fix(gitlab_issue): assignee_ids and labels as lists

* docs(gitlab_issue): fix missing element types

* Apply suggestions from code review

Co-authored-by: Léo GATELLIER <26511053+lgatellier@users.noreply.github.com>

* chore(gitlab_issue): remove unnecessary parameter checks

* chore(gitlab_issue): renaming milestone_id parameter to milestone_search

---------

Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Léo GATELLIER <26511053+lgatellier@users.noreply.github.com>
(cherry picked from commit f4a87fdbcb)

Co-authored-by: Ondrej Zvara <zvara.ondrej@gmail.com>
2023-12-02 21:26:10 +01:00
patchback[bot]
42efe21600 [PR #7641/58cce27d backport][stable-8] Fix Keycloak API client to quote '/' properly (#7665)
Fix Keycloak API client to quote '/' properly (#7641)

* fix Keycloak API client to quote '/' properly

* add changelog

* Update changelogs/fragments/7641-fix-keycloak-api-client-to-quote-properly.yml

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

---------

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

Co-authored-by: Tomohiko Ozawa <kota65535@gmail.com>
2023-12-02 09:40:04 +01:00
patchback[bot]
fc02a7c74e [PR #7564/241cc02f backport][stable-8] onepassword lookup - Make section and field case insensitive (#7662)
onepassword lookup - Make section and field case insensitive (#7564)

* onepassword lookup: Make section and field case insensitive

This was a regression in behavior when adding support for op v2.

* Return a string by default to avoid an exception if a field is missing

* Use a helper function to lower a value if possible

* Update changelog

(cherry picked from commit 241cc02fa8)

Co-authored-by: Sam Doran <sdoran@redhat.com>
2023-12-01 18:17:48 +01:00
patchback[bot]
ef16e7ea4e [PR #7656/096d36ad backport][stable-8] passwordstore tests: re-enable gopass on Debian-like systems (#7658)
passwordstore tests: re-enable gopass on Debian-like systems (#7656)

Re-enable gopass on Debian-like systems.

(cherry picked from commit 096d36adc5)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-12-01 18:03:28 +01:00
patchback[bot]
dce0a65ffe [PR #7630/0589c841 backport][stable-8] Fix and re-enable cmd_runner tests (#7655)
Fix and re-enable cmd_runner tests (#7630)

Fix cmd_runner tests.

(cherry picked from commit 0589c84176)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-12-01 17:48:29 +01:00
patchback[bot]
ab2c0992e4 [PR #7540/cf7a58f6 backport][stable-8] Allow update of proxmox container configuration (#7648)
Allow update of proxmox container configuration (#7540)

* add update paramater to proxmox module

* add changelog fragment

* revert formatting changes

* make update idempotent

* fix lints

---------

Co-authored-by: Eric Trombly <etrombly@iomaxis.com>
(cherry picked from commit cf7a58f627)

Co-authored-by: Eric Trombly <etrombly@yahoo.com>
2023-12-01 07:55:15 +01:00
patchback[bot]
2c6b2e344b [PR #7602/e3a3950e backport][stable-8] fix #7600 add hookscript parameter to proxmox_kvm (#7649)
fix #7600 add hookscript parameter to proxmox_kvm (#7602)

* fix #7600 add hookscript parameter to proxmox_kvm

* add issue url to changelog

* fix changelog missing quote

* add missing version_added

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

* changelog: add missing dot

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

---------

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

Co-authored-by: Eric Le Lay <222469+elelay@users.noreply.github.com>
2023-12-01 07:54:54 +01:00
patchback[bot]
d87b91e279 [PR #7624/af01b462 backport][stable-8] redhat_subscription: use D-Bus registration on RHEL 7 only on 7.4+ (#7643)
redhat_subscription: use D-Bus registration on RHEL 7 only on 7.4+ (#7624)

subscription-manager does not provide a D-Bus interface in versions of
RHEL 7 older than 7.4.

(cherry picked from commit af01b462d5)

Co-authored-by: Pino Toscano <ptoscano@redhat.com>
2023-11-30 05:13:51 +00:00
patchback[bot]
505cde7e6b [PR #7569/42e55e4f backport][stable-8] infiniband can be a slave too (#7635)
infiniband can be a slave too (#7569)

* infiniband can be a slave too

* adding changelog fragment

(cherry picked from commit 42e55e4f86)

Co-authored-by: mark-tomich <tomichms@nih.gov>
2023-11-29 13:27:18 +01:00
patchback[bot]
0fcf81dd18 [PR #7588/d716bd46 backport][stable-8] ipa_config: add passkey choice to ipauserauthtype (#7636)
ipa_config: add passkey choice to ipauserauthtype (#7588)

* ipa_config: add passkey choice to ipauserauthtype

* Changelog Fragment - 7588

* ipa_config: edit ipauserauthtype description

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

---------

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

Co-authored-by: Christer Warén <cwchristerw@gmail.com>
2023-11-29 13:26:59 +01:00
patchback[bot]
e62a256724 [PR #7589/512b2c73 backport][stable-8] ipa_user: add idp and passkey choices to ipauserauthtype (#7637)
ipa_user: add idp and passkey choices to ipauserauthtype (#7589)

* ipa_user: add idp and passkey to ipauserauthtype

* Changelog Fragment - 7589

* ipa_user: edit ipauserauthtype description

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

---------

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

Co-authored-by: Christer Warén <cwchristerw@gmail.com>
2023-11-29 13:26:50 +01:00
patchback[bot]
ee7ba1a691 [PR #7587/1b9d437b backport][stable-8] New module git config info (#7638)
New module git config info (#7587)

Add new module git_config_info

(cherry picked from commit 1b9d437be8)

Co-authored-by: Günther Grill <guenhter@users.noreply.github.com>
2023-11-29 13:26:41 +01:00
patchback[bot]
ee428ccd64 [PR #7631/dbba0d19 backport][stable-8] Fix osx_defaults tests (#7633)
Fix osx_defaults tests (#7631)

Fix osx_defaults tests.

(cherry picked from commit dbba0d1956)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-11-29 07:47:19 +01:00
patchback[bot]
580f8b30a8 [PR #7625/3b779eca backport][stable-8] Fix bad expressions in tests (#7629)
Fix bad expressions in tests (#7625)

* Fix bad expressions in tests.

ci_complete

* Disable cmd_runner integration tests.

ci_complete

* Another bad expression.

ci_complete

(cherry picked from commit 3b779ecade)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-11-29 07:30:10 +01:00
patchback[bot]
7204798479 [PR #7576/d9f3e7a2 backport][stable-8] Only disable cert validation in examples for local network access (#7618)
Only disable cert validation in examples for local network access (#7576)

Only disable cert validation in examples for local network access!

(cherry picked from commit d9f3e7a2ec)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-11-26 22:13:50 +01:00
patchback[bot]
59b1329337 [PR #7490/e0346d40 backport][stable-8] Add onepassword_doc lookup plugin (#7617)
Add onepassword_doc lookup plugin (#7490)

* Add onepassword_doc lookup plugin

* Switch to a doc fragment

* Add unit test

* Update docs

* Move parameter validation to the OnePass object

This makes it built in for other lookup plugins using this class.

* Use kwargs for OnePass instantiation

There are enough parameters now that using them positionally can result in
odd behavior.

* Update tests

Correct conftest file name so fixtures are discovered and loaded correctly
Move constant so it doesn’t need to be imported
Add a patch since the parameter validation moved to part of the class init

* Use a lookup docs fragment

* Correct plugin description

(cherry picked from commit e0346d400f)

Co-authored-by: Sam Doran <sdoran@redhat.com>
2023-11-26 21:45:42 +01:00
patchback[bot]
e3eaeda81a [PR #7612/5adb7ab9 backport][stable-8] interfaces_file: filter by address_familiy when updating method (#7616)
interfaces_file: filter by address_familiy when updating method (#7612)

* When updating method, check address_family if provided.

* Also test modifying 'method' without address_family filter.

(cherry picked from commit 5adb7ab948)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-11-26 20:30:55 +01:00
patchback[bot]
b7e68f5b2d [PR #7611/f496256d backport][stable-8] Improve interfaces_file documentation (#7614)
Improve interfaces_file documentation (#7611)

Improve interfaces_file documentation.

(cherry picked from commit f496256d18)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-11-26 20:30:42 +01:00
patchback[bot]
dcb38bece0 [PR #7461/d05932fb backport][stable-8] Add option to proxmox dynamic inventory to exclude nodes (#7606)
Add option to proxmox dynamic inventory to exclude nodes (#7461)

* Create option to exclude proxmox nodes

* improve node exclusion by only remove the top level group

* add fragment

* Update changelogs/fragments/7437-proxmox-inventory-add-exclude-nodes.yaml

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

* Update plugins/inventory/proxmox.py

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

* Rework node exclusion

* Update fragement PR number

* include release version in option

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

* Clarify description

* Update unit test

* Fix typos in unit test

* Fix additonal typos in test

* Fix CI

* Fixing yet another whitespace pep error

---------

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

Co-authored-by: IamLunchbox <56757745+IamLunchbox@users.noreply.github.com>
2023-11-26 17:35:57 +01:00
patchback[bot]
c82c375aef [PR #7538/938aec49 backport][stable-8] [keycloak_user_federation]: Adding option krbPrincipalAttribute (#7605)
[keycloak_user_federation]: Adding option krbPrincipalAttribute (#7538)

* keycloak_user_federation: Adding support for krbPrincipalAttribute

Signed-off-by: boolman <boolman@gmail.com>

* pr/7538 adding changelogs/fragment file

Signed-off-by: boolman <boolman@gmail.com>

* Update changelogs/fragments/7538-add-krbprincipalattribute-option.yml

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

* Update plugins/modules/keycloak_user_federation.py

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

* Update plugins/modules/keycloak_user_federation.py

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

---------

Signed-off-by: boolman <boolman@gmail.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 938aec492e)

Co-authored-by: Boolman <boolman@gmail.com>
2023-11-26 17:35:45 +01:00
patchback[bot]
d5f6889f51 [PR #7603/12395732 backport][stable-8] CI: temporarily skip passwordstore tests on Debian/Ubuntu (#7608)
CI: temporarily skip passwordstore tests on Debian/Ubuntu (#7603)

Skip passwordstore tests on Debian/Ubuntu.

(cherry picked from commit 12395732e8)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-11-26 17:35:25 +01:00
patchback[bot]
ff8e67840f [PR #7535/af5da7d4 backport][stable-8] fix(modules/terraform): handle multiline strings correctly in complex variables (#7599)
fix(modules/terraform): handle multiline strings correctly in complex variables (#7535)

(cherry picked from commit af5da7d412)

Co-authored-by: Yann Soubeyrand <github@yann.soubeyrand.eu>
2023-11-24 21:47:55 +01:00
patchback[bot]
c1d142f543 [PR #7591/19984ce4 backport][stable-8] Update proxmox_tasks_info.py (#7595)
Update proxmox_tasks_info.py (#7591)

fix typo
I spend 3 hours because of this mistake

(cherry picked from commit 19984ce4df)

Co-authored-by: Андрей Неустроев <99169437+aneustroev@users.noreply.github.com>
2023-11-24 21:29:32 +01:00
patchback[bot]
cb9be1349a [PR #7592/b2dea631 backport][stable-8] Remove Fedora 36 from CI (#7597)
Remove Fedora 36 from CI (#7592)

Remove Fedora 36 from CI.

(cherry picked from commit b2dea631d1)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-11-24 21:29:23 +01:00
patchback[bot]
59086813c1 [PR #7558/fce91ebb backport][stable-8] ini_file: documentation for 'section' to stop mentioning that null can be passed (#7584)
ini_file: documentation for 'section' to stop mentioning that null can be passed (#7558)

Update ini_file's documentation for 'section' to stop mentioning that null can be passed.

(cherry picked from commit fce91ebbd4)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-11-23 06:53:37 +01:00
patchback[bot]
12319f4a82 [PR #7552/58705d5a backport][stable-8] More docs cleanup (#7579)
More docs cleanup (#7552)

* More docs improvements.

* timezone: mention which versions of AIX are supported.

(cherry picked from commit 58705d5ac3)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-11-23 06:18:57 +01:00
patchback[bot]
04b29342d2 [PR #7550/f87777b9 backport][stable-8] irc module: add validate_certs, rename use_ssl to use_tls (keeping use_ssl as an alias) (#7575)
irc module: add validate_certs, rename use_ssl to use_tls (keeping use_ssl as an alias) (#7550)

* Rename use_ssl to use_tls, keep use_ssl as an alias.

* Add validate_certs option.

* Add changelog fragment and recommend setting TLS related settings to true.

* Fix formatting.

* Update documentation to use use_tls=true and validate_certs=true.

(cherry picked from commit f87777b9f5)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-11-22 19:27:57 +01:00
patchback[bot]
0d23fa7a49 [PR #7549/d530470d backport][stable-8] logentries: docs improvements (#7572)
logentries: docs improvements (#7549)

Docs improvements.

(cherry picked from commit d530470d30)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-11-22 19:27:44 +01:00
patchback[bot]
dbec1ebf7a [PR #7554/0c4d2a6e backport][stable-8] galaxy.yml: improve description, improve YAML, remove not really relevant comments (#7570)
galaxy.yml: improve description, improve YAML, remove not really relevant comments (#7554)

Improve description, improve YAML, remove not really relevant comments.

(cherry picked from commit 0c4d2a6e5e)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-11-22 19:27:23 +01:00
patchback[bot]
feefec42df [PR #7563/09b9ea46 backport][stable-8] Set resources payload as a list (#7574)
Set resources payload as a list (#7563)

* Set resources payload as a list

* Update changelogs/fragments/7151-fix-keycloak_authz_permission-incorrect-resource-payload.yml

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

---------

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

Co-authored-by: fostermi <mfosterm@gmail.com>
2023-11-22 19:20:50 +01:00
patchback[bot]
a60cba237f [PR #7533/2a5e7c33 backport][stable-8] Add test fqdn_valid (#7567)
Add test fqdn_valid (#7533)

* Add test fqdn_valid

* Add integration test fqdn_valid

* Add changelogs 7533-add-test-fqdn_valid

* Fix changelogs filename 7533-add-test-fqdn_valid.yml

* Add runme.* to install PyPI package fqdn and run the test.

* Remove changelog. New tests are documented by their version_added + short_description.

* Guarded import fqdn.

* Update plugins/test/fqdn_valid.py

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

* Update plugins/test/fqdn_valid.py

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

* Update plugins/test/fqdn_valid.py

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

* Update plugins/test/fqdn_valid.py

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

* Update tests/integration/targets/test_fqdn_valid/aliases

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

* Add tests/fqdn_valid.py maintained by vbotka.

* Fix integration. Add explicit collections to test_fqdn_valid

* Fix integration. Remove unused import ansible.errors

* Fix PEP8 E275

* Fix E402 module level import not at top of file.

* Fix E275 missing whitespace after keyword

* Update plugins/test/fqdn_valid.py

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

* Update plugins/test/fqdn_valid.py

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

* Update plugins/test/fqdn_valid.py

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

* Update plugins/test/fqdn_valid.py

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

---------

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

Co-authored-by: Vladimir Botka <vbotka@gmail.com>
2023-11-22 09:26:17 +01:00
patchback[bot]
76d011ed4b [PR #7515/5147c494 backport][stable-8] Add support for loopback type in nmcli module (#7566)
Add support for loopback type in nmcli module (#7515)

* add support for loopback devices

* add support for loopback devices

* fix yamllint issue in changelog fragment

* Fix yamlint warning and add note about new connectin type in docs

* change order of lines in documentation so they are sorted

(cherry picked from commit 5147c49498)

Co-authored-by: Alex Groshev <38885591+haddystuff@users.noreply.github.com>
2023-11-22 09:26:04 +01:00
patchback[bot]
3ba00d5a07 [PR #7551/a88f6f56 backport][stable-8] Clean up doc fragments a bit (#7568)
Clean up doc fragments a bit (#7551)

Clean up doc fragments a bit.

(cherry picked from commit a88f6f56c7)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-11-22 09:25:54 +01:00
patchback[bot]
8eb3003894 [PR #7560/9b163926 backport][stable-8] test helper: Helper.from_module() injects test function into test module (#7562)
test helper: Helper.from_module() injects test function into test module (#7560)

(cherry picked from commit 9b16392648)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2023-11-22 09:11:12 +01:00
patchback[bot]
89158ce325 [PR #7555/404782c9 backport][stable-8] ansible_galaxy_install: forgot to remove mentions of the no longer supported Ansible 2.9 in the docs (#7561)
ansible_galaxy_install: forgot to remove mentions of the no longer supported Ansible 2.9 in the docs (#7555)

Forgot to remove mentions of the no longer supported Ansible 2.9 in the docs.

(cherry picked from commit 404782c9d7)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-11-20 22:18:05 +01:00
patchback[bot]
7f8d77b9f3 [PR #7542/21cd65fc backport][stable-8] ssl.wrap_socket() was removed in Python 3.12 (#7557)
ssl.wrap_socket() was removed in Python 3.12 (#7542)

* ssl.wrap_socket() was removed in Python 3.12.

* Make code for irc module backwards-compatible.

(cherry picked from commit 21cd65fccf)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-11-19 14:46:21 +01:00
Felix Fontein
3cf90b3e36 Prepare 8.1.0 release. 2023-11-19 10:50:13 +01:00
patchback[bot]
189b737c50 [PR #7495/3c12c6f4 backport][stable-8] [proxmox_disk]: Add ability to manipulate CD-ROM drive (#7553)
[proxmox_disk]: Add ability to manipulate CD-ROM drive (#7495)

* add: ability to manipulate CD-ROM drive

Added ability to manipulate CD-ROM drive:
create, mount, umount, use physical drive.

* Add changelog fragment

* Relax cdrom option requirement

* Formatting values

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

* YAML fix

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

---------

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

Co-authored-by: castorsky <csky57@gmail.com>
2023-11-19 10:40:06 +01:00
patchback[bot]
c4bd7c2b7b [PR #7541/b8ecb167 backport][stable-8] CI: devel supports Fedora 39, and no longer Fedora 38 (#7548)
CI: devel supports Fedora 39, and no longer Fedora 38 (#7541)

* devel supports Fedora 39, and no longer Fedora 38.

* Disable 'mail' tests for Python 3.12+.

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

* Fix setupSSLServer to work with Python 3.12.

(cherry picked from commit b8ecb1671b)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-11-18 14:34:13 +01:00
patchback[bot]
ea427d3c82 [PR #7543/b3c661a9 backport][stable-8] sysrc: FreeBSD jail test no longer works with FreeBSD 13.1 (#7546)
sysrc: FreeBSD jail test no longer works with FreeBSD 13.1 (#7543)

Jail test no longer works with FreeBSD 13.1.

(cherry picked from commit b3c661a9f6)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-11-18 14:01:43 +01:00
patchback[bot]
bc011c60e6 [PR #7534/89f12c87 backport][stable-8] CI: remove skip/python2.6 from aliases (#7537)
CI: remove skip/python2.6 from aliases (#7534)

Remove skip/python2.6 from aliases.

Since 8.0.0 we no longer support any ansible-core version that supports Python 2.6.

(cherry picked from commit 89f12c87eb)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-11-16 21:22:07 +01:00
patchback[bot]
a76537b24f [PR #7116/f8652571 backport][stable-8] Support 1Password Connect (#5588) (#7536)
Support 1Password Connect (#5588) (#7116)

* Support 1Password Connect (#5588)

- Support 1Password Connect with the opv2 client

* Follow pep8, be less explicit

* Update changelog to include PR

* 1Password Connect host and token are now also parameters

* Get argument values from the environment or lookup arguments

* Move imports

* Force using Connect token and host at the same time

* Update unit tests

* Update documentation

* Additional tests

(cherry picked from commit f8652571f7)

Co-authored-by: Xeryus Stokkel <XeryusTC@users.noreply.github.com>
2023-11-16 21:02:54 +01:00
patchback[bot]
327777a1da [PR #7524/32fa588f backport][stable-8] CI: Add rhel/9.3 for devel, remove rhel/9.2 (#7531)
CI: Add rhel/9.3 for devel, remove rhel/9.2 (#7524)

* Add rhel/9.3 for devel, remove rhel/9.2.

* Also skip rhel/9.3 when skipping rhel/9.2.

* snapd is also on available on RHEL 9.3.

(cherry picked from commit 32fa588f47)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-11-16 07:55:14 +01:00
patchback[bot]
d8ee97c7e9 [PR #7517/8d886b42 backport][stable-8] Close elastic APM client to release connections (#7529)
Close elastic APM client to release connections (#7517)

* Close elastic APM client to release connections

* Changelog fragment

(cherry picked from commit 8d886b42ec)

Co-authored-by: Iuri de Silvio <iurisilvio@gmail.com>
2023-11-15 22:34:45 +01:00
patchback[bot]
52ffc4eb7c [PR #7415/df66885f backport][stable-8] Ipa sudorule/add deny options (#7526)
Ipa sudorule/add deny options (#7415)

* Introduce options to include 'deny' commands and command groups

* Adding Changelog fragment

* Apply suggestions from code review

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

* Update changelogs/fragments/add-ipa-sudorule-deny-cmd.yml

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

* Update plugins/modules/ipa_sudorule.py

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

* Update plugins/modules/ipa_sudorule.py

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

---------

Co-authored-by: Ris Adams <ris@risadams.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit df66885fa4)

Co-authored-by: Ris Adams <5329119+risadams@users.noreply.github.com>
2023-11-15 22:13:57 +01:00
patchback[bot]
be8c05bf65 [PR #7489/f8d8f691 backport][stable-8] Netcup DNS: Add support for additional record types (#7525)
Netcup DNS: Add support for additional record types (#7489)

* Netcup DNS: Add support for additional record types

* Netcup DNS: Add changelog fragment

* Netcup DNS: Include information on minimum required versions in module documentation

* Apply suggestions from code review

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

---------

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

Co-authored-by: buzz-tee <11776936+buzz-tee@users.noreply.github.com>
2023-11-15 22:13:41 +01:00
patchback[bot]
bf284a01cb [PR #7499/d0870a02 backport][stable-8] infiniband and bond interfaces can receive MTU settings too (#7527)
infiniband and bond interfaces can receive MTU settings too (#7499)

* infiniband and bond interfaces can receive MTU settings too

* adding test for default mtu setting

* the mtu parameter for infiniband is different than for ethernet

* adding changelog fragment

* Update changelogs/fragments/7499-allow-mtu-setting-on-bond-and-infiniband-interfaces.yml

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

---------

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

Co-authored-by: mark-tomich <tomichms@nih.gov>
2023-11-15 22:13:22 +01:00
patchback[bot]
c1f9aeaac8 [PR #7486/4a74f46e backport][stable-8] refactor(gitlab modules): remove duplicate gitlab package check (#7516)
refactor(gitlab modules): remove duplicate gitlab package check (#7486)

(cherry picked from commit 4a74f46e56)

Co-authored-by: Léo GATELLIER <26511053+lgatellier@users.noreply.github.com>
2023-11-13 20:42:35 +01:00
patchback[bot]
1a5ad80589 [PR #7199/6b00b76f backport][stable-8] feat(gitlab_runner module): Add support for the new runner creation workflow (#7511)
feat(gitlab_runner module): Add support for the new runner creation workflow (#7199)

feat(gitlab_runner module): Handle new runner creation workflow

(cherry picked from commit 6b00b76f32)

Co-authored-by: Léo GATELLIER <26511053+lgatellier@users.noreply.github.com>
2023-11-13 20:22:33 +01:00
patchback[bot]
f2e2157bcc [PR #7468/65f58afb backport][stable-8] Improve performance of the bitwarden lookup plugin (#7512)
Improve performance of the bitwarden lookup plugin (#7468)

* Improve performance of the bitwarden lookup plugin

When looking for items using an item id, we can access the item directly with
bw get item instead of searching through all items. This doubles the lookup
speed.

* Update changelogs/fragments/bitwarden-lookup-performance.yaml

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

* fix indentation

* Ensure backwards compatible behavior in case of errors when doing bitwarden lookup by id

* chore: Link to correct PR in changelog fragment

* Use identity check when comparing with None

---------

Co-authored-by: Richard Klose <richard.klose@gec.io>
Co-authored-by: Richard Klose <richard@klose.dev>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 65f58afbd9)

Co-authored-by: Pascal Hofmann <mail@pascalhofmann.de>
2023-11-13 20:22:25 +01:00
patchback[bot]
20d2488f0f [PR #7456/c2f08c57 backport][stable-8] [ssh_config] Add support for ControlMaster (#7510)
[ssh_config] Add support for ControlMaster (#7456)

* [ssh_config] Add support for ControlMaster

* Create separate function to convert bool

* Allow str values with yes/no options to also use bool

(cherry picked from commit c2f08c57e0)

Co-authored-by: Marcel <maleo@google.com>
2023-11-13 20:22:17 +01:00
patchback[bot]
7d75bb3d7e [PR #7462/2583c604 backport][stable-8] Add ostype parameter in LXC container clone of Proxmox VE (#7513)
Add ostype parameter in LXC container clone of Proxmox VE (#7462)

* update. proxmox lxc add ostype param

* update.

* update. E501

* update. E123

* update. pullrequestreview-1711205075

* update. commit undo formatted by editor auto-update

* update. add change fragment (pullrequestreview-1711205075)

* update. pullrequestreview-1711911827

(cherry picked from commit 2583c60487)

Co-authored-by: blacknon <blacknon@orebibou.com>
2023-11-13 20:22:09 +01:00
patchback[bot]
c5f8719fe9 [PR #7426/6a514b68 backport][stable-8] Add options for password generation in the passwordstore module (#7507)
Add options for password generation in the passwordstore module (#7426)

* feat: Add options for password generation.

* feat: Add documentations for options for password generation.

* fix: Remove newline from the end of the stored raw password

* fix: Define 'msg' variable before the reference inside the condition block

* feat: Add information when the 'timestamp' parameter was added

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

* feat: Add information when the 'preserve' parameter was added

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

* feat: Add changelog fragment for adding new parameters to the 'passwordstore' module

* feat: Change the evaluation of password modification conditions.

* feat: Change version of parameter 'timestamp' from 8.0.0 to 8.0.1

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

* feat: Change version of parameter 'preserve' from 8.0.0 to 8.0.1

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

* fix: Remove newline character from the timestamp message

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

* fix: Add newline character to the end of 'preserve' message.

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

---------

Co-authored-by: Michal Drobny <494056@muni.cz>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 6a514b6843)

Co-authored-by: Michal Drobny <70282353+drobnymichal@users.noreply.github.com>
2023-11-13 20:22:00 +01:00
patchback[bot]
79cfc48dd5 [PR #7143/07a47c04 backport][stable-8] add template option to proxmox and proxmox_kvm (#7488)
add template option to proxmox and proxmox_kvm (#7143)

* add template option to proxmox and proxmox_kvm

* make recommended updates

* fix tests

* resolve comments on PR

* save changes to changelog fragment

* Update changelogs/fragments/7143-proxmox-template.yml

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

---------

Co-authored-by: Eric Trombly <etrombly@iomaxis.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 07a47c047b)

Co-authored-by: Eric Trombly <etrombly@yahoo.com>
2023-11-13 20:21:53 +01:00
patchback[bot]
e0489d738a [PR #7472/567c7d18 backport][stable-8] feature(gitlab): add 'ca_path' option (#7487)
feature(gitlab): add 'ca_path' option (#7472)

(cherry picked from commit 567c7d1839)

Co-authored-by: Léo GATELLIER <26511053+lgatellier@users.noreply.github.com>
2023-11-13 20:21:43 +01:00
Felix Fontein
3e1cbbb617 Next expected release will be 8.1.0. 2023-11-13 20:20:57 +01:00
Felix Fontein
28d7c499b5 Release 8.0.2. 2023-11-13 19:58:06 +01:00
Felix Fontein
9f218be912 Prepare 8.0.2 release. 2023-11-11 12:39:26 +01:00
Felix Fontein
363936a544 Fix RST code formatting.
(cherry picked from commit e1503fc306)
2023-11-11 12:38:33 +01:00
patchback[bot]
a8351fa9df [PR #7506/c2e578cb backport][stable-8] pipx: change parameter formatter for pip_args (#7514)
pipx: change parameter formatter for pip_args (#7506)

* change parameter formatter for pip_args

* add changelog frag

(cherry picked from commit c2e578cb14)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2023-11-11 12:36:48 +01:00
patchback[bot]
4b84127ef3 [PR #7501/48e860be backport][stable-8] Use isinstance() instead of type() (#7503)
Use isinstance() instead of type() (#7501)

* Replace type comparisons with isinstance() checks.

* Add changelog.

(cherry picked from commit 48e860be20)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-11-08 13:27:04 +01:00
Felix Fontein
82e1f24d2e The next expected release is 8.0.2. 2023-11-06 21:43:17 +01:00
Felix Fontein
9e8b6ea803 Release 8.0.1. 2023-11-06 21:05:10 +01:00
Felix Fontein
db8a6609de Fix release summary. 2023-11-06 21:04:45 +01:00
patchback[bot]
5be75b8e43 [PR #7464/03049893 backport][stable-8] fix vm removal in proxmox_pool_member.py (#7494)
fix vm removal in proxmox_pool_member.py (#7464)

* fix vm removal in proxmox_pool_member.py

in the original the vm doesn't get removed, always errors with "'Failed to delete a member (12345) from the pool TestPool: list.remove(x): x not in list'

* add changelog fragment

* fix linting errors in changelog

(cherry picked from commit 0304989392)

Co-authored-by: aungvari <12872375+aungvari@users.noreply.github.com>
2023-11-06 20:45:46 +01:00
patchback[bot]
71b1ae0aff [PR #7471/ab0b85d7 backport][stable-8] Redfish: Updated message handling for update operations to skip message objects with missing MessageId properties (#7492)
Redfish: Updated message handling for update operations to skip message objects with missing MessageId properties (#7471)

* Redfish: Updated message handling for update operations to skip message objects with missing MessageId properties

Signed-off-by: Mike Raineri <michael.raineri@dell.com>

* Update 7465-redfish-firmware-update-message-id-hardening.yml

---------

Signed-off-by: Mike Raineri <michael.raineri@dell.com>
(cherry picked from commit ab0b85d7d2)

Co-authored-by: Mike Raineri <mraineri@gmail.com>
2023-11-06 06:25:16 +01:00
patchback[bot]
9b2fa2cfd7 [PR #7480/74e941e4 backport][stable-8] Disable nomad tests (#7484)
Disable nomad tests (#7480)

Disable nomad tests.

(cherry picked from commit 74e941e432)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-11-04 14:01:15 +01:00
patchback[bot]
83193ffc1f [PR #7476/57e36d7d backport][stable-8] timezone tests: do not restore original timezone if it wasn't known (value 'n/a') (#7479)
timezone tests: do not restore original timezone if it wasn't known (value 'n/a') (#7476)

Do not restore original timezone if it wasn't known (value 'n/a').

(cherry picked from commit 57e36d7dc2)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-11-04 13:23:02 +01:00
Felix Fontein
4b955a3548 Prepare 8.0.1 release. 2023-11-04 12:18:42 +01:00
patchback[bot]
c7dbda3656 [PR #7467/a366318a backport][stable-8] [gitlab] Fix gitlab constants calls (#7474)
[gitlab] Fix gitlab constants calls (#7467)

fix: Fix gitlab constants calls

Co-authored-by: Arnaud Hatzenbuhler <arnaud.hatzenbuhler@conserto.pro>
(cherry picked from commit a366318ac6)

Co-authored-by: Arnaud Hatzenbuhler <arnaud.hatzenbuhler@gmail.com>
2023-11-04 09:31:49 +01:00
Felix Fontein
e98cf96499 Fix version number. 2023-11-02 13:13:50 +01:00
Felix Fontein
8d52dc3f1d Next expected release will be 8.0.1. 2023-11-01 09:19:18 +01:00
Felix Fontein
5f9ea0b7ac Release 8.0.0. 2023-11-01 08:34:14 +01:00
Felix Fontein
d125f5bee6 Main branches are stable-8 and stable-7; stable-6 runs more seldomly in CI.
(cherry picked from commit 6d0bcec1cb)
2023-11-01 08:10:31 +01:00
Felix Fontein
82c5970811 Prepare 8.0.0 release. 2023-11-01 08:09:07 +01:00
1139 changed files with 59568 additions and 64939 deletions

View File

@@ -29,14 +29,14 @@ schedules:
always: true
branches:
include:
- stable-10
- stable-9
- stable-8
- cron: 0 11 * * 0
displayName: Weekly (old stable branches)
always: true
branches:
include:
- stable-8
- stable-7
variables:
- name: checkoutPath
@@ -73,19 +73,6 @@ stages:
- test: 3
- test: 4
- test: extra
- stage: Sanity_2_18
displayName: Sanity 2.18
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Test {0}
testFormat: 2.18/sanity/{0}
targets:
- test: 1
- test: 2
- test: 3
- test: 4
- stage: Sanity_2_17
displayName: Sanity 2.17
dependsOn: []
@@ -112,6 +99,19 @@ stages:
- test: 2
- test: 3
- test: 4
- stage: Sanity_2_15
displayName: Sanity 2.15
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Test {0}
testFormat: 2.15/sanity/{0}
targets:
- test: 1
- test: 2
- test: 3
- test: 4
### Units
- stage: Units_devel
displayName: Units devel
@@ -128,17 +128,6 @@ stages:
- test: '3.11'
- test: '3.12'
- test: '3.13'
- stage: Units_2_18
displayName: Units 2.18
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: 2.18/units/{0}/1
targets:
- test: 3.8
- test: "3.13"
- stage: Units_2_17
displayName: Units 2.17
dependsOn: []
@@ -162,6 +151,17 @@ stages:
- test: 2.7
- test: 3.6
- test: "3.11"
- stage: Units_2_15
displayName: Units 2.15
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: 2.15/units/{0}/1
targets:
- test: 3.5
- test: "3.10"
## Remote
- stage: Remote_devel_extra_vms
@@ -172,14 +172,12 @@ stages:
parameters:
testFormat: devel/{0}
targets:
- name: Alpine 3.20
test: alpine/3.20
# - name: Fedora 40
# test: fedora/40
- name: Alpine 3.19
test: alpine/3.19
# - name: Fedora 39
# test: fedora/39
- name: Ubuntu 22.04
test: ubuntu/22.04
- name: Ubuntu 24.04
test: ubuntu/24.04
groups:
- vm
- stage: Remote_devel
@@ -192,26 +190,10 @@ stages:
targets:
- name: macOS 14.3
test: macos/14.3
- name: RHEL 9.4
test: rhel/9.4
- name: FreeBSD 14.1
test: freebsd/14.1
- name: FreeBSD 13.4
test: freebsd/13.4
groups:
- 1
- 2
- 3
- stage: Remote_2_18
displayName: Remote 2.18
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.18/{0}
targets:
- name: RHEL 9.4
test: rhel/9.4
- name: RHEL 9.3
test: rhel/9.3
- name: FreeBSD 14.0
test: freebsd/14.0
groups:
- 1
- 2
@@ -226,10 +208,6 @@ stages:
targets:
- name: FreeBSD 13.3
test: freebsd/13.3
- name: RHEL 9.3
test: rhel/9.3
- name: FreeBSD 14.0
test: freebsd/14.0
groups:
- 1
- 2
@@ -248,10 +226,30 @@ stages:
test: rhel/9.2
- name: RHEL 8.8
test: rhel/8.8
- name: FreeBSD 13.2
test: freebsd/13.2
groups:
- 1
- 2
- 3
- stage: Remote_2_15
displayName: Remote 2.15
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.15/{0}
targets:
- name: RHEL 9.1
test: rhel/9.1
- name: RHEL 8.7
test: rhel/8.7
- name: RHEL 7.9
test: rhel/7.9
# - name: FreeBSD 13.2
# test: freebsd/13.2
# - name: FreeBSD 13.1
# test: freebsd/13.1
# - name: FreeBSD 12.4
# test: freebsd/12.4
groups:
- 1
- 2
@@ -266,28 +264,12 @@ stages:
parameters:
testFormat: devel/linux/{0}
targets:
- name: Fedora 40
test: fedora40
- name: Alpine 3.20
test: alpine320
- name: Fedora 39
test: fedora39
- name: Ubuntu 20.04
test: ubuntu2004
- name: Ubuntu 22.04
test: ubuntu2204
- name: Ubuntu 24.04
test: ubuntu2404
groups:
- 1
- 2
- 3
- stage: Docker_2_18
displayName: Docker 2.18
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.18/linux/{0}
targets:
- name: Ubuntu 24.04
test: ubuntu2404
groups:
- 1
- 2
@@ -300,12 +282,8 @@ stages:
parameters:
testFormat: 2.17/linux/{0}
targets:
- name: Fedora 39
test: fedora39
- name: Alpine 3.19
test: alpine319
- name: Ubuntu 20.04
test: ubuntu2004
groups:
- 1
- 2
@@ -324,6 +302,20 @@ stages:
test: opensuse15
- name: Alpine 3
test: alpine3
groups:
- 1
- 2
- 3
- stage: Docker_2_15
displayName: Docker 2.15
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.15/linux/{0}
targets:
- name: Fedora 37
test: fedora37
- name: CentOS 7
test: centos7
groups:
@@ -345,86 +337,84 @@ stages:
- name: Debian Bookworm
test: debian-bookworm/3.11
- name: ArchLinux
test: archlinux/3.13
test: archlinux/3.12
groups:
- 1
- 2
- 3
### Generic
# Right now all generic tests are disabled. Uncomment when at least one of them is re-enabled.
# - stage: Generic_devel
# displayName: Generic devel
# dependsOn: []
# jobs:
# - template: templates/matrix.yml
# parameters:
# nameFormat: Python {0}
# testFormat: devel/generic/{0}/1
# targets:
# - test: '3.8'
# - test: '3.11'
# - test: '3.13'
# - stage: Generic_2_18
# displayName: Generic 2.18
# dependsOn: []
# jobs:
# - template: templates/matrix.yml
# parameters:
# nameFormat: Python {0}
# testFormat: 2.18/generic/{0}/1
# targets:
# - test: '3.8'
# - test: '3.13'
# - stage: Generic_2_17
# displayName: Generic 2.17
# dependsOn: []
# jobs:
# - template: templates/matrix.yml
# parameters:
# nameFormat: Python {0}
# testFormat: 2.17/generic/{0}/1
# targets:
# - test: '3.7'
# - test: '3.12'
# - stage: Generic_2_16
# displayName: Generic 2.16
# dependsOn: []
# jobs:
# - template: templates/matrix.yml
# parameters:
# nameFormat: Python {0}
# testFormat: 2.16/generic/{0}/1
# targets:
# - test: '2.7'
# - test: '3.6'
# - test: '3.11'
- stage: Generic_devel
displayName: Generic devel
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: devel/generic/{0}/1
targets:
- test: '3.8'
- test: '3.11'
- test: '3.13'
- stage: Generic_2_17
displayName: Generic 2.17
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: 2.17/generic/{0}/1
targets:
- test: '3.7'
- test: '3.12'
- stage: Generic_2_16
displayName: Generic 2.16
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: 2.16/generic/{0}/1
targets:
- test: '2.7'
- test: '3.6'
- test: '3.11'
- stage: Generic_2_15
displayName: Generic 2.15
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: 2.15/generic/{0}/1
targets:
- test: '3.9'
- stage: Summary
condition: succeededOrFailed()
dependsOn:
- Sanity_devel
- Sanity_2_18
- Sanity_2_17
- Sanity_2_16
- Sanity_2_15
- Units_devel
- Units_2_18
- Units_2_17
- Units_2_16
- Units_2_15
- Remote_devel_extra_vms
- Remote_devel
- Remote_2_18
- Remote_2_17
- Remote_2_16
- Remote_2_15
- Docker_devel
- Docker_2_18
- Docker_2_17
- Docker_2_16
- Docker_2_15
- Docker_community_devel
# Right now all generic tests are disabled. Uncomment when at least one of them is re-enabled.
# - Generic_devel
# - Generic_2_18
# - Generic_2_17
# - Generic_2_16
# - Generic_2_15
jobs:
- template: templates/coverage.yml

152
.github/BOTMETA.yml vendored
View File

@@ -33,8 +33,6 @@ files:
maintainers: $team_ansible_core
$becomes/pmrun.py:
maintainers: $team_ansible_core
$becomes/run0.py:
maintainers: konstruktoid
$becomes/sesu.py:
maintainers: nekonyuu
$becomes/sudosu.py:
@@ -61,6 +59,7 @@ files:
$callbacks/elastic.py:
keywords: apm observability
maintainers: v1v
$callbacks/hipchat.py: {}
$callbacks/jabber.py: {}
$callbacks/log_plays.py: {}
$callbacks/loganalytics.py:
@@ -90,8 +89,6 @@ files:
maintainers: ryancurrah
$callbacks/syslog_json.py:
maintainers: imjoseangel
$callbacks/timestamp.py:
maintainers: kurokobo
$callbacks/unixy.py:
labels: unixy
maintainers: akatch
@@ -120,8 +117,6 @@ files:
maintainers: $team_ansible_core
$doc_fragments/:
labels: docs_fragments
$doc_fragments/django.py:
maintainers: russoz
$doc_fragments/hpe3par.py:
labels: hpe3par
maintainers: farhan7500 gautamphegde
@@ -130,13 +125,9 @@ files:
maintainers: $team_huawei
$doc_fragments/nomad.py:
maintainers: chris93111 apecnascimento
$doc_fragments/pipx.py:
maintainers: russoz
$doc_fragments/xenserver.py:
labels: xenserver
maintainers: bvitnik
$filters/accumulate.py:
maintainers: VannTen
$filters/counter.py:
maintainers: keilr
$filters/crc32.py:
@@ -160,8 +151,6 @@ files:
$filters/jc.py:
maintainers: kellyjonbrazil
$filters/json_query.py: {}
$filters/keep_keys.py:
maintainers: vbotka
$filters/lists.py:
maintainers: cfiehe
$filters/lists_difference.yml:
@@ -175,12 +164,6 @@ files:
$filters/lists_union.yml:
maintainers: cfiehe
$filters/random_mac.py: {}
$filters/remove_keys.py:
maintainers: vbotka
$filters/replace_keys.py:
maintainers: vbotka
$filters/reveal_ansible_type.py:
maintainers: vbotka
$filters/time.py:
maintainers: resmo
$filters/to_days.yml:
@@ -213,8 +196,6 @@ files:
maintainers: opoplawski
$inventories/gitlab_runners.py:
maintainers: morph027
$inventories/iocage.py:
maintainers: vbotka
$inventories/icinga2.py:
maintainers: BongoEADGC6
$inventories/linode.py:
@@ -311,18 +292,10 @@ files:
maintainers: delineaKrehl tylerezimmerman
$module_utils/:
labels: module_utils
$module_utils/android_sdkmanager.py:
maintainers: shamilovstas
$module_utils/btrfs.py:
maintainers: gnfzdz
$module_utils/cmd_runner_fmt.py:
maintainers: russoz
$module_utils/cmd_runner.py:
maintainers: russoz
$module_utils/deps.py:
maintainers: russoz
$module_utils/django.py:
maintainers: russoz
$module_utils/gconftool2.py:
labels: gconftool2
maintainers: russoz
@@ -366,8 +339,6 @@ files:
$module_utils/pipx.py:
labels: pipx
maintainers: russoz
$module_utils/python_runner.py:
maintainers: russoz
$module_utils/puppet.py:
labels: puppet
maintainers: russoz
@@ -424,8 +395,6 @@ files:
ignore: DavidWittman jiuka
labels: alternatives
maintainers: mulby
$modules/android_sdk.py:
maintainers: shamilovstas
$modules/ansible_galaxy_install.py:
maintainers: russoz
$modules/apache2_mod_proxy.py:
@@ -459,8 +428,6 @@ files:
maintainers: hkariti
$modules/bitbucket_:
maintainers: catcombo
$modules/bootc_manage.py:
maintainers: cooktheryan
$modules/bower.py:
maintainers: mwarkentin
$modules/btrfs_:
@@ -514,8 +481,6 @@ files:
ignore: skornehl
$modules/dconf.py:
maintainers: azaghal
$modules/decompress.py:
maintainers: shamilovstas
$modules/deploy_helper.py:
maintainers: ramondelafuente
$modules/dimensiondata_network.py:
@@ -525,12 +490,6 @@ files:
maintainers: tintoy
$modules/discord.py:
maintainers: cwollinger
$modules/django_check.py:
maintainers: russoz
$modules/django_command.py:
maintainers: russoz
$modules/django_createcachetable.py:
maintainers: russoz
$modules/django_manage.py:
ignore: scottanderson42 tastychutney
labels: django_manage
@@ -573,6 +532,8 @@ files:
maintainers: $team_flatpak
$modules/flatpak_remote.py:
maintainers: $team_flatpak
$modules/flowdock.py:
ignore: mcodd
$modules/gandi_livedns.py:
maintainers: gthiemonge
$modules/gconftool2.py:
@@ -661,11 +622,6 @@ files:
labels: homebrew_ macos
maintainers: $team_macos
notify: chris-short
$modules/homebrew_services.py:
ignore: ryansb
keywords: brew cask services darwin homebrew macosx macports osx
labels: homebrew_ macos
maintainers: $team_macos kitizz
$modules/homectl.py:
maintainers: jameslivulpi
$modules/honeybadger_deployment.py:
@@ -725,8 +681,6 @@ files:
$modules/ipa_:
maintainers: $team_ipa
ignore: fxfitz
$modules/ipa_getkeytab.py:
maintainers: abakanovskii
$modules/ipa_dnsrecord.py:
maintainers: $team_ipa jwbernin
$modules/ipbase_info.py:
@@ -772,8 +726,6 @@ files:
maintainers: sermilrod
$modules/jenkins_job_info.py:
maintainers: stpierre
$modules/jenkins_node.py:
maintainers: phyrwork
$modules/jenkins_plugin.py:
maintainers: jtyr
$modules/jenkins_script.py:
@@ -810,8 +762,6 @@ files:
maintainers: fynncfchen johncant
$modules/keycloak_clientsecret_regenerate.py:
maintainers: fynncfchen johncant
$modules/keycloak_component.py:
maintainers: fivetide
$modules/keycloak_group.py:
maintainers: adamgoossens
$modules/keycloak_identity_provider.py:
@@ -828,8 +778,6 @@ files:
maintainers: elfelip
$modules/keycloak_user_federation.py:
maintainers: laurpaum
$modules/keycloak_userprofile.py:
maintainers: yeoldegrove
$modules/keycloak_component_info.py:
maintainers: desand01
$modules/keycloak_client_rolescope.py:
@@ -844,8 +792,6 @@ files:
maintainers: ahussey-redhat
$modules/kibana_plugin.py:
maintainers: barryib
$modules/krb_ticket.py:
maintainers: abakanovskii
$modules/launchd.py:
maintainers: martinm82
$modules/layman.py:
@@ -856,8 +802,6 @@ files:
maintainers: drybjed jtyr noles
$modules/ldap_entry.py:
maintainers: jtyr
$modules/ldap_inc.py:
maintainers: pduveau
$modules/ldap_passwd.py:
maintainers: KellerFuchs jtyr
$modules/ldap_search.py:
@@ -999,8 +943,6 @@ files:
maintainers: $team_opennebula
$modules/one_host.py:
maintainers: rvalle
$modules/one_vnet.py:
maintainers: abakanovskii
$modules/oneandone_:
maintainers: aajdinov edevenport
$modules/onepassword_info.py:
@@ -1129,8 +1071,6 @@ files:
$modules/proxmox_kvm.py:
ignore: skvidal
maintainers: helldorado krauthosting
$modules/proxmox_backup.py:
maintainers: IamLunchbox
$modules/proxmox_nic.py:
maintainers: Kogelvis krauthosting
$modules/proxmox_node_info.py:
@@ -1156,6 +1096,46 @@ files:
$modules/python_requirements_info.py:
ignore: ryansb
maintainers: willthames
$modules/rax:
ignore: ryansb sivel
$modules/rax.py:
maintainers: omgjlk sivel
$modules/rax_cbs.py:
maintainers: claco
$modules/rax_cbs_attachments.py:
maintainers: claco
$modules/rax_cdb.py:
maintainers: jails
$modules/rax_cdb_database.py:
maintainers: jails
$modules/rax_cdb_user.py:
maintainers: jails
$modules/rax_clb.py:
maintainers: claco
$modules/rax_clb_nodes.py:
maintainers: neuroid
$modules/rax_clb_ssl.py:
maintainers: smashwilson
$modules/rax_files.py:
maintainers: angstwad
$modules/rax_files_objects.py:
maintainers: angstwad
$modules/rax_identity.py:
maintainers: claco
$modules/rax_mon_alarm.py:
maintainers: smashwilson
$modules/rax_mon_check.py:
maintainers: smashwilson
$modules/rax_mon_entity.py:
maintainers: smashwilson
$modules/rax_mon_notification.py:
maintainers: smashwilson
$modules/rax_mon_notification_plan.py:
maintainers: smashwilson
$modules/rax_network.py:
maintainers: claco omgjlk
$modules/rax_queue.py:
maintainers: claco
$modules/read_csv.py:
maintainers: dagwieers
$modules/redfish_:
@@ -1180,6 +1160,12 @@ files:
keywords: kvm libvirt proxmox qemu
labels: rhevm virt
maintainers: $team_virt TimothyVandenbrande
$modules/rhn_channel.py:
labels: rhn_channel
maintainers: vincentvdk alikins $team_rhn
$modules/rhn_register.py:
labels: rhn_register
maintainers: jlaska $team_rhn
$modules/rhsm_release.py:
maintainers: seandst $team_rhsm
$modules/rhsm_repository.py:
@@ -1314,6 +1300,8 @@ files:
maintainers: farhan7500 gautamphegde
$modules/ssh_config.py:
maintainers: gaqzi Akasurde
$modules/stackdriver.py:
maintainers: bwhaley
$modules/stacki_host.py:
labels: stacki_host
maintainers: bsanders bbyhuy
@@ -1343,10 +1331,6 @@ files:
maintainers: precurse
$modules/sysrc.py:
maintainers: dlundgren
$modules/systemd_creds_decrypt.py:
maintainers: konstruktoid
$modules/systemd_creds_encrypt.py:
maintainers: konstruktoid
$modules/sysupgrade.py:
maintainers: precurse
$modules/taiga_issue.py:
@@ -1410,6 +1394,8 @@ files:
maintainers: $team_wdc
$modules/wdc_redfish_info.py:
maintainers: $team_wdc
$modules/webfaction_:
maintainers: quentinsf
$modules/xattr.py:
labels: xattr
maintainers: bcoca
@@ -1461,19 +1447,10 @@ files:
ignore: matze
labels: zypper
maintainers: $team_suse
$plugin_utils/ansible_type.py:
maintainers: vbotka
$modules/zypper_repository_info.py:
labels: zypper
maintainers: $team_suse TobiasZeuch181
$plugin_utils/keys_filter.py:
maintainers: vbotka
$plugin_utils/unsafe.py:
maintainers: felixfontein
$tests/a_module.py:
maintainers: felixfontein
$tests/ansible_type.py:
maintainers: vbotka
$tests/fqdn_valid.py:
maintainers: vbotka
#########################
@@ -1487,14 +1464,6 @@ files:
maintainers: felixfontein
docs/docsite/rst/filter_guide_abstract_informations_lists_helper.rst:
maintainers: cfiehe
docs/docsite/rst/filter_guide-abstract_informations-lists_of_dictionaries-keep_keys.rst:
maintainers: vbotka
docs/docsite/rst/filter_guide-abstract_informations-lists_of_dictionaries-remove_keys.rst:
maintainers: vbotka
docs/docsite/rst/filter_guide-abstract_informations-lists_of_dictionaries-replace_keys.rst:
maintainers: vbotka
docs/docsite/rst/filter_guide-abstract_informations-lists_of_dictionaries.rst:
maintainers: vbotka
docs/docsite/rst/filter_guide_abstract_informations_merging_lists_of_dictionaries.rst:
maintainers: vbotka
docs/docsite/rst/filter_guide_conversions.rst:
@@ -1511,20 +1480,12 @@ files:
maintainers: ericzolf
docs/docsite/rst/guide_alicloud.rst:
maintainers: xiaozhu36
docs/docsite/rst/guide_cmdrunner.rst:
maintainers: russoz
docs/docsite/rst/guide_deps.rst:
maintainers: russoz
docs/docsite/rst/guide_modulehelper.rst:
maintainers: russoz
docs/docsite/rst/guide_online.rst:
maintainers: remyleone
docs/docsite/rst/guide_packet.rst:
maintainers: baldwinSPC nurfet-becirevic t0mk teebes
docs/docsite/rst/guide_scaleway.rst:
maintainers: $team_scaleway
docs/docsite/rst/guide_vardict.rst:
maintainers: russoz
docs/docsite/rst/test_guide.rst:
maintainers: felixfontein
#########################
@@ -1556,7 +1517,7 @@ macros:
team_ansible_core:
team_aix: MorrisA bcoca d-little flynn1973 gforster kairoaraujo marvin-sinister mator molekuul ramooncamacho wtcross
team_bsd: JoergFiedler MacLemon bcoca dch jasperla mekanix opoplawski overhacked tuxillo
team_consul: sgargan apollo13 Ilgmi
team_consul: sgargan apollo13
team_cyberark_conjur: jvanderhoof ryanprior
team_e_spirit: MatrixCrawler getjack
team_flatpak: JayKayy oolongbrothers
@@ -1565,7 +1526,7 @@ macros:
team_huawei: QijunPan TommyLike edisonxiang freesky-edward hwDCN niuzhenguo xuxiaowei0512 yanzhangi zengchen1024 zhongjun2
team_ipa: Akasurde Nosmoht justchris1
team_jboss: Wolfant jairojunior wbrefvem
team_keycloak: eikef ndclt mattock thomasbach-dev
team_keycloak: eikef ndclt mattock
team_linode: InTheCloudDan decentral1se displague rmcintosh Charliekenney23 LBGarber
team_macos: Akasurde kyleabenson martinm82 danieljaouen indrajitr
team_manageiq: abellotti cben gtanzillo yaacov zgalor dkorn evertmulder
@@ -1574,9 +1535,10 @@ macros:
team_oracle: manojmeda mross22 nalsaber
team_purestorage: bannaych dnix101 genegr lionmax opslounge raekins sdodsley sile16
team_redfish: mraineri tomasg2012 xmadsen renxulei rajeevkallur bhavya06 jyundt
team_rhn: FlossWare alikins barnabycourt vritant
team_rhsm: cnsnyder ptoscano
team_scaleway: remyleone abarbare
team_solaris: bcoca fishman jasperla jpdasma mator scathatheworm troy2914 xen0l
team_suse: commel evrardjp lrupp AnderEnder alxgu andytom sealor
team_suse: commel evrardjp lrupp toabctl AnderEnder alxgu andytom sealor
team_virt: joshainglis karmab Thulium-Drake Ajpantuso
team_wdc: mikemoerk

View File

@@ -29,7 +29,8 @@ jobs:
strategy:
matrix:
ansible:
- '2.15'
- '2.13'
- '2.14'
# Ansible-test on various stable branches does not yet work well with cgroups v2.
# Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04
# image for these stable branches. The list of branches where this is necessary will
@@ -65,12 +66,16 @@ jobs:
exclude:
- ansible: ''
include:
- ansible: '2.15'
- ansible: '2.13'
python: '2.7'
- ansible: '2.15'
python: '3.5'
- ansible: '2.15'
python: '3.10'
- ansible: '2.13'
python: '3.8'
- ansible: '2.13'
python: '2.7'
- ansible: '2.13'
python: '3.8'
- ansible: '2.14'
python: '3.9'
steps:
- name: >-
@@ -111,29 +116,54 @@ jobs:
exclude:
- ansible: ''
include:
# 2.15
- ansible: '2.15'
# 2.13
- ansible: '2.13'
docker: fedora35
python: ''
target: azp/posix/1/
- ansible: '2.13'
docker: fedora35
python: ''
target: azp/posix/2/
- ansible: '2.13'
docker: fedora35
python: ''
target: azp/posix/3/
- ansible: '2.13'
docker: opensuse15py2
python: ''
target: azp/posix/1/
- ansible: '2.13'
docker: opensuse15py2
python: ''
target: azp/posix/2/
- ansible: '2.13'
docker: opensuse15py2
python: ''
target: azp/posix/3/
- ansible: '2.13'
docker: alpine3
python: ''
target: azp/posix/1/
- ansible: '2.15'
- ansible: '2.13'
docker: alpine3
python: ''
target: azp/posix/2/
- ansible: '2.15'
- ansible: '2.13'
docker: alpine3
python: ''
target: azp/posix/3/
- ansible: '2.15'
docker: fedora37
# 2.14
- ansible: '2.14'
docker: alpine3
python: ''
target: azp/posix/1/
- ansible: '2.15'
docker: fedora37
- ansible: '2.14'
docker: alpine3
python: ''
target: azp/posix/2/
- ansible: '2.15'
docker: fedora37
- ansible: '2.14'
docker: alpine3
python: ''
target: azp/posix/3/
# Right now all generic tests are disabled. Uncomment when at least one of them is re-enabled.
@@ -141,14 +171,11 @@ jobs:
# docker: default
# python: '3.9'
# target: azp/generic/1/
# Right now all generic tests are disabled. Uncomment when at least one of them is re-enabled.
# - ansible: '2.14'
# docker: default
# python: '3.10'
# target: azp/generic/1/
# - ansible: '2.15'
# docker: default
# python: '3.9'
# target: azp/generic/1/
steps:
- name: >-

View File

@@ -25,8 +25,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL

View File

@@ -7,14 +7,10 @@ name: Verify REUSE
on:
push:
branches:
- main
- stable-*
pull_request:
branches: [main]
pull_request_target:
types: [opened, synchronize, reopened]
branches:
- main
- stable-*
branches: [main]
# Run CI once per day (at 07:30 UTC)
schedule:
- cron: '30 7 * * *'
@@ -28,8 +24,7 @@ jobs:
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
uses: fsfe/reuse-action@v3

4
.gitignore vendored
View File

@@ -512,7 +512,3 @@ $RECYCLE.BIN/
# Integration tests cloud configs
tests/integration/cloud-config-*.ini
# VSCode specific extensions
.vscode/settings.json

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -56,8 +56,6 @@ 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
The following commands show how to run sanity tests:
```.bash
@@ -68,8 +66,6 @@ ansible-test sanity --docker -v
ansible-test sanity --docker -v plugins/modules/system/pids.py tests/integration/targets/pids/
```
### Unit tests
The following commands show how to run unit tests:
```.bash
@@ -83,32 +79,13 @@ ansible-test units --docker -v --python 3.8
ansible-test units --docker -v --python 3.8 tests/unit/plugins/modules/net_tools/test_nmcli.py
```
### Integration tests
The following commands show how to run integration tests:
#### In Docker
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`.
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
ansible-test integration -v --docker fedora40
# Run integration tests for the interfaces_files module in a Docker container using the
# fedora35 operating system image (the supported images depend on your ansible-core version):
ansible-test integration --docker fedora35 -v interfaces_file
# Template
ansible-test integration -v --docker image_name test_name
# Example community.general.ini_file module on fedora40 Docker image:
ansible-test integration -v --docker fedora40 ini_file
```
#### Without isolation
```.bash
# Run integration tests for the flattened lookup **without any isolation**:
ansible-test integration -v lookup_flattened
```

View File

@@ -6,7 +6,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
# Community General Collection
[![Build Status](https://dev.azure.com/ansible/community.general/_apis/build/status/CI?branchName=stable-10)](https://dev.azure.com/ansible/community.general/_build?definitionId=31)
[![Build Status](https://dev.azure.com/ansible/community.general/_apis/build/status/CI?branchName=stable-8)](https://dev.azure.com/ansible/community.general/_build?definitionId=31)
[![EOL CI](https://github.com/ansible-collections/community.general/workflows/EOL%20CI/badge.svg?event=push)](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)
@@ -23,21 +23,9 @@ We follow [Ansible Code of Conduct](https://docs.ansible.com/ansible/latest/comm
If you encounter abusive behavior violating the [Ansible Code of Conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html), please refer to the [policy violations](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html#policy-violations) section of the Code of Conduct for information on how to raise a complaint.
## Communication
* Join the Ansible forum:
* [Get Help](https://forum.ansible.com/c/help/6): get help or help others. This is for questions about modules or plugins in the collection. Please add appropriate tags if you start new discussions.
* [Tag `community-general`](https://forum.ansible.com/tag/community-general): discuss the *collection itself*, instead of specific modules or plugins.
* [Social Spaces](https://forum.ansible.com/c/chat/4): gather and interact with fellow enthusiasts.
* [News & Announcements](https://forum.ansible.com/c/news/5): track project-wide announcements including social events.
* The Ansible [Bullhorn newsletter](https://docs.ansible.com/ansible/devel/community/communication.html#the-bullhorn): used to announce releases and important changes.
For more information about communication, see the [Ansible communication guide](https://docs.ansible.com/ansible/devel/community/communication.html).
## Tested with Ansible
Tested with the current ansible-core 2.15, ansible-core 2.16, ansible-core 2.17, ansible-core 2.18 releases and the current development version of ansible-core. Ansible-core versions before 2.15.0 are not supported. This includes all ansible-base 2.10 and Ansible 2.9 releases.
Tested with the current ansible-core 2.13, ansible-core 2.14, ansible-core 2.15, ansible-core 2.16, ansible-core 2.17 releases and the current development version of ansible-core. Ansible-core versions before 2.13.0 are not supported. This includes all ansible-base 2.10 and Ansible 2.9 releases.
## External requirements
@@ -110,13 +98,25 @@ It is necessary for maintainers of this collection to be subscribed to:
They also should be subscribed to Ansible's [The Bullhorn newsletter](https://docs.ansible.com/ansible/devel/community/communication.html#the-bullhorn).
## Communication
We announce important development changes and releases through Ansible's [The Bullhorn newsletter](https://eepurl.com/gZmiEP). If you are a collection developer, be sure you are subscribed.
Join us in the `#ansible` (general use questions and support), `#ansible-community` (community and collection development questions), and other [IRC channels](https://docs.ansible.com/ansible/devel/community/communication.html#irc-channels) on [Libera.chat](https://libera.chat).
We take part in the global quarterly [Ansible Contributor Summit](https://github.com/ansible/community/wiki/Contributor-Summit) virtually or in-person. Track [The Bullhorn newsletter](https://eepurl.com/gZmiEP) and join us.
For more information about communities, meetings and agendas see [Community Wiki](https://github.com/ansible/community/wiki/Community).
For more information about communication, refer to Ansible's the [Communication guide](https://docs.ansible.com/ansible/devel/community/communication.html).
## Publishing New Version
See the [Releasing guidelines](https://github.com/ansible/community-docs/blob/main/releasing_collections.rst) to learn how to release this collection.
## Release notes
See the [changelog](https://github.com/ansible-collections/community.general/blob/stable-10/CHANGELOG.md).
See the [changelog](https://github.com/ansible-collections/community.general/blob/stable-8/CHANGELOG.md).
## Roadmap
@@ -135,8 +135,8 @@ See [this issue](https://github.com/ansible-collections/community.general/issues
This collection is primarily licensed and distributed as a whole under the GNU General Public License v3.0 or later.
See [LICENSES/GPL-3.0-or-later.txt](https://github.com/ansible-collections/community.general/blob/stable-10/COPYING) for the full text.
See [LICENSES/GPL-3.0-or-later.txt](https://github.com/ansible-collections/community.general/blob/main/COPYING) for the full text.
Parts of the collection are licensed under the [BSD 2-Clause license](https://github.com/ansible-collections/community.general/blob/stable-10/LICENSES/BSD-2-Clause.txt), the [MIT license](https://github.com/ansible-collections/community.general/blob/stable-10/LICENSES/MIT.txt), and the [PSF 2.0 license](https://github.com/ansible-collections/community.general/blob/stable-10/LICENSES/PSF-2.0.txt).
Parts of the collection are licensed under the [BSD 2-Clause license](https://github.com/ansible-collections/community.general/blob/main/LICENSES/BSD-2-Clause.txt), the [MIT license](https://github.com/ansible-collections/community.general/blob/main/LICENSES/MIT.txt), and the [PSF 2.0 license](https://github.com/ansible-collections/community.general/blob/main/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/).

File diff suppressed because it is too large Load Diff

View File

@@ -18,25 +18,23 @@ output_formats:
prelude_section_name: release_summary
prelude_section_title: Release Summary
sections:
- - major_changes
- Major Changes
- - minor_changes
- Minor Changes
- - breaking_changes
- Breaking Changes / Porting Guide
- - deprecated_features
- Deprecated Features
- - removed_features
- Removed Features (previously deprecated)
- - security_fixes
- Security Fixes
- - bugfixes
- Bugfixes
- - known_issues
- Known Issues
- - major_changes
- Major Changes
- - minor_changes
- Minor Changes
- - breaking_changes
- Breaking Changes / Porting Guide
- - deprecated_features
- Deprecated Features
- - removed_features
- Removed Features (previously deprecated)
- - security_fixes
- Security Fixes
- - bugfixes
- Bugfixes
- - known_issues
- Known Issues
title: Community General
trivial_section_name: trivial
use_fqcn: true
add_plugin_period: true
changelog_nice_yaml: true
changelog_sort: version

View File

@@ -14,9 +14,3 @@ sections:
- guide_online
- guide_packet
- guide_scaleway
- title: Developer Guides
toctree:
- guide_deps
- guide_vardict
- guide_cmdrunner
- guide_modulehelper

View File

@@ -1,61 +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
-->
# Docs helper. Create RST file.
The playbook `playbook.yml` writes a RST file that can be used in
docs/docsite/rst. The usage of this helper is recommended but not
mandatory. You can stop reading here and update the RST file manually
if you don't want to use this helper.
## Run the playbook
If you want to generate the RST file by this helper fit the variables
in the playbook and the template to your needs. Then, run the play
```sh
shell> ansible-playbook playbook.yml
```
## Copy RST to docs/docsite/rst
Copy the RST file to `docs/docsite/rst` and remove it from this
directory.
## Update the checksums
Substitute the variables and run the below commands
```sh
shell> sha1sum {{ target_vars }} > {{ target_sha1 }}
shell> sha1sum {{ file_rst }} > {{ file_sha1 }}
```
## Playbook explained
The playbook includes the variable *tests* from the integration tests
and creates the RST file from the template. The playbook will
terminate if:
* The file with the variable *tests* was changed
* The RST file was changed
This means that this helper is probably not up to date.
### The file with the variable *tests* was changed
This means that somebody updated the integration tests. Review the
changes and update the template if needed. Update the checksum to pass
the integrity test. The playbook message provides you with the
command.
### The RST file was changed
This means that somebody updated the RST file manually. Review the
changes and update the template. Update the checksum to pass the
integrity test. The playbook message provides you with the
command. Make sure that the updated template will create identical RST
file. Only then apply your changes.

View File

@@ -1,80 +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
keep_keys
"""""""""
Use the filter :ansplugin:`community.general.keep_keys#filter` if you have a list of dictionaries and want to keep certain keys only.
.. note:: The output of the examples in this section use the YAML callback plugin. Quoting: "Ansible output that can be quite a bit easier to read than the default JSON formatting." See :ansplugin:`the documentation for the community.general.yaml callback plugin <community.general.yaml#callback>`.
Let us use the below list in the following examples:
.. code-block:: yaml
input:
{{ tests.0.input | to_yaml(indent=2) | indent(5) }}
{% for i in tests[0:1]|subelements('group') %}
* {{ i.1.d }}
.. code-block:: yaml+jinja
:emphasize-lines: 1
target: {{ i.1.tt }}
result: "{{ lookup('file', target ~ '/templates/' ~ i.0.template) }}"
{% endfor %}
gives
.. code-block:: yaml
:emphasize-lines: 1-
result:
{{ tests.0.result | to_yaml(indent=2) | indent(5) }}
.. versionadded:: 9.1.0
* The results of the below examples 1-5 are all the same:
.. code-block:: yaml
:emphasize-lines: 1-
result:
{{ tests.1.result | to_yaml(indent=2) | indent(5) }}
{% for i in tests[1:2]|subelements('group') %}
{{ loop.index }}. {{ i.1.d }}
.. code-block:: yaml+jinja
:emphasize-lines: 1,2
mp: {{ i.1.mp }}
target: {{ i.1.tt }}
result: "{{ lookup('file', target ~ '/templates/' ~ i.0.template) }}"
{% endfor %}
* The results of the below examples 6-9 are all the same:
.. code-block:: yaml
:emphasize-lines: 1-
result:
{{ tests.2.result | to_yaml(indent=2) | indent(5) }}
{% for i in tests[2:3]|subelements('group') %}
{{ loop.index + 5 }}. {{ i.1.d }}
.. code-block:: yaml+jinja
:emphasize-lines: 1,2
mp: {{ i.1.mp }}
target: {{ i.1.tt }}
result: "{{ lookup('file', target ~ '/templates/' ~ i.0.template) }}"
{% endfor %}

View File

@@ -1 +0,0 @@
8690afce792abc95693c2f61f743ee27388b1592 ../../rst/filter_guide-abstract_informations-lists_of_dictionaries-keep_keys.rst

View File

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

View File

@@ -1,79 +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
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Create docs REST files
# shell> ansible-playbook playbook.yml
#
# Proofread and copy created *.rst file into the directory
# docs/docsite/rst. Do not add *.rst in this directory to the version
# control.
#
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# community.general/docs/docsite/helper/keep_keys/playbook.yml
- name: Create RST file for docs/docsite/rst
hosts: localhost
gather_facts: false
vars:
plugin: keep_keys
plugin_type: filter
docs_path:
- filter_guide
- abstract_informations
- lists_of_dictionaries
file_base: "{{ (docs_path + [plugin]) | join('-') }}"
file_rst: ../../rst/{{ file_base }}.rst
file_sha1: "{{ plugin }}.rst.sha1"
target: "../../../../tests/integration/targets/{{ plugin_type }}_{{ plugin }}"
target_vars: "{{ target }}/vars/main/tests.yml"
target_sha1: tests.yml.sha1
tasks:
- name: Test integrity tests.yml
when:
- integrity | d(true) | bool
- lookup('file', target_sha1) != lookup('pipe', 'sha1sum ' ~ target_vars)
block:
- name: Changed tests.yml
ansible.builtin.debug:
msg: |
Changed {{ target_vars }}
Review the changes and update {{ target_sha1 }}
shell> sha1sum {{ target_vars }} > {{ target_sha1 }}
- name: Changed tests.yml end host
ansible.builtin.meta: end_play
- name: Test integrity RST file
when:
- integrity | d(true) | bool
- lookup('file', file_sha1) != lookup('pipe', 'sha1sum ' ~ file_rst)
block:
- name: Changed RST file
ansible.builtin.debug:
msg: |
Changed {{ file_rst }}
Review the changes and update {{ file_sha1 }}
shell> sha1sum {{ file_rst }} > {{ file_sha1 }}
- name: Changed RST file end host
ansible.builtin.meta: end_play
- name: Include target vars
include_vars:
file: "{{ target_vars }}"
- name: Create RST file
ansible.builtin.template:
src: "{{ file_base }}.rst.j2"
dest: "{{ file_base }}.rst"

View File

@@ -1 +0,0 @@
c6fc4ee2017d9222675bcd13cc4f88ba8d14f38d ../../../../tests/integration/targets/filter_keep_keys/vars/main/tests.yml

View File

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

View File

@@ -1,61 +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
-->
# Docs helper. Create RST file.
The playbook `playbook.yml` writes a RST file that can be used in
docs/docsite/rst. The usage of this helper is recommended but not
mandatory. You can stop reading here and update the RST file manually
if you don't want to use this helper.
## Run the playbook
If you want to generate the RST file by this helper fit the variables
in the playbook and the template to your needs. Then, run the play
```sh
shell> ansible-playbook playbook.yml
```
## Copy RST to docs/docsite/rst
Copy the RST file to `docs/docsite/rst` and remove it from this
directory.
## Update the checksums
Substitute the variables and run the below commands
```sh
shell> sha1sum {{ target_vars }} > {{ target_sha1 }}
shell> sha1sum {{ file_rst }} > {{ file_sha1 }}
```
## Playbook explained
The playbook includes the variable *tests* from the integration tests
and creates the RST file from the template. The playbook will
terminate if:
* The file with the variable *tests* was changed
* The RST file was changed
This means that this helper is probably not up to date.
### The file with the variable *tests* was changed
This means that somebody updated the integration tests. Review the
changes and update the template if needed. Update the checksum to pass
the integrity test. The playbook message provides you with the
command.
### The RST file was changed
This means that somebody updated the RST file manually. Review the
changes and update the template. Update the checksum to pass the
integrity test. The playbook message provides you with the
command. Make sure that the updated template will create identical RST
file. Only then apply your changes.

View File

@@ -1,80 +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
remove_keys
"""""""""""
Use the filter :ansplugin:`community.general.remove_keys#filter` if you have a list of dictionaries and want to remove certain keys.
.. note:: The output of the examples in this section use the YAML callback plugin. Quoting: "Ansible output that can be quite a bit easier to read than the default JSON formatting." See See :ansplugin:`the documentation for the community.general.yaml callback plugin <community.general.yaml#callback>`.
Let us use the below list in the following examples:
.. code-block:: yaml
input:
{{ tests.0.input | to_yaml(indent=2) | indent(5) }}
{% for i in tests[0:1]|subelements('group') %}
* {{ i.1.d }}
.. code-block:: yaml+jinja
:emphasize-lines: 1
target: {{ i.1.tt }}
result: "{{ lookup('file', target ~ '/templates/' ~ i.0.template) }}"
{% endfor %}
gives
.. code-block:: yaml
:emphasize-lines: 1-
result:
{{ tests.0.result | to_yaml(indent=2) | indent(5) }}
.. versionadded:: 9.1.0
* The results of the below examples 1-5 are all the same:
.. code-block:: yaml
:emphasize-lines: 1-
result:
{{ tests.1.result | to_yaml(indent=2) | indent(5) }}
{% for i in tests[1:2]|subelements('group') %}
{{ loop.index }}. {{ i.1.d }}
.. code-block:: yaml+jinja
:emphasize-lines: 1,2
mp: {{ i.1.mp }}
target: {{ i.1.tt }}
result: "{{ lookup('file', target ~ '/templates/' ~ i.0.template) }}"
{% endfor %}
* The results of the below examples 6-9 are all the same:
.. code-block:: yaml
:emphasize-lines: 1-
result:
{{ tests.2.result | to_yaml(indent=2) | indent(5) }}
{% for i in tests[2:3]|subelements('group') %}
{{ loop.index + 5 }}. {{ i.1.d }}
.. code-block:: yaml+jinja
:emphasize-lines: 1,2
mp: {{ i.1.mp }}
target: {{ i.1.tt }}
result: "{{ lookup('file', target ~ '/templates/' ~ i.0.template) }}"
{% endfor %}

View File

@@ -1,79 +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
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Create docs REST files
# shell> ansible-playbook playbook.yml
#
# Proofread and copy created *.rst file into the directory
# docs/docsite/rst. Do not add *.rst in this directory to the version
# control.
#
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# community.general/docs/docsite/helper/remove_keys/playbook.yml
- name: Create RST file for docs/docsite/rst
hosts: localhost
gather_facts: false
vars:
plugin: remove_keys
plugin_type: filter
docs_path:
- filter_guide
- abstract_informations
- lists_of_dictionaries
file_base: "{{ (docs_path + [plugin]) | join('-') }}"
file_rst: ../../rst/{{ file_base }}.rst
file_sha1: "{{ plugin }}.rst.sha1"
target: "../../../../tests/integration/targets/{{ plugin_type }}_{{ plugin }}"
target_vars: "{{ target }}/vars/main/tests.yml"
target_sha1: tests.yml.sha1
tasks:
- name: Test integrity tests.yml
when:
- integrity | d(true) | bool
- lookup('file', target_sha1) != lookup('pipe', 'sha1sum ' ~ target_vars)
block:
- name: Changed tests.yml
ansible.builtin.debug:
msg: |
Changed {{ target_vars }}
Review the changes and update {{ target_sha1 }}
shell> sha1sum {{ target_vars }} > {{ target_sha1 }}
- name: Changed tests.yml end host
ansible.builtin.meta: end_play
- name: Test integrity RST file
when:
- integrity | d(true) | bool
- lookup('file', file_sha1) != lookup('pipe', 'sha1sum ' ~ file_rst)
block:
- name: Changed RST file
ansible.builtin.debug:
msg: |
Changed {{ file_rst }}
Review the changes and update {{ file_sha1 }}
shell> sha1sum {{ file_rst }} > {{ file_sha1 }}
- name: Changed RST file end host
ansible.builtin.meta: end_play
- name: Include target vars
include_vars:
file: "{{ target_vars }}"
- name: Create RST file
ansible.builtin.template:
src: "{{ file_base }}.rst.j2"
dest: "{{ file_base }}.rst"

View File

@@ -1 +0,0 @@
3cc606b42e3d450cf6323f25930f7c5a591fa086 ../../rst/filter_guide-abstract_informations-lists_of_dictionaries-remove_keys.rst

View File

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

View File

@@ -1 +0,0 @@
0554335045f02d8c37b824355b0cf86864cee9a5 ../../../../tests/integration/targets/filter_remove_keys/vars/main/tests.yml

View File

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

View File

@@ -1,61 +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
-->
# Docs helper. Create RST file.
The playbook `playbook.yml` writes a RST file that can be used in
docs/docsite/rst. The usage of this helper is recommended but not
mandatory. You can stop reading here and update the RST file manually
if you don't want to use this helper.
## Run the playbook
If you want to generate the RST file by this helper fit the variables
in the playbook and the template to your needs. Then, run the play
```sh
shell> ansible-playbook playbook.yml
```
## Copy RST to docs/docsite/rst
Copy the RST file to `docs/docsite/rst` and remove it from this
directory.
## Update the checksums
Substitute the variables and run the below commands
```sh
shell> sha1sum {{ target_vars }} > {{ target_sha1 }}
shell> sha1sum {{ file_rst }} > {{ file_sha1 }}
```
## Playbook explained
The playbook includes the variable *tests* from the integration tests
and creates the RST file from the template. The playbook will
terminate if:
* The file with the variable *tests* was changed
* The RST file was changed
This means that this helper is probably not up to date.
### The file with the variable *tests* was changed
This means that somebody updated the integration tests. Review the
changes and update the template if needed. Update the checksum to pass
the integrity test. The playbook message provides you with the
command.
### The RST file was changed
This means that somebody updated the RST file manually. Review the
changes and update the template. Update the checksum to pass the
integrity test. The playbook message provides you with the
command. Make sure that the updated template will create identical RST
file. Only then apply your changes.

View File

@@ -1,110 +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
replace_keys
""""""""""""
Use the filter :ansplugin:`community.general.replace_keys#filter` if you have a list of dictionaries and want to replace certain keys.
.. note:: The output of the examples in this section use the YAML callback plugin. Quoting: "Ansible output that can be quite a bit easier to read than the default JSON formatting." See :ansplugin:`the documentation for the community.general.yaml callback plugin <community.general.yaml#callback>`.
Let us use the below list in the following examples:
.. code-block:: yaml
input:
{{ tests.0.input | to_yaml(indent=2) | indent(5) }}
{% for i in tests[0:1]|subelements('group') %}
* {{ i.1.d }}
.. code-block:: yaml+jinja
:emphasize-lines: 1-3
target:
{{ i.1.tt | to_yaml(indent=2) | indent(5) }}
result: "{{ lookup('file', target ~ '/templates/' ~ i.0.template) }}"
{% endfor %}
gives
.. code-block:: yaml
:emphasize-lines: 1-
result:
{{ tests.0.result | to_yaml(indent=2) | indent(5) }}
.. versionadded:: 9.1.0
* The results of the below examples 1-3 are all the same:
.. code-block:: yaml
:emphasize-lines: 1-
result:
{{ tests.1.result | to_yaml(indent=2) | indent(5) }}
{% for i in tests[1:2]|subelements('group') %}
{{ loop.index }}. {{ i.1.d }}
.. code-block:: yaml+jinja
:emphasize-lines: 1-4
mp: {{ i.1.mp }}
target:
{{ i.1.tt | to_yaml(indent=2) | indent(5) }}
result: "{{ lookup('file', target ~ '/templates/' ~ i.0.template) }}"
{% endfor %}
* The results of the below examples 4-5 are the same:
.. code-block:: yaml
:emphasize-lines: 1-
result:
{{ tests.2.result | to_yaml(indent=2) | indent(5) }}
{% for i in tests[2:3]|subelements('group') %}
{{ loop.index + 3 }}. {{ i.1.d }}
.. code-block:: yaml+jinja
:emphasize-lines: 1-3
mp: {{ i.1.mp }}
target:
{{ i.1.tt | to_yaml(indent=2) | indent(5) }}
result: "{{ lookup('file', target ~ '/templates/' ~ i.0.template) }}"
{% endfor %}
{% for i in tests[3:4]|subelements('group') %}
{{ loop.index + 5 }}. {{ i.1.d }}
.. code-block:: yaml
:emphasize-lines: 1-
input:
{{ i.0.input | to_yaml(indent=2) | indent(5) }}
.. code-block:: yaml+jinja
:emphasize-lines: 1-4
mp: {{ i.1.mp }}
target:
{{ i.1.tt | to_yaml(indent=2) | indent(5) }}
result: "{{ lookup('file', target ~ '/templates/' ~ i.0.template) }}"
gives
.. code-block:: yaml
:emphasize-lines: 1-
result:
{{ i.0.result | to_yaml(indent=2) | indent(5) }}
{% endfor %}

View File

@@ -1,79 +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
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Create docs REST files
# shell> ansible-playbook playbook.yml
#
# Proofread and copy created *.rst file into the directory
# docs/docsite/rst. Do not add *.rst in this directory to the version
# control.
#
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# community.general/docs/docsite/helper/replace_keys/playbook.yml
- name: Create RST file for docs/docsite/rst
hosts: localhost
gather_facts: false
vars:
plugin: replace_keys
plugin_type: filter
docs_path:
- filter_guide
- abstract_informations
- lists_of_dictionaries
file_base: "{{ (docs_path + [plugin]) | join('-') }}"
file_rst: ../../rst/{{ file_base }}.rst
file_sha1: "{{ plugin }}.rst.sha1"
target: "../../../../tests/integration/targets/{{ plugin_type }}_{{ plugin }}"
target_vars: "{{ target }}/vars/main/tests.yml"
target_sha1: tests.yml.sha1
tasks:
- name: Test integrity tests.yml
when:
- integrity | d(true) | bool
- lookup('file', target_sha1) != lookup('pipe', 'sha1sum ' ~ target_vars)
block:
- name: Changed tests.yml
ansible.builtin.debug:
msg: |
Changed {{ target_vars }}
Review the changes and update {{ target_sha1 }}
shell> sha1sum {{ target_vars }} > {{ target_sha1 }}
- name: Changed tests.yml end host
ansible.builtin.meta: end_play
- name: Test integrity RST file
when:
- integrity | d(true) | bool
- lookup('file', file_sha1) != lookup('pipe', 'sha1sum ' ~ file_rst)
block:
- name: Changed RST file
ansible.builtin.debug:
msg: |
Changed {{ file_rst }}
Review the changes and update {{ file_sha1 }}
shell> sha1sum {{ file_rst }} > {{ file_sha1 }}
- name: Changed RST file end host
ansible.builtin.meta: end_play
- name: Include target vars
include_vars:
file: "{{ target_vars }}"
- name: Create RST file
ansible.builtin.template:
src: "{{ file_base }}.rst.j2"
dest: "{{ file_base }}.rst"

View File

@@ -1 +0,0 @@
403f23c02ac02b1c3b611cb14f9b3ba59dc3f587 ../../rst/filter_guide-abstract_informations-lists_of_dictionaries-replace_keys.rst

View File

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

View File

@@ -1 +0,0 @@
2e54f3528c95cca746d5748f1ed7ada56ad0890e ../../../../tests/integration/targets/filter_replace_keys/vars/main/tests.yml

View File

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

View File

@@ -9,8 +9,6 @@ edit_on_github:
path_prefix: ''
extra_links:
- description: Ask for help
url: https://forum.ansible.com/c/help/6/none
- description: Submit a bug report
url: https://github.com/ansible-collections/community.general/issues/new?assignees=&labels=&template=bug_report.yml
- description: Request a feature
@@ -24,10 +22,6 @@ communication:
- topic: General usage and support questions
network: Libera
channel: '#ansible'
forums:
- topic: "Ansible Forum: General usage and support questions"
# The following URL directly points to the "Get Help" section
url: https://forum.ansible.com/c/help/6/none
- topic: "Ansible Forum: Discussions about the collection itself, not for specific modules or plugins"
# The following URL directly points to the "community-general" tag
url: https://forum.ansible.com/tag/community-general
mailing_lists:
- topic: Ansible Project List
url: https://groups.google.com/g/ansible-project

View File

@@ -1,151 +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
keep_keys
"""""""""
Use the filter :ansplugin:`community.general.keep_keys#filter` if you have a list of dictionaries and want to keep certain keys only.
.. note:: The output of the examples in this section use the YAML callback plugin. Quoting: "Ansible output that can be quite a bit easier to read than the default JSON formatting." See :ansplugin:`the documentation for the community.general.yaml callback plugin <community.general.yaml#callback>`.
Let us use the below list in the following examples:
.. code-block:: yaml
input:
- k0_x0: A0
k1_x1: B0
k2_x2: [C0]
k3_x3: foo
- k0_x0: A1
k1_x1: B1
k2_x2: [C1]
k3_x3: bar
* By default, match keys that equal any of the items in the target.
.. code-block:: yaml+jinja
:emphasize-lines: 1
target: ['k0_x0', 'k1_x1']
result: "{{ input | community.general.keep_keys(target=target) }}"
gives
.. code-block:: yaml
:emphasize-lines: 1-
result:
- {k0_x0: A0, k1_x1: B0}
- {k0_x0: A1, k1_x1: B1}
.. versionadded:: 9.1.0
* The results of the below examples 1-5 are all the same:
.. code-block:: yaml
:emphasize-lines: 1-
result:
- {k0_x0: A0, k1_x1: B0}
- {k0_x0: A1, k1_x1: B1}
1. Match keys that equal any of the items in the target.
.. code-block:: yaml+jinja
:emphasize-lines: 1,2
mp: equal
target: ['k0_x0', 'k1_x1']
result: "{{ input | community.general.keep_keys(target=target, matching_parameter=mp) }}"
2. Match keys that start with any of the items in the target.
.. code-block:: yaml+jinja
:emphasize-lines: 1,2
mp: starts_with
target: ['k0', 'k1']
result: "{{ input | community.general.keep_keys(target=target, matching_parameter=mp) }}"
3. Match keys that end with any of the items in target.
.. code-block:: yaml+jinja
:emphasize-lines: 1,2
mp: ends_with
target: ['x0', 'x1']
result: "{{ input | community.general.keep_keys(target=target, matching_parameter=mp) }}"
4. Match keys by the regex.
.. code-block:: yaml+jinja
:emphasize-lines: 1,2
mp: regex
target: ['^.*[01]_x.*$']
result: "{{ input | community.general.keep_keys(target=target, matching_parameter=mp) }}"
5. Match keys by the regex.
.. code-block:: yaml+jinja
:emphasize-lines: 1,2
mp: regex
target: ^.*[01]_x.*$
result: "{{ input | community.general.keep_keys(target=target, matching_parameter=mp) }}"
* The results of the below examples 6-9 are all the same:
.. code-block:: yaml
:emphasize-lines: 1-
result:
- {k0_x0: A0}
- {k0_x0: A1}
6. Match keys that equal the target.
.. code-block:: yaml+jinja
:emphasize-lines: 1,2
mp: equal
target: k0_x0
result: "{{ input | community.general.keep_keys(target=target, matching_parameter=mp) }}"
7. Match keys that start with the target.
.. code-block:: yaml+jinja
:emphasize-lines: 1,2
mp: starts_with
target: k0
result: "{{ input | community.general.keep_keys(target=target, matching_parameter=mp) }}"
8. Match keys that end with the target.
.. code-block:: yaml+jinja
:emphasize-lines: 1,2
mp: ends_with
target: x0
result: "{{ input | community.general.keep_keys(target=target, matching_parameter=mp) }}"
9. Match keys by the regex.
.. code-block:: yaml+jinja
:emphasize-lines: 1,2
mp: regex
target: ^.*0_x.*$
result: "{{ input | community.general.keep_keys(target=target, matching_parameter=mp) }}"

View File

@@ -1,159 +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
remove_keys
"""""""""""
Use the filter :ansplugin:`community.general.remove_keys#filter` if you have a list of dictionaries and want to remove certain keys.
.. note:: The output of the examples in this section use the YAML callback plugin. Quoting: "Ansible output that can be quite a bit easier to read than the default JSON formatting." See See :ansplugin:`the documentation for the community.general.yaml callback plugin <community.general.yaml#callback>`.
Let us use the below list in the following examples:
.. code-block:: yaml
input:
- k0_x0: A0
k1_x1: B0
k2_x2: [C0]
k3_x3: foo
- k0_x0: A1
k1_x1: B1
k2_x2: [C1]
k3_x3: bar
* By default, match keys that equal any of the items in the target.
.. code-block:: yaml+jinja
:emphasize-lines: 1
target: ['k0_x0', 'k1_x1']
result: "{{ input | community.general.remove_keys(target=target) }}"
gives
.. code-block:: yaml
:emphasize-lines: 1-
result:
- k2_x2: [C0]
k3_x3: foo
- k2_x2: [C1]
k3_x3: bar
.. versionadded:: 9.1.0
* The results of the below examples 1-5 are all the same:
.. code-block:: yaml
:emphasize-lines: 1-
result:
- k2_x2: [C0]
k3_x3: foo
- k2_x2: [C1]
k3_x3: bar
1. Match keys that equal any of the items in the target.
.. code-block:: yaml+jinja
:emphasize-lines: 1,2
mp: equal
target: ['k0_x0', 'k1_x1']
result: "{{ input | community.general.remove_keys(target=target, matching_parameter=mp) }}"
2. Match keys that start with any of the items in the target.
.. code-block:: yaml+jinja
:emphasize-lines: 1,2
mp: starts_with
target: ['k0', 'k1']
result: "{{ input | community.general.remove_keys(target=target, matching_parameter=mp) }}"
3. Match keys that end with any of the items in target.
.. code-block:: yaml+jinja
:emphasize-lines: 1,2
mp: ends_with
target: ['x0', 'x1']
result: "{{ input | community.general.remove_keys(target=target, matching_parameter=mp) }}"
4. Match keys by the regex.
.. code-block:: yaml+jinja
:emphasize-lines: 1,2
mp: regex
target: ['^.*[01]_x.*$']
result: "{{ input | community.general.remove_keys(target=target, matching_parameter=mp) }}"
5. Match keys by the regex.
.. code-block:: yaml+jinja
:emphasize-lines: 1,2
mp: regex
target: ^.*[01]_x.*$
result: "{{ input | community.general.remove_keys(target=target, matching_parameter=mp) }}"
* The results of the below examples 6-9 are all the same:
.. code-block:: yaml
:emphasize-lines: 1-
result:
- k1_x1: B0
k2_x2: [C0]
k3_x3: foo
- k1_x1: B1
k2_x2: [C1]
k3_x3: bar
6. Match keys that equal the target.
.. code-block:: yaml+jinja
:emphasize-lines: 1,2
mp: equal
target: k0_x0
result: "{{ input | community.general.remove_keys(target=target, matching_parameter=mp) }}"
7. Match keys that start with the target.
.. code-block:: yaml+jinja
:emphasize-lines: 1,2
mp: starts_with
target: k0
result: "{{ input | community.general.remove_keys(target=target, matching_parameter=mp) }}"
8. Match keys that end with the target.
.. code-block:: yaml+jinja
:emphasize-lines: 1,2
mp: ends_with
target: x0
result: "{{ input | community.general.remove_keys(target=target, matching_parameter=mp) }}"
9. Match keys by the regex.
.. code-block:: yaml+jinja
:emphasize-lines: 1,2
mp: regex
target: ^.*0_x.*$
result: "{{ input | community.general.remove_keys(target=target, matching_parameter=mp) }}"

View File

@@ -1,175 +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
replace_keys
""""""""""""
Use the filter :ansplugin:`community.general.replace_keys#filter` if you have a list of dictionaries and want to replace certain keys.
.. note:: The output of the examples in this section use the YAML callback plugin. Quoting: "Ansible output that can be quite a bit easier to read than the default JSON formatting." See :ansplugin:`the documentation for the community.general.yaml callback plugin <community.general.yaml#callback>`.
Let us use the below list in the following examples:
.. code-block:: yaml
input:
- k0_x0: A0
k1_x1: B0
k2_x2: [C0]
k3_x3: foo
- k0_x0: A1
k1_x1: B1
k2_x2: [C1]
k3_x3: bar
* By default, match keys that equal any of the attributes before.
.. code-block:: yaml+jinja
:emphasize-lines: 1-3
target:
- {after: a0, before: k0_x0}
- {after: a1, before: k1_x1}
result: "{{ input | community.general.replace_keys(target=target) }}"
gives
.. code-block:: yaml
:emphasize-lines: 1-
result:
- a0: A0
a1: B0
k2_x2: [C0]
k3_x3: foo
- a0: A1
a1: B1
k2_x2: [C1]
k3_x3: bar
.. versionadded:: 9.1.0
* The results of the below examples 1-3 are all the same:
.. code-block:: yaml
:emphasize-lines: 1-
result:
- a0: A0
a1: B0
k2_x2: [C0]
k3_x3: foo
- a0: A1
a1: B1
k2_x2: [C1]
k3_x3: bar
1. Replace keys that starts with any of the attributes before.
.. code-block:: yaml+jinja
:emphasize-lines: 1-4
mp: starts_with
target:
- {after: a0, before: k0}
- {after: a1, before: k1}
result: "{{ input | community.general.replace_keys(target=target, matching_parameter=mp) }}"
2. Replace keys that ends with any of the attributes before.
.. code-block:: yaml+jinja
:emphasize-lines: 1-4
mp: ends_with
target:
- {after: a0, before: x0}
- {after: a1, before: x1}
result: "{{ input | community.general.replace_keys(target=target, matching_parameter=mp) }}"
3. Replace keys that match any regex of the attributes before.
.. code-block:: yaml+jinja
:emphasize-lines: 1-4
mp: regex
target:
- {after: a0, before: ^.*0_x.*$}
- {after: a1, before: ^.*1_x.*$}
result: "{{ input | community.general.replace_keys(target=target, matching_parameter=mp) }}"
* The results of the below examples 4-5 are the same:
.. code-block:: yaml
:emphasize-lines: 1-
result:
- {X: foo}
- {X: bar}
4. If more keys match the same attribute before the last one will be used.
.. code-block:: yaml+jinja
:emphasize-lines: 1-3
mp: regex
target:
- {after: X, before: ^.*_x.*$}
result: "{{ input | community.general.replace_keys(target=target, matching_parameter=mp) }}"
5. If there are items with equal attribute before the first one will be used.
.. code-block:: yaml+jinja
:emphasize-lines: 1-3
mp: regex
target:
- {after: X, before: ^.*_x.*$}
- {after: Y, before: ^.*_x.*$}
result: "{{ input | community.general.replace_keys(target=target, matching_parameter=mp) }}"
6. If there are more matches for a key the first one will be used.
.. code-block:: yaml
:emphasize-lines: 1-
input:
- {aaa1: A, bbb1: B, ccc1: C}
- {aaa2: D, bbb2: E, ccc2: F}
.. code-block:: yaml+jinja
:emphasize-lines: 1-4
mp: starts_with
target:
- {after: X, before: a}
- {after: Y, before: aa}
result: "{{ input | community.general.replace_keys(target=target, matching_parameter=mp) }}"
gives
.. code-block:: yaml
:emphasize-lines: 1-
result:
- {X: A, bbb1: B, ccc1: C}
- {X: D, bbb2: E, ccc2: F}

View File

@@ -1,18 +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
.. _ansible_collections.community.general.docsite.filter_guide.filter_guide_abstract_informations.lists_of_dicts:
Lists of dictionaries
^^^^^^^^^^^^^^^^^^^^^
Filters to manage keys in a list of dictionaries:
.. toctree::
:maxdepth: 1
filter_guide-abstract_informations-lists_of_dictionaries-keep_keys
filter_guide-abstract_informations-lists_of_dictionaries-remove_keys
filter_guide-abstract_informations-lists_of_dictionaries-replace_keys

View File

@@ -11,7 +11,6 @@ Abstract transformations
filter_guide_abstract_informations_dictionaries
filter_guide_abstract_informations_grouping
filter_guide-abstract_informations-lists_of_dictionaries
filter_guide_abstract_informations_merging_lists_of_dictionaries
filter_guide_abstract_informations_lists_helper
filter_guide_abstract_informations_counting_elements_in_sequence

View File

@@ -1,499 +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
.. _ansible_collections.community.general.docsite.guide_cmdrunner:
Command Runner guide
====================
Introduction
^^^^^^^^^^^^
The ``ansible_collections.community.general.plugins.module_utils.cmd_runner`` module util provides the
``CmdRunner`` class to help execute external commands. The class is a wrapper around
the standard ``AnsibleModule.run_command()`` method, handling command arguments, localization setting,
output processing output, check mode, and other features.
It is even more useful when one command is used in multiple modules, so that you can define all options
in a module util file, and each module uses the same runner with different arguments.
For the sake of clarity, throughout this guide, unless otherwise specified, we use the term *option* when referring to
Ansible module options, and the term *argument* when referring to the command line arguments for the external command.
Quickstart
""""""""""
``CmdRunner`` defines a command and a set of coded instructions on how to format
the command-line arguments, in which specific order, for a particular execution.
It relies on ``ansible.module_utils.basic.AnsibleModule.run_command()`` to actually execute the command.
There are other features, see more details throughout this document.
To use ``CmdRunner`` you must start by creating an object. The example below is a simplified
version of the actual code in :ansplugin:`community.general.ansible_galaxy_install#module`:
.. code-block:: python
from ansible_collections.community.general.plugins.module_utils.cmd_runner import CmdRunner, cmd_runner_fmt
runner = CmdRunner(
module,
command="ansible-galaxy",
arg_formats=dict(
type=cmd_runner_fmt.as_func(lambda v: [] if v == 'both' else [v]),
galaxy_cmd=cmd_runner_fmt.as_list(),
upgrade=cmd_runner_fmt.as_bool("--upgrade"),
requirements_file=cmd_runner_fmt.as_opt_val('-r'),
dest=cmd_runner_fmt.as_opt_val('-p'),
force=cmd_runner_fmt.as_bool("--force"),
no_deps=cmd_runner_fmt.as_bool("--no-deps"),
version=cmd_runner_fmt.as_fixed("--version"),
name=cmd_runner_fmt.as_list(),
)
)
This is meant to be done once, then every time you need to execute the command you create a context and pass values as needed:
.. code-block:: python
# Run the command with these arguments, when values exist for them
with runner("type galaxy_cmd upgrade force no_deps dest requirements_file name", output_process=process) as ctx:
ctx.run(galaxy_cmd="install", upgrade=upgrade)
# version is fixed, requires no value
with runner("version") as ctx:
dummy, stdout, dummy = ctx.run()
# passes arg 'data' to AnsibleModule.run_command()
with runner("type name", data=stdin_data) as ctx:
dummy, stdout, dummy = ctx.run()
# Another way of expressing it
dummy, stdout, dummy = runner("version").run()
Note that you can pass values for the arguments when calling ``run()``, otherwise ``CmdRunner``
uses the module options with the exact same names to provide values for the runner arguments.
If no value is passed and no module option is found for the name specified, then an exception is raised, unless
the argument is using ``cmd_runner_fmt.as_fixed`` as format function like the ``version`` in the example above.
See more about it below.
In the first example, values of ``type``, ``force``, ``no_deps`` and others
are taken straight from the module, whilst ``galaxy_cmd`` and ``upgrade`` are
passed explicitly.
.. note::
It is not possible to automatically retrieve values of suboptions.
That generates a resulting command line similar to (example taken from the
output of an integration test):
.. code-block:: python
[
"<venv>/bin/ansible-galaxy",
"collection",
"install",
"--upgrade",
"-p",
"<collection-install-path>",
"netbox.netbox",
]
Argument formats
^^^^^^^^^^^^^^^^
As seen in the example, ``CmdRunner`` expects a parameter named ``arg_formats``
defining how to format each CLI named argument.
An "argument format" is nothing but a function to transform the value of a variable
into something formatted for the command line.
Argument format function
""""""""""""""""""""""""
An ``arg_format`` function is defined in the form similar to:
.. code-block:: python
def func(value):
return ["--some-param-name", value]
The parameter ``value`` can be of any type - although there are convenience
mechanisms to help handling sequence and mapping objects.
The result is expected to be of the type ``Sequence[str]`` type (most commonly
``list[str]`` or ``tuple[str]``), otherwise it is considered to be a ``str``,
and it is coerced into ``list[str]``.
This resulting sequence of strings is added to the command line when that
argument is actually used.
For example, if ``func`` returns:
- ``["nee", 2, "shruberries"]``, the command line adds arguments ``"nee" "2" "shruberries"``.
- ``2 == 2``, the command line adds argument ``True``.
- ``None``, the command line adds argument ``None``.
- ``[]``, the command line adds no command line argument for that particular argument.
Convenience format methods
""""""""""""""""""""""""""
In the same module as ``CmdRunner`` there is a class ``cmd_runner_fmt`` which
provides a set of convenience methods that return format functions for common cases.
In the first block of code in the `Quickstart`_ section you can see the importing of
that class:
.. code-block:: python
from ansible_collections.community.general.plugins.module_utils.cmd_runner import CmdRunner, cmd_runner_fmt
The same example shows how to make use of some of them in the instantiation of the ``CmdRunner`` object.
A description of each one of the convenience methods available and examples of how to use them is found below.
In these descriptions ``value`` refers to the single parameter passed to the formatting function.
- ``cmd_runner_fmt.as_list()``
This method does not receive any parameter, function returns ``value`` as-is.
- Creation:
``cmd_runner_fmt.as_list()``
- Examples:
+----------------------+---------------------+
| Value | Outcome |
+======================+=====================+
| ``["foo", "bar"]`` | ``["foo", "bar"]`` |
+----------------------+---------------------+
| ``"foobar"`` | ``["foobar"]`` |
+----------------------+---------------------+
- ``cmd_runner_fmt.as_bool()``
This method receives two different parameters: ``args_true`` and ``args_false``, latter being optional.
If the boolean evaluation of ``value`` is ``True``, the format function returns ``args_true``.
If the boolean evaluation is ``False``, then the function returns ``args_false`` if it was provided, or ``[]`` otherwise.
- Creation (one arg):
``cmd_runner_fmt.as_bool("--force")``
- Examples:
+------------+--------------------+
| Value | Outcome |
+============+====================+
| ``True`` | ``["--force"]`` |
+------------+--------------------+
| ``False`` | ``[]`` |
+------------+--------------------+
- Creation (two args, ``None`` treated as ``False``):
``cmd_runner_fmt.as_bool("--relax", "--dont-do-it")``
- Examples:
+------------+----------------------+
| Value | Outcome |
+============+======================+
| ``True`` | ``["--relax"]`` |
+------------+----------------------+
| ``False`` | ``["--dont-do-it"]`` |
+------------+----------------------+
| | ``["--dont-do-it"]`` |
+------------+----------------------+
- Creation (two args, ``None`` is ignored):
``cmd_runner_fmt.as_bool("--relax", "--dont-do-it", ignore_none=True)``
- Examples:
+------------+----------------------+
| Value | Outcome |
+============+======================+
| ``True`` | ``["--relax"]`` |
+------------+----------------------+
| ``False`` | ``["--dont-do-it"]`` |
+------------+----------------------+
| | ``[]`` |
+------------+----------------------+
- ``cmd_runner_fmt.as_bool_not()``
This method receives one parameter, which is returned by the function when the boolean evaluation
of ``value`` is ``False``.
- Creation:
``cmd_runner_fmt.as_bool_not("--no-deps")``
- Examples:
+-------------+---------------------+
| Value | Outcome |
+=============+=====================+
| ``True`` | ``[]`` |
+-------------+---------------------+
| ``False`` | ``["--no-deps"]`` |
+-------------+---------------------+
- ``cmd_runner_fmt.as_optval()``
This method receives one parameter ``arg``, the function returns the string concatenation
of ``arg`` and ``value``.
- Creation:
``cmd_runner_fmt.as_optval("-i")``
- Examples:
+---------------+---------------------+
| Value | Outcome |
+===============+=====================+
| ``3`` | ``["-i3"]`` |
+---------------+---------------------+
| ``foobar`` | ``["-ifoobar"]`` |
+---------------+---------------------+
- ``cmd_runner_fmt.as_opt_val()``
This method receives one parameter ``arg``, the function returns ``[arg, value]``.
- Creation:
``cmd_runner_fmt.as_opt_val("--name")``
- Examples:
+--------------+--------------------------+
| Value | Outcome |
+==============+==========================+
| ``abc`` | ``["--name", "abc"]`` |
+--------------+--------------------------+
- ``cmd_runner_fmt.as_opt_eq_val()``
This method receives one parameter ``arg``, the function returns the string of the form
``{arg}={value}``.
- Creation:
``cmd_runner_fmt.as_opt_eq_val("--num-cpus")``
- Examples:
+------------+-------------------------+
| Value | Outcome |
+============+=========================+
| ``10`` | ``["--num-cpus=10"]`` |
+------------+-------------------------+
- ``cmd_runner_fmt.as_fixed()``
This method receives one parameter ``arg``, the function expects no ``value`` - if one
is provided then it is ignored.
The function returns ``arg`` as-is.
- Creation:
``cmd_runner_fmt.as_fixed("--version")``
- Examples:
+---------+-----------------------+
| Value | Outcome |
+=========+=======================+
| | ``["--version"]`` |
+---------+-----------------------+
| 57 | ``["--version"]`` |
+---------+-----------------------+
- Note:
This is the only special case in which a value can be missing for the formatting function.
The example also comes from the code in `Quickstart`_.
In that case, the module has code to determine the command's version so that it can assert compatibility.
There is no *value* to be passed for that CLI argument.
- ``cmd_runner_fmt.as_map()``
This method receives one parameter ``arg`` which must be a dictionary, and an optional parameter ``default``.
The function returns the evaluation of ``arg[value]``.
If ``value not in arg``, then it returns ``default`` if defined, otherwise ``[]``.
- Creation:
``cmd_runner_fmt.as_map(dict(a=1, b=2, c=3), default=42)``
- Examples:
+---------------------+---------------+
| Value | Outcome |
+=====================+===============+
| ``"b"`` | ``["2"]`` |
+---------------------+---------------+
| ``"yabadabadoo"`` | ``["42"]`` |
+---------------------+---------------+
- Note:
If ``default`` is not specified, invalid values return an empty list, meaning they are silently ignored.
- ``cmd_runner_fmt.as_func()``
This method receives one parameter ``arg`` which is itself is a format function and it must abide by the rules described above.
- Creation:
``cmd_runner_fmt.as_func(lambda v: [] if v == 'stable' else ['--channel', '{0}'.format(v)])``
- Note:
The outcome for that depends entirely on the function provided by the developer.
Other features for argument formatting
""""""""""""""""""""""""""""""""""""""
Some additional features are available as decorators:
- ``cmd_runner_fmt.unpack args()``
This decorator unpacks the incoming ``value`` as a list of elements.
For example, in ``ansible_collections.community.general.plugins.module_utils.puppet``, it is used as:
.. code-block:: python
@cmd_runner_fmt.unpack_args
def execute_func(execute, manifest):
if execute:
return ["--execute", execute]
else:
return [manifest]
runner = CmdRunner(
module,
command=_prepare_base_cmd(),
path_prefix=_PUPPET_PATH_PREFIX,
arg_formats=dict(
# ...
_execute=cmd_runner_fmt.as_func(execute_func),
# ...
),
)
Then, in :ansplugin:`community.general.puppet#module` it is put to use with:
.. code-block:: python
with runner(args_order) as ctx:
rc, stdout, stderr = ctx.run(_execute=[p['execute'], p['manifest']])
- ``cmd_runner_fmt.unpack_kwargs()``
Conversely, this decorator unpacks the incoming ``value`` as a ``dict``-like object.
- ``cmd_runner_fmt.stack()``
This decorator assumes ``value`` is a sequence and concatenates the output
of the wrapped function applied to each element of the sequence.
For example, in :ansplugin:`community.general.django_check#module`, the argument format for ``database``
is defined as:
.. code-block:: python
arg_formats = dict(
# ...
database=cmd_runner_fmt.stack(cmd_runner_fmt.as_opt_val)("--database"),
# ...
)
When receiving a list ``["abc", "def"]``, the output is:
.. code-block:: python
["--database", "abc", "--database", "def"]
Command Runner
^^^^^^^^^^^^^^
Settings that can be passed to the ``CmdRunner`` constructor are:
- ``module: AnsibleModule``
Module instance. Mandatory parameter.
- ``command: str | list[str]``
Command to be executed. It can be a single string, the executable name, or a list
of strings containing the executable name as the first element and, optionally, fixed parameters.
Those parameters are used in all executions of the runner.
The *executable* pointed by this parameter (whether itself when ``str`` or its first element when ``list``) is
processed using ``AnsibleModule.get_bin_path()`` *unless* it is an absolute path or contains the character ``/``.
- ``arg_formats: dict``
Mapping of argument names to formatting functions.
- ``default_args_order: str``
As the name suggests, a default ordering for the arguments. When
this is passed, the context can be created without specifying ``args_order``. Defaults to ``()``.
- ``check_rc: bool``
When ``True``, if the return code from the command is not zero, the module exits
with an error. Defaults to ``False``.
- ``path_prefix: list[str]``
If the command being executed is installed in a non-standard directory path,
additional paths might be provided to search for the executable. Defaults to ``None``.
- ``environ_update: dict``
Pass additional environment variables to be set during the command execution.
Defaults to ``None``.
- ``force_lang: str``
It is usually important to force the locale to one specific value, so that responses are consistent and, therefore, parseable.
Please note that using this option (which is enabled by default) overwrites the environment variables ``LANGUAGE`` and ``LC_ALL``.
To disable this mechanism, set this parameter to ``None``.
In community.general 9.1.0 a special value ``auto`` was introduced for this parameter, with the effect
that ``CmdRunner`` then tries to determine the best parseable locale for the runtime.
It should become the default value in the future, but for the time being the default value is ``C``.
When creating a context, the additional settings that can be passed to the call are:
- ``args_order: str``
Establishes the order in which the arguments are rendered in the command line.
This parameter is mandatory unless ``default_args_order`` was provided to the runner instance.
- ``output_process: func``
Function to transform the output of the executable into different values or formats.
See examples in section below.
- ``check_mode_skip: bool``
Whether to skip the actual execution of the command when the module is in check mode.
Defaults to ``False``.
- ``check_mode_return: any``
If ``check_mode_skip=True``, then return this value instead.
- valid named arguments to ``AnsibleModule.run_command()``
Other than ``args``, any valid argument to ``run_command()`` can be passed when setting up the run context.
For example, ``data`` can be used to send information to the command's standard input.
Or ``cwd`` can be used to run the command inside a specific working directory.
Additionally, any other valid parameters for ``AnsibleModule.run_command()`` may be passed, but unexpected behavior
might occur if redefining options already present in the runner or its context creation. Use with caution.
Processing results
^^^^^^^^^^^^^^^^^^
As mentioned, ``CmdRunner`` uses ``AnsibleModule.run_command()`` to execute the external command,
and it passes the return value from that method back to caller. That means that,
by default, the result is going to be a tuple ``(rc, stdout, stderr)``.
If you need to transform or process that output, you can pass a function to the context,
as the ``output_process`` parameter. It must be a function like:
.. code-block:: python
def process(rc, stdout, stderr):
# do some magic
return processed_value # whatever that is
In that case, the return of ``run()`` is the ``processed_value`` returned by the function.
PythonRunner
^^^^^^^^^^^^
The ``PythonRunner`` class is a specialized version of ``CmdRunner``, geared towards the execution of
Python scripts. It features two extra and mutually exclusive parameters ``python`` and ``venv`` in its constructor:
.. code-block:: python
from ansible_collections.community.general.plugins.module_utils.python_runner import PythonRunner
from ansible_collections.community.general.plugins.module_utils.cmd_runner import cmd_runner_fmt
runner = PythonRunner(
module,
command=["-m", "django"],
arg_formats=dict(...),
python="python",
venv="/path/to/some/venv",
)
The default value for ``python`` is the string ``python``, and the for ``venv`` it is ``None``.
The command line produced by such a command with ``python="python3.12"`` is something like:
.. code-block:: shell
/usr/bin/python3.12 -m django <arg1> <arg2> ...
And the command line for ``venv="/work/venv"`` is like:
.. code-block:: shell
/work/venv/bin/python -m django <arg1> <arg2> ...
You may provide the value of the ``command`` argument as a string (in that case the string is used as a script name)
or as a list, in which case the elements of the list must be valid arguments for the Python interpreter, as in the example above.
See `Command line and environment <https://docs.python.org/3/using/cmdline.html>`_ for more details.
If the parameter ``python`` is an absolute path, or contains directory separators, such as ``/``, then it is used
as-is, otherwise the runtime ``PATH`` is searched for that command name.
Other than that, everything else works as in ``CmdRunner``.
.. versionadded:: 4.8.0

View File

@@ -1,74 +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
.. _ansible_collections.community.general.docsite.guide_deps:
``deps`` Guide
==============
Using ``deps``
^^^^^^^^^^^^^^
The ``ansible_collections.community.general.plugins.module_utils.deps`` module util simplifies
the importing of code as described in :ref:`Importing and using shared code <shared_code>`.
Please notice that ``deps`` is meant to be used specifically with Ansible modules, and not other types of plugins.
The same example from the Developer Guide would become:
.. code-block:: python
from ansible_collections.community.general.plugins.module_utils import deps
with deps.declare("foo"):
import foo
Then in ``main()``, just after the argspec (or anywhere in the code, for that matter), do
.. code-block:: python
deps.validate(module) # assuming module is a valid AnsibleModule instance
By default, ``deps`` will rely on ``ansible.module_utils.basic.missing_required_lib`` to generate
a message about a failing import. That function accepts parameters ``reason`` and ``url``, and
and so does ``deps```:
.. code-block:: python
with deps.declare("foo", reason="foo is needed to properly bar", url="https://foo.bar.io"):
import foo
If you would rather write a custom message instead of using ``missing_required_lib`` then do:
.. code-block:: python
with deps.declare("foo", msg="Custom msg explaining why foo is needed"):
import foo
``deps`` allows for multiple dependencies to be declared:
.. code-block:: python
with deps.declare("foo"):
import foo
with deps.declare("bar"):
import bar
with deps.declare("doe"):
import doe
By default, ``deps.validate()`` will check on all the declared dependencies, but if so desired,
they can be validated selectively by doing:
.. code-block:: python
deps.validate(module, "foo") # only validates the "foo" dependency
deps.validate(module, "doe:bar") # only validates the "doe" and "bar" dependencies
deps.validate(module, "-doe:bar") # validates all dependencies except "doe" and "bar"
.. versionadded:: 6.1.0

View File

@@ -1,547 +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
.. _ansible_collections.community.general.docsite.guide_modulehelper:
Module Helper guide
===================
Introduction
^^^^^^^^^^^^
Writing a module for Ansible is largely described in existing documentation.
However, a good part of that is boilerplate code that needs to be repeated every single time.
That is where ``ModuleHelper`` comes to assistance: a lot of that boilerplate code is done.
.. _ansible_collections.community.general.docsite.guide_modulehelper.quickstart:
Quickstart
""""""""""
See the `example from Ansible documentation <https://docs.ansible.com/ansible/latest/dev_guide/developing_modules_general.html#creating-a-module>`_
written with ``ModuleHelper``.
But bear in mind that it does not showcase all of MH's features:
.. code-block:: python
from ansible_collections.community.general.plugins.module_utils.module_helper import ModuleHelper
class MyTest(ModuleHelper):
module = dict(
argument_spec=dict(
name=dict(type='str', required=True),
new=dict(type='bool', required=False, default=False),
),
supports_check_mode=True,
)
use_old_vardict = False
def __run__(self):
self.vars.original_message = ''
self.vars.message = ''
if self.check_mode:
return
self.vars.original_message = self.vars.name
self.vars.message = 'goodbye'
self.changed = self.vars['new']
if self.vars.name == "fail me":
self.do_raise("You requested this to fail")
def main():
MyTest.execute()
if __name__ == '__main__':
main()
Module Helper
^^^^^^^^^^^^^
Introduction
""""""""""""
``ModuleHelper`` is a wrapper around the standard ``AnsibleModule``, providing extra features and conveniences.
The basic structure of a module using ``ModuleHelper`` is as shown in the
:ref:`ansible_collections.community.general.docsite.guide_modulehelper.quickstart`
section above, but there are more elements that will take part in it.
.. code-block:: python
from ansible_collections.community.general.plugins.module_utils.module_helper import ModuleHelper
class MyTest(ModuleHelper):
output_params = ()
change_params = ()
diff_params = ()
facts_name = None
facts_params = ()
use_old_vardict = True
mute_vardict_deprecation = False
module = dict(
argument_spec=dict(...),
# ...
)
After importing the ``ModuleHelper`` class, you need to declare your own class extending it.
.. seealso::
There is a variation called ``StateModuleHelper``, which builds on top of the features provided by MH.
See :ref:`ansible_collections.community.general.docsite.guide_modulehelper.statemh` below for more details.
The easiest way of specifying the module is to create the class variable ``module`` with a dictionary
containing the exact arguments that would be passed as parameters to ``AnsibleModule``.
If you prefer to create the ``AnsibleModule`` object yourself, just assign it to the ``module`` class variable.
MH also accepts a parameter ``module`` in its constructor, if that parameter is used used,
then it will override the class variable. The parameter can either be ``dict`` or ``AnsibleModule`` as well.
Beyond the definition of the module, there are other variables that can be used to control aspects
of MH's behavior. These variables should be set at the very beginning of the class, and their semantics are
explained through this document.
The main logic of MH happens in the ``ModuleHelper.run()`` method, which looks like:
.. code-block:: python
@module_fails_on_exception
def run(self):
self.__init_module__()
self.__run__()
self.__quit_module__()
output = self.output
if 'failed' not in output:
output['failed'] = False
self.module.exit_json(changed=self.has_changed(), **output)
The method ``ModuleHelper.__run__()`` must be implemented by the module and most
modules will be able to perform their actions implementing only that MH method.
However, in some cases, you might want to execute actions before or after the main tasks, in which cases
you should implement ``ModuleHelper.__init_module__()`` and ``ModuleHelper.__quit_module__()`` respectively.
Note that the output comes from ``self.output``, which is a ``@property`` method.
By default, that property will collect all the variables that are marked for output and return them in a dictionary with their values.
Moreover, the default ``self.output`` will also handle Ansible ``facts`` and *diff mode*.
Also note the changed status comes from ``self.has_changed()``, which is usually calculated from variables that are marked
to track changes in their content.
.. seealso::
More details in sections
:ref:`ansible_collections.community.general.docsite.guide_modulehelper.paramvaroutput` and
:ref:`ansible_collections.community.general.docsite.guide_modulehelper.changes` below.
.. seealso::
See more about the decorator
:ref:`ansible_collections.community.general.docsite.guide_modulehelper.modulefailsdeco` below.
Another way to write the example from the
:ref:`ansible_collections.community.general.docsite.guide_modulehelper.quickstart`
would be:
.. code-block:: python
def __init_module__(self):
self.vars.original_message = ''
self.vars.message = ''
def __run__(self):
if self.check_mode:
return
self.vars.original_message = self.vars.name
self.vars.message = 'goodbye'
self.changed = self.vars['new']
def __quit_module__(self):
if self.vars.name == "fail me":
self.do_raise("You requested this to fail")
Notice that there are no calls to ``module.exit_json()`` nor ``module.fail_json()``: if the module fails, raise an exception.
You can use the convenience method ``self.do_raise()`` or raise the exception as usual in Python to do that.
If no exception is raised, then the module succeeds.
.. seealso::
See more about exceptions in section
:ref:`ansible_collections.community.general.docsite.guide_modulehelper.exceptions` below.
Ansible modules must have a ``main()`` function and the usual test for ``'__main__'``. When using MH that should look like:
.. code-block:: python
def main():
MyTest.execute()
if __name__ == '__main__':
main()
The class method ``execute()`` is nothing more than a convenience shorcut for:
.. code-block:: python
m = MyTest()
m.run()
Optionally, an ``AnsibleModule`` may be passed as parameter to ``execute()``.
.. _ansible_collections.community.general.docsite.guide_modulehelper.paramvaroutput:
Parameters, variables, and output
"""""""""""""""""""""""""""""""""
All the parameters automatically become variables in the ``self.vars`` attribute, which is of the ``VarDict`` type.
By using ``self.vars``, you get a central mechanism to access the parameters but also to expose variables as return values of the module.
As described in :ref:`ansible_collections.community.general.docsite.guide_vardict`, variables in ``VarDict`` have metadata associated to them.
One of the attributes in that metadata marks the variable for output, and MH makes use of that to generate the module's return values.
.. important::
The ``VarDict`` feature described was introduced in community.general 7.1.0, but there was a first
implementation of it embedded within ``ModuleHelper``.
That older implementation is now deprecated and will be removed in community.general 11.0.0.
After community.general 7.1.0, MH modules generate a deprecation message about *using the old VarDict*.
There are two ways to prevent that from happening:
#. Set ``mute_vardict_deprecation = True`` and the deprecation will be silenced. If the module still uses the old ``VarDict``,
it will not be able to update to community.general 11.0.0 (Spring 2026) upon its release.
#. Set ``use_old_vardict = False`` to make the MH module use the new ``VarDict`` immediatelly.
The new ``VarDict`` and its use is documented and this is the recommended way to handle this.
.. code-block:: python
class MyTest(ModuleHelper):
use_old_vardict = False
mute_vardict_deprecation = True
...
These two settings are mutually exclusive, but that is not enforced and the behavior when setting both is not specified.
Contrary to new variables created in ``VarDict``, module parameters are not set for output by default.
If you want to include some module parameters in the output, list them in the ``output_params`` class variable.
.. code-block:: python
class MyTest(ModuleHelper):
output_params = ('state', 'name')
...
Another neat feature provided by MH by using ``VarDict`` is the automatic tracking of changes when setting the metadata ``change=True``.
Again, to enable this feature for module parameters, you must list them in the ``change_params`` class variable.
.. code-block:: python
class MyTest(ModuleHelper):
# example from community.general.xfconf
change_params = ('value', )
...
.. seealso::
See more about this in
:ref:`ansible_collections.community.general.docsite.guide_modulehelper.changes` below.
Similarly, if you want to use Ansible's diff mode, you can set the metadata ``diff=True`` and ``diff_params`` for module parameters.
With that, MH will automatically generate the diff output for variables that have changed.
.. code-block:: python
class MyTest(ModuleHelper):
diff_params = ('value', )
def __run__(self):
# example from community.general.gio_mime
self.vars.set_meta("handler", initial_value=gio_mime_get(self.runner, self.vars.mime_type), diff=True, change=True)
Moreover, if a module is set to return *facts* instead of return values, then again use the metadata ``fact=True`` and ``fact_params`` for module parameters.
Additionally, you must specify ``facts_name``, as in:
.. code-block:: python
class VolumeFacts(ModuleHelper):
facts_name = 'volume_facts'
def __init_module__(self):
self.vars.set("volume", 123, fact=True)
That generates an Ansible fact like:
.. code-block:: yaml+jinja
- name: Obtain volume facts
some.collection.volume_facts:
# parameters
- name: Print volume facts
debug:
msg: Volume fact is {{ ansible_facts.volume_facts.volume }}
.. important::
If ``facts_name`` is not set, the module does not generate any facts.
.. _ansible_collections.community.general.docsite.guide_modulehelper.changes:
Handling changes
""""""""""""""""
In MH there are many ways to indicate change in the module execution. Here they are:
Tracking changes in variables
-----------------------------
As explained above, you can enable change tracking in any number of variables in ``self.vars``.
By the end of the module execution, if any of those variables has a value different then the first value assigned to them,
then that will be picked up by MH and signalled as changed at the module output.
See the example below to learn how you can enabled change tracking in variables:
.. code-block:: python
# using __init_module__() as example, it works the same in __run__() and __quit_module__()
def __init_module__(self):
# example from community.general.ansible_galaxy_install
self.vars.set("new_roles", {}, change=True)
# example of "hidden" variable used only to track change in a value from community.general.gconftool2
self.vars.set('_value', self.vars.previous_value, output=False, change=True)
# enable change-tracking without assigning value
self.vars.set_meta("new_roles", change=True)
# if you must forcibly set an initial value to the variable
self.vars.set_meta("new_roles", initial_value=[])
...
If the end value of any variable marked ``change`` is different from its initial value, then MH will return ``changed=True``.
Indicating changes with ``changed``
-----------------------------------
If you want to indicate change directly in the code, then use the ``self.changed`` property in MH.
Beware that this is a ``@property`` method in MH, with both a *getter* and a *setter*.
By default, that hidden field is set to ``False``.
Effective change
----------------
The effective outcome for the module is determined in the ``self.has_changed()`` method, and it consists of the logical *OR* operation
between ``self.changed`` and the change calculated from ``self.vars``.
.. _ansible_collections.community.general.docsite.guide_modulehelper.exceptions:
Exceptions
""""""""""
In MH, instead of calling ``module.fail_json()`` you can just raise an exception.
The output variables are collected the same way they would be for a successful execution.
However, you can set output variables specifically for that exception, if you so choose.
.. code-block:: python
from ansible_collections.community.general.plugins.module_utils.module_helper import ModuleHelperException
def __init_module__(self):
if not complex_validation():
self.do_raise("Validation failed!")
# Or passing output variables
awesomeness = calculate_awesomeness()
if awesomeness > 1000:
self.do_raise("Over awesome, I cannot handle it!", update_output={"awesomeness": awesomeness})
# which is just a convenience shortcut for
raise ModuleHelperException("...", update_output={...})
All exceptions derived from ``Exception`` are captured and translated into a ``fail_json()`` call.
However, if you do want to call ``self.module.fail_json()`` yourself it will work,
just keep in mind that there will be no automatic handling of output variables in that case.
Behind the curtains, all ``do_raise()`` does is to raise a ``ModuleHelperException``.
If you want to create specialized error handling for your code, the best way is to extend that clas and raise it when needed.
.. _ansible_collections.community.general.docsite.guide_modulehelper.statemh:
StateModuleHelper
^^^^^^^^^^^^^^^^^
Many modules use a parameter ``state`` that effectively controls the exact action performed by the module, such as
``state=present`` or ``state=absent`` for installing or removing packages.
By using ``StateModuleHelper`` you can make your code like the excerpt from the ``gconftool2`` below:
.. code-block:: python
from ansible_collections.community.general.plugins.module_utils.module_helper import StateModuleHelper
class GConftool(StateModuleHelper):
...
module = dict(
...
)
use_old_vardict = False
def __init_module__(self):
self.runner = gconftool2_runner(self.module, check_rc=True)
...
self.vars.set('previous_value', self._get(), fact=True)
self.vars.set('value_type', self.vars.value_type)
self.vars.set('_value', self.vars.previous_value, output=False, change=True)
self.vars.set_meta('value', initial_value=self.vars.previous_value)
self.vars.set('playbook_value', self.vars.value, fact=True)
...
def state_absent(self):
with self.runner("state key", output_process=self._make_process(False)) as ctx:
ctx.run()
self.vars.set('run_info', ctx.run_info, verbosity=4)
self.vars.set('new_value', None, fact=True)
self.vars._value = None
def state_present(self):
with self.runner("direct config_source value_type state key value", output_process=self._make_process(True)) as ctx:
ctx.run()
self.vars.set('run_info', ctx.run_info, verbosity=4)
self.vars.set('new_value', self._get(), fact=True)
self.vars._value = self.vars.new_value
Note that the method ``__run__()`` is implemented in ``StateModuleHelper``, all you need to implement are the methods ``state_<state_value>``.
In the example above, :ansplugin:`community.general.gconftool2#module` only has two states, ``present`` and ``absent``, thus, ``state_present()`` and ``state_absent()``.
If the controlling parameter is not called ``state``, like in :ansplugin:`community.general.jira#module` module, just let SMH know about it:
.. code-block:: python
class JIRA(StateModuleHelper):
state_param = 'operation'
def operation_create(self):
...
def operation_search(self):
...
Lastly, if the module is called with ``state=somevalue`` and the method ``state_somevalue``
is not implemented, SMH will resort to call a method called ``__state_fallback__()``.
By default, this method will raise a ``ValueError`` indicating the method was not found.
Naturally, you can override that method to write a default implementation, as in :ansplugin:`community.general.locale_gen#module`:
.. code-block:: python
def __state_fallback__(self):
if self.vars.state_tracking == self.vars.state:
return
if self.vars.ubuntu_mode:
self.apply_change_ubuntu(self.vars.state, self.vars.name)
else:
self.apply_change(self.vars.state, self.vars.name)
That module has only the states ``present`` and ``absent`` and the code for both is the one in the fallback method.
.. note::
The name of the fallback method **does not change** if you set a different value of ``state_param``.
Other Conveniences
^^^^^^^^^^^^^^^^^^
Delegations to AnsibleModule
""""""""""""""""""""""""""""
The MH properties and methods below are delegated as-is to the underlying ``AnsibleModule`` instance in ``self.module``:
- ``check_mode``
- ``get_bin_path()``
- ``warn()``
- ``deprecate()``
Additionally, MH will also delegate:
- ``diff_mode`` to ``self.module._diff``
- ``verbosity`` to ``self.module._verbosity``
Decorators
""""""""""
The following decorators should only be used within ``ModuleHelper`` class.
@cause_changes
--------------
This decorator will control whether the outcome of the method will cause the module to signal change in its output.
If the method completes without raising an exception it is considered to have succeeded, otherwise, it will have failed.
The decorator has a parameter ``when`` that accepts three different values: ``success``, ``failure``, and ``always``.
There are also two legacy parameters, ``on_success`` and ``on_failure``, that will be deprecated, so do not use them.
The value of ``changed`` in the module output will be set to ``True``:
- ``when="success"`` and the method completes without raising an exception.
- ``when="failure"`` and the method raises an exception.
- ``when="always"``, regardless of the method raising an exception or not.
.. code-block:: python
from ansible_collections.community.general.plugins.module_utils.module_helper import cause_changes
# adapted excerpt from the community.general.jira module
class JIRA(StateModuleHelper):
@cause_changes(when="success")
def operation_create(self):
...
If ``when`` has a different value or no parameters are specificied, the decorator will have no effect whatsoever.
.. _ansible_collections.community.general.docsite.guide_modulehelper.modulefailsdeco:
@module_fails_on_exception
--------------------------
In a method using this decorator, if an exception is raised, the text message of that exception will be captured
by the decorator and used to call ``self.module.fail_json()``.
In most of the cases there will be no need to use this decorator, because ``ModuleHelper.run()`` already uses it.
@check_mode_skip
----------------
If the module is running in check mode, this decorator will prevent the method from executing.
The return value in that case is ``None``.
.. code-block:: python
from ansible_collections.community.general.plugins.module_utils.module_helper import check_mode_skip
# adapted excerpt from the community.general.locale_gen module
class LocaleGen(StateModuleHelper):
@check_mode_skip
def __state_fallback__(self):
...
@check_mode_skip_returns
------------------------
This decorator is similar to the previous one, but the developer can control the return value for the method when running in check mode.
It is used with one of two parameters. One is ``callable`` and the return value in check mode will be ``callable(self, *args, **kwargs)``,
where ``self`` is the ``ModuleHelper`` instance and the union of ``args`` and ``kwargs`` will contain all the parameters passed to the method.
The other option is to use the parameter ``value``, in which case the method will return ``value`` when in check mode.
References
^^^^^^^^^^
- `Ansible Developer Guide <https://docs.ansible.com/ansible/latest/dev_guide/index.html>`_
- `Creating a module <https://docs.ansible.com/ansible/latest/dev_guide/developing_modules_general.html#creating-a-module>`_
- `Returning ansible facts <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#ansible-facts>`_
- :ref:`ansible_collections.community.general.docsite.guide_vardict`
.. versionadded:: 3.1.0

View File

@@ -1,176 +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
.. _ansible_collections.community.general.docsite.guide_vardict:
VarDict Guide
=============
Introduction
^^^^^^^^^^^^
The ``ansible_collections.community.general.plugins.module_utils.vardict`` module util provides the
``VarDict`` class to help manage the module variables. That class is a container for module variables,
especially the ones for which the module must keep track of state changes, and the ones that should
be published as return values.
Each variable has extra behaviors controlled by associated metadata, simplifying the generation of
output values from the module.
Quickstart
""""""""""
The simplest way of using ``VarDict`` is:
.. code-block:: python
from ansible_collections.community.general.plugins.module_utils.vardict import VarDict
Then in ``main()``, or any other function called from there:
.. code-block:: python
vars = VarDict()
# Next 3 statements are equivalent
vars.abc = 123
vars["abc"] = 123
vars.set("abc", 123)
vars.xyz = "bananas"
vars.ghi = False
And by the time the module is about to exit:
.. code-block:: python
results = vars.output()
module.exit_json(**results)
That makes the return value of the module:
.. code-block:: javascript
{
"abc": 123,
"xyz": "bananas",
"ghi": false
}
Metadata
""""""""
The metadata values associated with each variable are:
- ``output: bool`` - marks the variable for module output as a module return value.
- ``fact: bool`` - marks the variable for module output as an Ansible fact.
- ``verbosity: int`` - sets the minimum level of verbosity for which the variable will be included in the output.
- ``change: bool`` - controls the detection of changes in the variable value.
- ``initial_value: any`` - when using ``change`` and need to forcefully set an intial value to the variable.
- ``diff: bool`` - used along with ``change``, this generates an Ansible-style diff ``dict``.
See the sections below for more details on how to use the metadata.
Using VarDict
^^^^^^^^^^^^^
Basic Usage
"""""""""""
As shown above, variables can be accessed using the ``[]`` operator, as in a ``dict`` object,
and also as an object attribute, such as ``vars.abc``. The form using the ``set()``
method is special in the sense that you can use it to set metadata values:
.. code-block:: python
vars.set("abc", 123, output=False)
vars.set("abc", 123, output=True, change=True)
Another way to set metadata after the variables have been created is:
.. code-block:: python
vars.set_meta("abc", output=False)
vars.set_meta("abc", output=True, change=True, diff=True)
You can use either operator and attribute forms to access the value of the variable. Other ways to
access its value and its metadata are:
.. code-block:: python
print("abc value = {0}".format(vars.var("abc")["value"])) # get the value
print("abc output? {0}".format(vars.get_meta("abc")["output"])) # get the metadata like this
The names of methods, such as ``set``, ``get_meta``, ``output`` amongst others, are reserved and
cannot be used as variable names. If you try to use a reserved name a ``ValueError`` exception
is raised with the message "Name <var> is reserved".
Generating output
"""""""""""""""""
By default, every variable create will be enable for output with minimum verbosity set to zero, in
other words, they will always be in the output by default.
You can control that when creating the variable for the first time or later in the code:
.. code-block:: python
vars.set("internal", x + 4, output=False)
vars.set_meta("internal", output=False)
You can also set the verbosity of some variable, like:
.. code-block:: python
vars.set("abc", x + 4)
vars.set("debug_x", x, verbosity=3)
results = vars.output(module._verbosity)
module.exit_json(**results)
If the module was invoked with verbosity lower than 3, then the output will only contain
the variable ``abc``. If running at higher verbosity, as in ``ansible-playbook -vvv``,
then the output will also contain ``debug_x``.
Generating facts is very similar to regular output, but variables are not marked as facts by default.
.. code-block:: python
vars.set("modulefact", x + 4, fact=True)
vars.set("debugfact", x, fact=True, verbosity=3)
results = vars.output(module._verbosity)
results["ansible_facts"] = {"module_name": vars.facts(module._verbosity)}
module.exit_json(**results)
Handling change
"""""""""""""""
You can use ``VarDict`` to determine whether variables have had their values changed.
.. code-block:: python
vars.set("abc", 42, change=True)
vars.abc = 90
results = vars.output()
results["changed"] = vars.has_changed
module.exit_json(**results)
If tracking changes in variables, you may want to present the difference between the initial and the final
values of it. For that, you want to use:
.. code-block:: python
vars.set("abc", 42, change=True, diff=True)
vars.abc = 90
results = vars.output()
results["changed"] = vars.has_changed
results["diff"] = vars.diff()
module.exit_json(**results)
.. versionadded:: 7.1.0

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -22,33 +22,25 @@ class ActionModule(ActionBase):
_VALID_ARGS = frozenset(('path', 'state', 'table', 'noflush', 'counters', 'modprobe', 'ip_version', 'wait'))
DEFAULT_SUDOABLE = True
@staticmethod
def msg_error__async_and_poll_not_zero(task_poll, task_async, max_timeout):
return (
"This module doesn't support async>0 and poll>0 when its 'state' param "
"is set to 'restored'. To enable its rollback feature (that needs the "
"module to run asynchronously on the remote), please set task attribute "
f"'poll' (={task_poll}) to 0, and 'async' (={task_async}) to a value >2 and not greater than "
f"'ansible_timeout' (={max_timeout}) (recommended).")
@staticmethod
def msg_warning__no_async_is_no_rollback(task_poll, task_async, max_timeout):
return (
"Attempts to restore iptables state without rollback in case of mistake "
"may lead the ansible controller to loose access to the hosts and never "
"regain it before fixing firewall rules through a serial console, or any "
f"other way except SSH. Please set task attribute 'poll' (={task_poll}) to 0, and "
f"'async' (={task_async}) to a value >2 and not greater than 'ansible_timeout' (={max_timeout}) "
"(recommended).")
@staticmethod
def msg_warning__async_greater_than_timeout(task_poll, task_async, max_timeout):
return (
"You attempt to restore iptables state with rollback in case of mistake, "
"but with settings that will lead this rollback to happen AFTER that the "
"controller will reach its own timeout. Please set task attribute 'poll' "
f"(={task_poll}) to 0, and 'async' (={task_async}) to a value >2 and not greater than "
f"'ansible_timeout' (={max_timeout}) (recommended).")
MSG_ERROR__ASYNC_AND_POLL_NOT_ZERO = (
"This module doesn't support async>0 and poll>0 when its 'state' param "
"is set to 'restored'. To enable its rollback feature (that needs the "
"module to run asynchronously on the remote), please set task attribute "
"'poll' (=%s) to 0, and 'async' (=%s) to a value >2 and not greater than "
"'ansible_timeout' (=%s) (recommended).")
MSG_WARNING__NO_ASYNC_IS_NO_ROLLBACK = (
"Attempts to restore iptables state without rollback in case of mistake "
"may lead the ansible controller to loose access to the hosts and never "
"regain it before fixing firewall rules through a serial console, or any "
"other way except SSH. Please set task attribute 'poll' (=%s) to 0, and "
"'async' (=%s) to a value >2 and not greater than 'ansible_timeout' (=%s) "
"(recommended).")
MSG_WARNING__ASYNC_GREATER_THAN_TIMEOUT = (
"You attempt to restore iptables state with rollback in case of mistake, "
"but with settings that will lead this rollback to happen AFTER that the "
"controller will reach its own timeout. Please set task attribute 'poll' "
"(=%s) to 0, and 'async' (=%s) to a value >2 and not greater than "
"'ansible_timeout' (=%s) (recommended).")
def _async_result(self, async_status_args, task_vars, timeout):
'''
@@ -96,25 +88,21 @@ class ActionModule(ActionBase):
max_timeout = self._connection._play_context.timeout
module_args = self._task.args
async_status_args = {}
starter_cmd = None
confirm_cmd = None
if module_args.get('state', None) == 'restored':
if not wrap_async:
if not check_mode:
display.warning(self.msg_error__async_and_poll_not_zero(
display.warning(self.MSG_WARNING__NO_ASYNC_IS_NO_ROLLBACK % (
task_poll,
task_async,
max_timeout))
elif task_poll:
raise AnsibleActionFail(self.msg_warning__no_async_is_no_rollback(
raise AnsibleActionFail(self.MSG_ERROR__ASYNC_AND_POLL_NOT_ZERO % (
task_poll,
task_async,
max_timeout))
else:
if task_async > max_timeout and not check_mode:
display.warning(self.msg_warning__async_greater_than_timeout(
display.warning(self.MSG_WARNING__ASYNC_GREATER_THAN_TIMEOUT % (
task_poll,
task_async,
max_timeout))
@@ -127,10 +115,10 @@ class ActionModule(ActionBase):
# remote and local sides (if not the same, make the loop
# longer on the controller); and set a backup file path.
module_args['_timeout'] = task_async
module_args['_back'] = f'{async_dir}/iptables.state'
module_args['_back'] = '%s/iptables.state' % async_dir
async_status_args = dict(mode='status')
confirm_cmd = f"rm -f {module_args['_back']}"
starter_cmd = f"touch {module_args['_back']}.starter"
confirm_cmd = 'rm -f %s' % module_args['_back']
starter_cmd = 'touch %s.starter' % module_args['_back']
remaining_time = max(task_async, max_timeout)
# do work!

View File

@@ -18,10 +18,6 @@ from ansible.utils.display import Display
display = Display()
def fmt(mapping, key):
return to_native(mapping[key]).strip()
class TimedOutException(Exception):
pass
@@ -88,26 +84,31 @@ class ActionModule(ActionBase):
def get_distribution(self, task_vars):
# FIXME: only execute the module if we don't already have the facts we need
distribution = {}
display.debug(f'{self._task.action}: running setup module to get distribution')
display.debug('{action}: running setup module to get distribution'.format(action=self._task.action))
module_output = self._execute_module(
task_vars=task_vars,
module_name='ansible.legacy.setup',
module_args={'gather_subset': 'min'})
try:
if module_output.get('failed', False):
raise AnsibleError(f"Failed to determine system distribution. {fmt(module_output, 'module_stdout')}, {fmt(module_output, 'module_stderr')}")
raise AnsibleError('Failed to determine system distribution. {0}, {1}'.format(
to_native(module_output['module_stdout']).strip(),
to_native(module_output['module_stderr']).strip()))
distribution['name'] = module_output['ansible_facts']['ansible_distribution'].lower()
distribution['version'] = to_text(
module_output['ansible_facts']['ansible_distribution_version'].split('.')[0])
distribution['family'] = to_text(module_output['ansible_facts']['ansible_os_family'].lower())
display.debug(f"{self._task.action}: distribution: {distribution}")
display.debug("{action}: distribution: {dist}".format(action=self._task.action, dist=distribution))
return distribution
except KeyError as ke:
raise AnsibleError(f'Failed to get distribution information. Missing "{ke.args[0]}" in output.')
raise AnsibleError('Failed to get distribution information. Missing "{0}" in output.'.format(ke.args[0]))
def get_shutdown_command(self, task_vars, distribution):
def find_command(command, find_search_paths):
display.debug(f'{self._task.action}: running find module looking in {find_search_paths} to get path for "{command}"')
display.debug('{action}: running find module looking in {paths} to get path for "{command}"'.format(
action=self._task.action,
command=command,
paths=find_search_paths))
find_result = self._execute_module(
task_vars=task_vars,
# prevent collection search by calling with ansible.legacy (still allows library/ override of find)
@@ -129,37 +130,42 @@ class ActionModule(ActionBase):
if is_string(search_paths):
search_paths = [search_paths]
# Error if we didn't get a list
err_msg = "'search_paths' must be a string or flat list of strings, got {0}"
try:
incorrect_type = any(not is_string(x) for x in search_paths)
if not isinstance(search_paths, list) or incorrect_type:
raise TypeError
except TypeError:
# Error if we didn't get a list
err_msg = f"'search_paths' must be a string or flat list of strings, got {search_paths}"
raise AnsibleError(err_msg)
raise AnsibleError(err_msg.format(search_paths))
full_path = find_command(shutdown_bin, search_paths) # find the path to the shutdown command
if not full_path: # if we could not find the shutdown command
# tell the user we will try with systemd
display.vvv(f'Unable to find command "{shutdown_bin}" in search paths: {search_paths}, will attempt a shutdown using systemd directly.')
display.vvv('Unable to find command "{0}" in search paths: {1}, will attempt a shutdown using systemd '
'directly.'.format(shutdown_bin, search_paths)) # tell the user we will try with systemd
systemctl_search_paths = ['/bin', '/usr/bin']
full_path = find_command('systemctl', systemctl_search_paths) # find the path to the systemctl command
if not full_path: # if we couldn't find systemctl
raise AnsibleError(
f'Could not find command "{shutdown_bin}" in search paths: {search_paths} or systemctl'
f' command in search paths: {systemctl_search_paths}, unable to shutdown.') # we give up here
'Could not find command "{0}" in search paths: {1} or systemctl command in search paths: {2}, unable to shutdown.'.
format(shutdown_bin, search_paths, systemctl_search_paths)) # we give up here
else:
return f"{full_path[0]} poweroff" # done, since we cannot use args with systemd shutdown
return "{0} poweroff".format(full_path[0]) # done, since we cannot use args with systemd shutdown
# systemd case taken care of, here we add args to the command
args = self._get_value_from_facts('SHUTDOWN_COMMAND_ARGS', distribution, 'DEFAULT_SHUTDOWN_COMMAND_ARGS')
# Convert seconds to minutes. If less that 60, set it to 0.
delay_sec = self.delay
shutdown_message = self._task.args.get('msg', self.DEFAULT_SHUTDOWN_MESSAGE)
af = args.format(delay_sec=delay_sec, delay_min=delay_sec // 60, message=shutdown_message)
return f'{full_path[0]} {af}'
return '{0} {1}'. \
format(
full_path[0],
args.format(
delay_sec=delay_sec,
delay_min=delay_sec // 60,
message=shutdown_message
)
)
def perform_shutdown(self, task_vars, distribution):
result = {}
@@ -168,8 +174,9 @@ class ActionModule(ActionBase):
self.cleanup(force=True)
try:
display.vvv(f"{self._task.action}: shutting down server...")
display.debug(f"{self._task.action}: shutting down server with command '{shutdown_command_exec}'")
display.vvv("{action}: shutting down server...".format(action=self._task.action))
display.debug("{action}: shutting down server with command '{command}'".
format(action=self._task.action, command=shutdown_command_exec))
if self._play_context.check_mode:
shutdown_result['rc'] = 0
else:
@@ -177,13 +184,16 @@ class ActionModule(ActionBase):
except AnsibleConnectionFailure as e:
# If the connection is closed too quickly due to the system being shutdown, carry on
display.debug(
f'{self._task.action}: AnsibleConnectionFailure caught and handled: {e}')
'{action}: AnsibleConnectionFailure caught and handled: {error}'.format(action=self._task.action,
error=to_text(e)))
shutdown_result['rc'] = 0
if shutdown_result['rc'] != 0:
result['failed'] = True
result['shutdown'] = False
result['msg'] = f"Shutdown command failed. Error was {fmt(shutdown_result, 'stdout')}, {fmt(shutdown_result, 'stderr')}"
result['msg'] = "Shutdown command failed. Error was {stdout}, {stderr}".format(
stdout=to_native(shutdown_result['stdout'].strip()),
stderr=to_native(shutdown_result['stderr'].strip()))
return result
result['failed'] = False
@@ -196,7 +206,7 @@ class ActionModule(ActionBase):
# If running with local connection, fail so we don't shutdown ourself
if self._connection.transport == 'local' and (not self._play_context.check_mode):
msg = f'Running {self._task.action} with local connection would shutdown the control node.'
msg = 'Running {0} with local connection would shutdown the control node.'.format(self._task.action)
return {'changed': False, 'elapsed': 0, 'shutdown': False, 'failed': True, 'msg': msg}
if task_vars is None:

View File

@@ -5,86 +5,80 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
name: doas
short_description: Do As user
description:
- This become plugins allows your remote/login user to execute commands as another user using the C(doas) utility.
author: Ansible Core Team
options:
become_user:
description: User you 'become' to execute the task.
type: string
ini:
- section: privilege_escalation
key: become_user
- section: doas_become_plugin
key: user
vars:
- name: ansible_become_user
- name: ansible_doas_user
env:
- name: ANSIBLE_BECOME_USER
- name: ANSIBLE_DOAS_USER
become_exe:
description: C(doas) executable.
type: string
default: doas
ini:
- section: privilege_escalation
key: become_exe
- section: doas_become_plugin
key: executable
vars:
- name: ansible_become_exe
- name: ansible_doas_exe
env:
- name: ANSIBLE_BECOME_EXE
- name: ANSIBLE_DOAS_EXE
become_flags:
description: Options to pass to C(doas).
type: string
default: ''
ini:
- section: privilege_escalation
key: become_flags
- section: doas_become_plugin
key: flags
vars:
- name: ansible_become_flags
- name: ansible_doas_flags
env:
- name: ANSIBLE_BECOME_FLAGS
- name: ANSIBLE_DOAS_FLAGS
become_pass:
description: Password for C(doas) prompt.
type: string
required: false
vars:
- name: ansible_become_password
- name: ansible_become_pass
- name: ansible_doas_pass
env:
- name: ANSIBLE_BECOME_PASS
- name: ANSIBLE_DOAS_PASS
ini:
- section: doas_become_plugin
key: password
prompt_l10n:
DOCUMENTATION = '''
name: doas
short_description: Do As user
description:
- List of localized strings to match for prompt detection.
- If empty we will use the built in one.
type: list
elements: string
default: []
ini:
- section: doas_become_plugin
key: localized_prompts
vars:
- name: ansible_doas_prompt_l10n
env:
- name: ANSIBLE_DOAS_PROMPT_L10N
"""
- This become plugins allows your remote/login user to execute commands as another user via the doas utility.
author: Ansible Core Team
options:
become_user:
description: User you 'become' to execute the task
ini:
- section: privilege_escalation
key: become_user
- section: doas_become_plugin
key: user
vars:
- name: ansible_become_user
- name: ansible_doas_user
env:
- name: ANSIBLE_BECOME_USER
- name: ANSIBLE_DOAS_USER
become_exe:
description: Doas executable
default: doas
ini:
- section: privilege_escalation
key: become_exe
- section: doas_become_plugin
key: executable
vars:
- name: ansible_become_exe
- name: ansible_doas_exe
env:
- name: ANSIBLE_BECOME_EXE
- name: ANSIBLE_DOAS_EXE
become_flags:
description: Options to pass to doas
default: ''
ini:
- section: privilege_escalation
key: become_flags
- section: doas_become_plugin
key: flags
vars:
- name: ansible_become_flags
- name: ansible_doas_flags
env:
- name: ANSIBLE_BECOME_FLAGS
- name: ANSIBLE_DOAS_FLAGS
become_pass:
description: password for doas prompt
required: false
vars:
- name: ansible_become_password
- name: ansible_become_pass
- name: ansible_doas_pass
env:
- name: ANSIBLE_BECOME_PASS
- name: ANSIBLE_DOAS_PASS
ini:
- section: doas_become_plugin
key: password
prompt_l10n:
description:
- List of localized strings to match for prompt detection
- If empty we'll use the built in one
default: []
ini:
- section: doas_become_plugin
key: localized_prompts
vars:
- name: ansible_doas_prompt_l10n
env:
- name: ANSIBLE_DOAS_PROMPT_L10N
'''
import re
@@ -125,9 +119,9 @@ class BecomeModule(BecomeBase):
flags += ' -n'
become_user = self.get_option('become_user')
user = f'-u {become_user}' if become_user else ''
user = '-u %s' % (become_user) if become_user else ''
success_cmd = self._build_success_command(cmd, shell, noexe=True)
executable = getattr(shell, 'executable', shell.SHELL_FAMILY)
return f'{become_exe} {flags} {user} {executable} -c {success_cmd}'
return '%s %s %s %s -c %s' % (become_exe, flags, user, executable, success_cmd)

View File

@@ -5,72 +5,68 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
name: dzdo
short_description: Centrify's Direct Authorize
description:
- This become plugins allows your remote/login user to execute commands as another user using the C(dzdo) utility.
author: Ansible Core Team
options:
become_user:
description: User you 'become' to execute the task.
type: string
ini:
- section: privilege_escalation
key: become_user
- section: dzdo_become_plugin
key: user
vars:
- name: ansible_become_user
- name: ansible_dzdo_user
env:
- name: ANSIBLE_BECOME_USER
- name: ANSIBLE_DZDO_USER
become_exe:
description: C(dzdo) executable.
type: string
default: dzdo
ini:
- section: privilege_escalation
key: become_exe
- section: dzdo_become_plugin
key: executable
vars:
- name: ansible_become_exe
- name: ansible_dzdo_exe
env:
- name: ANSIBLE_BECOME_EXE
- name: ANSIBLE_DZDO_EXE
become_flags:
description: Options to pass to C(dzdo).
type: string
default: -H -S -n
ini:
- section: privilege_escalation
key: become_flags
- section: dzdo_become_plugin
key: flags
vars:
- name: ansible_become_flags
- name: ansible_dzdo_flags
env:
- name: ANSIBLE_BECOME_FLAGS
- name: ANSIBLE_DZDO_FLAGS
become_pass:
description: Options to pass to C(dzdo).
type: string
required: false
vars:
- name: ansible_become_password
- name: ansible_become_pass
- name: ansible_dzdo_pass
env:
- name: ANSIBLE_BECOME_PASS
- name: ANSIBLE_DZDO_PASS
ini:
- section: dzdo_become_plugin
key: password
"""
DOCUMENTATION = '''
name: dzdo
short_description: Centrify's Direct Authorize
description:
- This become plugins allows your remote/login user to execute commands as another user via the dzdo utility.
author: Ansible Core Team
options:
become_user:
description: User you 'become' to execute the task
ini:
- section: privilege_escalation
key: become_user
- section: dzdo_become_plugin
key: user
vars:
- name: ansible_become_user
- name: ansible_dzdo_user
env:
- name: ANSIBLE_BECOME_USER
- name: ANSIBLE_DZDO_USER
become_exe:
description: Dzdo executable
default: dzdo
ini:
- section: privilege_escalation
key: become_exe
- section: dzdo_become_plugin
key: executable
vars:
- name: ansible_become_exe
- name: ansible_dzdo_exe
env:
- name: ANSIBLE_BECOME_EXE
- name: ANSIBLE_DZDO_EXE
become_flags:
description: Options to pass to dzdo
default: -H -S -n
ini:
- section: privilege_escalation
key: become_flags
- section: dzdo_become_plugin
key: flags
vars:
- name: ansible_become_flags
- name: ansible_dzdo_flags
env:
- name: ANSIBLE_BECOME_FLAGS
- name: ANSIBLE_DZDO_FLAGS
become_pass:
description: Options to pass to dzdo
required: false
vars:
- name: ansible_become_password
- name: ansible_become_pass
- name: ansible_dzdo_pass
env:
- name: ANSIBLE_BECOME_PASS
- name: ANSIBLE_DZDO_PASS
ini:
- section: dzdo_become_plugin
key: password
'''
from ansible.plugins.become import BecomeBase
@@ -92,10 +88,10 @@ class BecomeModule(BecomeBase):
flags = self.get_option('become_flags')
if self.get_option('become_pass'):
self.prompt = f'[dzdo via ansible, key={self._id}] password:'
flags = f"{flags.replace('-n', '')} -p \"{self.prompt}\""
self.prompt = '[dzdo via ansible, key=%s] password:' % self._id
flags = '%s -p "%s"' % (flags.replace('-n', ''), self.prompt)
become_user = self.get_option('become_user')
user = f'-u {become_user}' if become_user else ''
user = '-u %s' % (become_user) if become_user else ''
return f"{becomecmd} {flags} {user} {self._build_success_command(cmd, shell)}"
return ' '.join([becomecmd, flags, user, self._build_success_command(cmd, shell)])

View File

@@ -5,87 +5,81 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
name: ksu
short_description: Kerberos substitute user
description:
- This become plugins allows your remote/login user to execute commands as another user using the C(ksu) utility.
author: Ansible Core Team
options:
become_user:
description: User you 'become' to execute the task.
type: string
ini:
- section: privilege_escalation
key: become_user
- section: ksu_become_plugin
key: user
vars:
- name: ansible_become_user
- name: ansible_ksu_user
env:
- name: ANSIBLE_BECOME_USER
- name: ANSIBLE_KSU_USER
required: true
become_exe:
description: C(ksu) executable.
type: string
default: ksu
ini:
- section: privilege_escalation
key: become_exe
- section: ksu_become_plugin
key: executable
vars:
- name: ansible_become_exe
- name: ansible_ksu_exe
env:
- name: ANSIBLE_BECOME_EXE
- name: ANSIBLE_KSU_EXE
become_flags:
description: Options to pass to C(ksu).
type: string
default: ''
ini:
- section: privilege_escalation
key: become_flags
- section: ksu_become_plugin
key: flags
vars:
- name: ansible_become_flags
- name: ansible_ksu_flags
env:
- name: ANSIBLE_BECOME_FLAGS
- name: ANSIBLE_KSU_FLAGS
become_pass:
description: C(ksu) password.
type: string
required: false
vars:
- name: ansible_ksu_pass
- name: ansible_become_pass
- name: ansible_become_password
env:
- name: ANSIBLE_BECOME_PASS
- name: ANSIBLE_KSU_PASS
ini:
- section: ksu_become_plugin
key: password
prompt_l10n:
DOCUMENTATION = '''
name: ksu
short_description: Kerberos substitute user
description:
- List of localized strings to match for prompt detection.
- If empty we will use the built in one.
type: list
elements: string
default: []
ini:
- section: ksu_become_plugin
key: localized_prompts
vars:
- name: ansible_ksu_prompt_l10n
env:
- name: ANSIBLE_KSU_PROMPT_L10N
"""
- This become plugins allows your remote/login user to execute commands as another user via the ksu utility.
author: Ansible Core Team
options:
become_user:
description: User you 'become' to execute the task
ini:
- section: privilege_escalation
key: become_user
- section: ksu_become_plugin
key: user
vars:
- name: ansible_become_user
- name: ansible_ksu_user
env:
- name: ANSIBLE_BECOME_USER
- name: ANSIBLE_KSU_USER
required: true
become_exe:
description: Su executable
default: ksu
ini:
- section: privilege_escalation
key: become_exe
- section: ksu_become_plugin
key: executable
vars:
- name: ansible_become_exe
- name: ansible_ksu_exe
env:
- name: ANSIBLE_BECOME_EXE
- name: ANSIBLE_KSU_EXE
become_flags:
description: Options to pass to ksu
default: ''
ini:
- section: privilege_escalation
key: become_flags
- section: ksu_become_plugin
key: flags
vars:
- name: ansible_become_flags
- name: ansible_ksu_flags
env:
- name: ANSIBLE_BECOME_FLAGS
- name: ANSIBLE_KSU_FLAGS
become_pass:
description: ksu password
required: false
vars:
- name: ansible_ksu_pass
- name: ansible_become_pass
- name: ansible_become_password
env:
- name: ANSIBLE_BECOME_PASS
- name: ANSIBLE_KSU_PASS
ini:
- section: ksu_become_plugin
key: password
prompt_l10n:
description:
- List of localized strings to match for prompt detection
- If empty we'll use the built in one
default: []
ini:
- section: ksu_become_plugin
key: localized_prompts
vars:
- name: ansible_ksu_prompt_l10n
env:
- name: ANSIBLE_KSU_PROMPT_L10N
'''
import re
@@ -124,4 +118,4 @@ class BecomeModule(BecomeBase):
flags = self.get_option('become_flags')
user = self.get_option('become_user')
return f'{exe} {user} {flags} -e {self._build_success_command(cmd, shell)} '
return '%s %s %s -e %s ' % (exe, user, flags, self._build_success_command(cmd, shell))

View File

@@ -5,90 +5,86 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
name: machinectl
short_description: Systemd's machinectl privilege escalation
description:
- This become plugins allows your remote/login user to execute commands as another user using the C(machinectl) utility.
author: Ansible Core Team
options:
become_user:
description: User you 'become' to execute the task.
type: string
default: ''
ini:
- section: privilege_escalation
key: become_user
- section: machinectl_become_plugin
key: user
vars:
- name: ansible_become_user
- name: ansible_machinectl_user
env:
- name: ANSIBLE_BECOME_USER
- name: ANSIBLE_MACHINECTL_USER
become_exe:
description: C(machinectl) executable.
type: string
default: machinectl
ini:
- section: privilege_escalation
key: become_exe
- section: machinectl_become_plugin
key: executable
vars:
- name: ansible_become_exe
- name: ansible_machinectl_exe
env:
- name: ANSIBLE_BECOME_EXE
- name: ANSIBLE_MACHINECTL_EXE
become_flags:
description: Options to pass to C(machinectl).
type: string
default: ''
ini:
- section: privilege_escalation
key: become_flags
- section: machinectl_become_plugin
key: flags
vars:
- name: ansible_become_flags
- name: ansible_machinectl_flags
env:
- name: ANSIBLE_BECOME_FLAGS
- name: ANSIBLE_MACHINECTL_FLAGS
become_pass:
description: Password for C(machinectl).
type: string
required: false
vars:
- name: ansible_become_password
- name: ansible_become_pass
- name: ansible_machinectl_pass
env:
- name: ANSIBLE_BECOME_PASS
- name: ANSIBLE_MACHINECTL_PASS
ini:
- section: machinectl_become_plugin
key: password
notes:
- When not using this plugin with user V(root), it only works correctly with a polkit rule which will alter the behaviour
of machinectl. This rule must alter the prompt behaviour to ask directly for the user credentials, if the user is allowed
to perform the action (take a look at the examples section). If such a rule is not present the plugin only work if it
is used in context with the root user, because then no further prompt will be shown by machinectl.
"""
DOCUMENTATION = '''
name: machinectl
short_description: Systemd's machinectl privilege escalation
description:
- This become plugins allows your remote/login user to execute commands as another user via the machinectl utility.
author: Ansible Core Team
options:
become_user:
description: User you 'become' to execute the task
default: ''
ini:
- section: privilege_escalation
key: become_user
- section: machinectl_become_plugin
key: user
vars:
- name: ansible_become_user
- name: ansible_machinectl_user
env:
- name: ANSIBLE_BECOME_USER
- name: ANSIBLE_MACHINECTL_USER
become_exe:
description: Machinectl executable
default: machinectl
ini:
- section: privilege_escalation
key: become_exe
- section: machinectl_become_plugin
key: executable
vars:
- name: ansible_become_exe
- name: ansible_machinectl_exe
env:
- name: ANSIBLE_BECOME_EXE
- name: ANSIBLE_MACHINECTL_EXE
become_flags:
description: Options to pass to machinectl
default: ''
ini:
- section: privilege_escalation
key: become_flags
- section: machinectl_become_plugin
key: flags
vars:
- name: ansible_become_flags
- name: ansible_machinectl_flags
env:
- name: ANSIBLE_BECOME_FLAGS
- name: ANSIBLE_MACHINECTL_FLAGS
become_pass:
description: Password for machinectl
required: false
vars:
- name: ansible_become_password
- name: ansible_become_pass
- name: ansible_machinectl_pass
env:
- name: ANSIBLE_BECOME_PASS
- name: ANSIBLE_MACHINECTL_PASS
ini:
- section: machinectl_become_plugin
key: password
notes:
- When not using this plugin with user V(root), it only works correctly with a polkit rule which will alter
the behaviour of machinectl. This rule must alter the prompt behaviour to ask directly for the user credentials,
if the user is allowed to perform the action (take a look at the examples section).
If such a rule is not present the plugin only work if it is used in context with the root user,
because then no further prompt will be shown by machinectl.
'''
EXAMPLES = r"""
EXAMPLES = r'''
# A polkit rule needed to use the module with a non-root user.
# See the Notes section for details.
/etc/polkit-1/rules.d/60-machinectl-fast-user-auth.rules: |-
polkit.addRule(function(action, subject) {
if(action.id == "org.freedesktop.machine1.host-shell" &&
subject.isInGroup("wheel")) {
return polkit.Result.AUTH_SELF_KEEP;
}
});
"""
60-machinectl-fast-user-auth.rules: |
polkit.addRule(function(action, subject) {
if(action.id == "org.freedesktop.machine1.host-shell" && subject.isInGroup("wheel")) {
return polkit.Result.AUTH_SELF_KEEP;
}
});
'''
from re import compile as re_compile
@@ -122,7 +118,7 @@ class BecomeModule(BecomeBase):
flags = self.get_option('become_flags')
user = self.get_option('become_user')
return f'{become} -q shell {flags} {user}@ {self._build_success_command(cmd, shell)}'
return '%s -q shell %s %s@ %s' % (become, flags, user, self._build_success_command(cmd, shell))
def check_success(self, b_output):
b_output = self.remove_ansi_codes(b_output)

View File

@@ -5,84 +5,80 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
name: pbrun
short_description: PowerBroker run
description:
- This become plugins allows your remote/login user to execute commands as another user using the C(pbrun) utility.
author: Ansible Core Team
options:
become_user:
description: User you 'become' to execute the task.
type: string
default: ''
ini:
- section: privilege_escalation
key: become_user
- section: pbrun_become_plugin
key: user
vars:
- name: ansible_become_user
- name: ansible_pbrun_user
env:
- name: ANSIBLE_BECOME_USER
- name: ANSIBLE_PBRUN_USER
become_exe:
description: C(pbrun) executable.
type: string
default: pbrun
ini:
- section: privilege_escalation
key: become_exe
- section: pbrun_become_plugin
key: executable
vars:
- name: ansible_become_exe
- name: ansible_pbrun_exe
env:
- name: ANSIBLE_BECOME_EXE
- name: ANSIBLE_PBRUN_EXE
become_flags:
description: Options to pass to C(pbrun).
type: string
default: ''
ini:
- section: privilege_escalation
key: become_flags
- section: pbrun_become_plugin
key: flags
vars:
- name: ansible_become_flags
- name: ansible_pbrun_flags
env:
- name: ANSIBLE_BECOME_FLAGS
- name: ANSIBLE_PBRUN_FLAGS
become_pass:
description: Password for C(pbrun).
type: string
required: false
vars:
- name: ansible_become_password
- name: ansible_become_pass
- name: ansible_pbrun_pass
env:
- name: ANSIBLE_BECOME_PASS
- name: ANSIBLE_PBRUN_PASS
ini:
- section: pbrun_become_plugin
key: password
wrap_exe:
description: Toggle to wrap the command C(pbrun) calls in C(shell -c) or not.
default: false
type: bool
ini:
- section: pbrun_become_plugin
key: wrap_execution
vars:
- name: ansible_pbrun_wrap_execution
env:
- name: ANSIBLE_PBRUN_WRAP_EXECUTION
"""
DOCUMENTATION = '''
name: pbrun
short_description: PowerBroker run
description:
- This become plugins allows your remote/login user to execute commands as another user via the pbrun utility.
author: Ansible Core Team
options:
become_user:
description: User you 'become' to execute the task
default: ''
ini:
- section: privilege_escalation
key: become_user
- section: pbrun_become_plugin
key: user
vars:
- name: ansible_become_user
- name: ansible_pbrun_user
env:
- name: ANSIBLE_BECOME_USER
- name: ANSIBLE_PBRUN_USER
become_exe:
description: Sudo executable
default: pbrun
ini:
- section: privilege_escalation
key: become_exe
- section: pbrun_become_plugin
key: executable
vars:
- name: ansible_become_exe
- name: ansible_pbrun_exe
env:
- name: ANSIBLE_BECOME_EXE
- name: ANSIBLE_PBRUN_EXE
become_flags:
description: Options to pass to pbrun
default: ''
ini:
- section: privilege_escalation
key: become_flags
- section: pbrun_become_plugin
key: flags
vars:
- name: ansible_become_flags
- name: ansible_pbrun_flags
env:
- name: ANSIBLE_BECOME_FLAGS
- name: ANSIBLE_PBRUN_FLAGS
become_pass:
description: Password for pbrun
required: false
vars:
- name: ansible_become_password
- name: ansible_become_pass
- name: ansible_pbrun_pass
env:
- name: ANSIBLE_BECOME_PASS
- name: ANSIBLE_PBRUN_PASS
ini:
- section: pbrun_become_plugin
key: password
wrap_exe:
description: Toggle to wrap the command pbrun calls in 'shell -c' or not
default: false
type: bool
ini:
- section: pbrun_become_plugin
key: wrap_execution
vars:
- name: ansible_pbrun_wrap_execution
env:
- name: ANSIBLE_PBRUN_WRAP_EXECUTION
'''
from ansible.plugins.become import BecomeBase
@@ -103,7 +99,7 @@ class BecomeModule(BecomeBase):
flags = self.get_option('become_flags')
become_user = self.get_option('become_user')
user = f'-u {become_user}' if become_user else ''
user = '-u %s' % (become_user) if become_user else ''
noexe = not self.get_option('wrap_exe')
return f"{become_exe} {flags} {user} {self._build_success_command(cmd, shell, noexe=noexe)}"
return ' '.join([become_exe, flags, user, self._build_success_command(cmd, shell, noexe=noexe)])

View File

@@ -5,89 +5,85 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
name: pfexec
short_description: profile based execution
description:
- This become plugins allows your remote/login user to execute commands as another user using the C(pfexec) utility.
author: Ansible Core Team
options:
become_user:
DOCUMENTATION = '''
name: pfexec
short_description: profile based execution
description:
- User you 'become' to execute the task.
- This plugin ignores this setting as pfexec uses its own C(exec_attr) to figure this out, but it is supplied here
for Ansible to make decisions needed for the task execution, like file permissions.
type: string
default: root
ini:
- section: privilege_escalation
key: become_user
- section: pfexec_become_plugin
key: user
vars:
- name: ansible_become_user
- name: ansible_pfexec_user
env:
- name: ANSIBLE_BECOME_USER
- name: ANSIBLE_PFEXEC_USER
become_exe:
description: C(pfexec) executable.
type: string
default: pfexec
ini:
- section: privilege_escalation
key: become_exe
- section: pfexec_become_plugin
key: executable
vars:
- name: ansible_become_exe
- name: ansible_pfexec_exe
env:
- name: ANSIBLE_BECOME_EXE
- name: ANSIBLE_PFEXEC_EXE
become_flags:
description: Options to pass to C(pfexec).
type: string
default: -H -S -n
ini:
- section: privilege_escalation
key: become_flags
- section: pfexec_become_plugin
key: flags
vars:
- name: ansible_become_flags
- name: ansible_pfexec_flags
env:
- name: ANSIBLE_BECOME_FLAGS
- name: ANSIBLE_PFEXEC_FLAGS
become_pass:
description: C(pfexec) password.
type: string
required: false
vars:
- name: ansible_become_password
- name: ansible_become_pass
- name: ansible_pfexec_pass
env:
- name: ANSIBLE_BECOME_PASS
- name: ANSIBLE_PFEXEC_PASS
ini:
- section: pfexec_become_plugin
key: password
wrap_exe:
description: Toggle to wrap the command C(pfexec) calls in C(shell -c) or not.
default: false
type: bool
ini:
- section: pfexec_become_plugin
key: wrap_execution
vars:
- name: ansible_pfexec_wrap_execution
env:
- name: ANSIBLE_PFEXEC_WRAP_EXECUTION
notes:
- This plugin ignores O(become_user) as pfexec uses its own C(exec_attr) to figure this out.
"""
- This become plugins allows your remote/login user to execute commands as another user via the pfexec utility.
author: Ansible Core Team
options:
become_user:
description:
- User you 'become' to execute the task
- This plugin ignores this setting as pfexec uses it's own C(exec_attr) to figure this out,
but it is supplied here for Ansible to make decisions needed for the task execution, like file permissions.
default: root
ini:
- section: privilege_escalation
key: become_user
- section: pfexec_become_plugin
key: user
vars:
- name: ansible_become_user
- name: ansible_pfexec_user
env:
- name: ANSIBLE_BECOME_USER
- name: ANSIBLE_PFEXEC_USER
become_exe:
description: Sudo executable
default: pfexec
ini:
- section: privilege_escalation
key: become_exe
- section: pfexec_become_plugin
key: executable
vars:
- name: ansible_become_exe
- name: ansible_pfexec_exe
env:
- name: ANSIBLE_BECOME_EXE
- name: ANSIBLE_PFEXEC_EXE
become_flags:
description: Options to pass to pfexec
default: -H -S -n
ini:
- section: privilege_escalation
key: become_flags
- section: pfexec_become_plugin
key: flags
vars:
- name: ansible_become_flags
- name: ansible_pfexec_flags
env:
- name: ANSIBLE_BECOME_FLAGS
- name: ANSIBLE_PFEXEC_FLAGS
become_pass:
description: pfexec password
required: false
vars:
- name: ansible_become_password
- name: ansible_become_pass
- name: ansible_pfexec_pass
env:
- name: ANSIBLE_BECOME_PASS
- name: ANSIBLE_PFEXEC_PASS
ini:
- section: pfexec_become_plugin
key: password
wrap_exe:
description: Toggle to wrap the command pfexec calls in 'shell -c' or not
default: false
type: bool
ini:
- section: pfexec_become_plugin
key: wrap_execution
vars:
- name: ansible_pfexec_wrap_execution
env:
- name: ANSIBLE_PFEXEC_WRAP_EXECUTION
notes:
- This plugin ignores O(become_user) as pfexec uses it's own C(exec_attr) to figure this out.
'''
from ansible.plugins.become import BecomeBase
@@ -106,4 +102,4 @@ class BecomeModule(BecomeBase):
flags = self.get_option('become_flags')
noexe = not self.get_option('wrap_exe')
return f'{exe} {flags} {self._build_success_command(cmd, shell, noexe=noexe)}'
return '%s %s %s' % (exe, flags, self._build_success_command(cmd, shell, noexe=noexe))

View File

@@ -5,60 +5,57 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
name: pmrun
short_description: Privilege Manager run
description:
- This become plugins allows your remote/login user to execute commands as another user using the C(pmrun) utility.
author: Ansible Core Team
options:
become_exe:
description: C(pmrun) executable.
type: string
default: pmrun
ini:
- section: privilege_escalation
key: become_exe
- section: pmrun_become_plugin
key: executable
vars:
- name: ansible_become_exe
- name: ansible_pmrun_exe
env:
- name: ANSIBLE_BECOME_EXE
- name: ANSIBLE_PMRUN_EXE
become_flags:
description: Options to pass to C(pmrun).
type: string
default: ''
ini:
- section: privilege_escalation
key: become_flags
- section: pmrun_become_plugin
key: flags
vars:
- name: ansible_become_flags
- name: ansible_pmrun_flags
env:
- name: ANSIBLE_BECOME_FLAGS
- name: ANSIBLE_PMRUN_FLAGS
become_pass:
description: C(pmrun) password.
type: string
required: false
vars:
- name: ansible_become_password
- name: ansible_become_pass
- name: ansible_pmrun_pass
env:
- name: ANSIBLE_BECOME_PASS
- name: ANSIBLE_PMRUN_PASS
ini:
- section: pmrun_become_plugin
key: password
notes:
- This plugin ignores the C(become_user) supplied and uses C(pmrun)'s own configuration to select the user.
"""
DOCUMENTATION = '''
name: pmrun
short_description: Privilege Manager run
description:
- This become plugins allows your remote/login user to execute commands as another user via the pmrun utility.
author: Ansible Core Team
options:
become_exe:
description: Sudo executable
default: pmrun
ini:
- section: privilege_escalation
key: become_exe
- section: pmrun_become_plugin
key: executable
vars:
- name: ansible_become_exe
- name: ansible_pmrun_exe
env:
- name: ANSIBLE_BECOME_EXE
- name: ANSIBLE_PMRUN_EXE
become_flags:
description: Options to pass to pmrun
default: ''
ini:
- section: privilege_escalation
key: become_flags
- section: pmrun_become_plugin
key: flags
vars:
- name: ansible_become_flags
- name: ansible_pmrun_flags
env:
- name: ANSIBLE_BECOME_FLAGS
- name: ANSIBLE_PMRUN_FLAGS
become_pass:
description: pmrun password
required: false
vars:
- name: ansible_become_password
- name: ansible_become_pass
- name: ansible_pmrun_pass
env:
- name: ANSIBLE_BECOME_PASS
- name: ANSIBLE_PMRUN_PASS
ini:
- section: pmrun_become_plugin
key: password
notes:
- This plugin ignores the become_user supplied and uses pmrun's own configuration to select the user.
'''
from ansible.plugins.become import BecomeBase
from ansible.module_utils.six.moves import shlex_quote
@@ -78,4 +75,4 @@ class BecomeModule(BecomeBase):
become = self.get_option('become_exe')
flags = self.get_option('become_flags')
return f'{become} {flags} {shlex_quote(self._build_success_command(cmd, shell))}'
return '%s %s %s' % (become, flags, shlex_quote(self._build_success_command(cmd, shell)))

View File

@@ -1,128 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2024, 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
DOCUMENTATION = r"""
name: run0
short_description: Systemd's run0
description:
- This become plugins allows your remote/login user to execute commands as another user using the C(run0) utility.
author:
- Thomas Sjögren (@konstruktoid)
version_added: '9.0.0'
options:
become_user:
description: User you 'become' to execute the task.
default: root
ini:
- section: privilege_escalation
key: become_user
- section: run0_become_plugin
key: user
vars:
- name: ansible_become_user
- name: ansible_run0_user
env:
- name: ANSIBLE_BECOME_USER
- name: ANSIBLE_RUN0_USER
type: string
become_exe:
description: C(run0) executable.
default: run0
ini:
- section: privilege_escalation
key: become_exe
- section: run0_become_plugin
key: executable
vars:
- name: ansible_become_exe
- name: ansible_run0_exe
env:
- name: ANSIBLE_BECOME_EXE
- name: ANSIBLE_RUN0_EXE
type: string
become_flags:
description: Options to pass to C(run0).
default: ''
ini:
- section: privilege_escalation
key: become_flags
- section: run0_become_plugin
key: flags
vars:
- name: ansible_become_flags
- name: ansible_run0_flags
env:
- name: ANSIBLE_BECOME_FLAGS
- name: ANSIBLE_RUN0_FLAGS
type: string
notes:
- This plugin will only work when a C(polkit) rule is in place.
"""
EXAMPLES = r"""
# An example polkit rule that allows the user 'ansible' in the 'wheel' group
# to execute commands using run0 without authentication.
/etc/polkit-1/rules.d/60-run0-fast-user-auth.rules: |-
polkit.addRule(function(action, subject) {
if(action.id == "org.freedesktop.systemd1.manage-units" &&
subject.isInGroup("wheel") &&
subject.user == "ansible") {
return polkit.Result.YES;
}
});
"""
from re import compile as re_compile
from ansible.plugins.become import BecomeBase
from ansible.module_utils._text import to_bytes
ansi_color_codes = re_compile(to_bytes(r"\x1B\[[0-9;]+m"))
class BecomeModule(BecomeBase):
name = "community.general.run0"
prompt = "Password: "
fail = ("==== AUTHENTICATION FAILED ====",)
success = ("==== AUTHENTICATION COMPLETE ====",)
require_tty = (
True # see https://github.com/ansible-collections/community.general/issues/6932
)
@staticmethod
def remove_ansi_codes(line):
return ansi_color_codes.sub(b"", line)
def build_become_command(self, cmd, shell):
super().build_become_command(cmd, shell)
if not cmd:
return cmd
become = self.get_option("become_exe")
flags = self.get_option("become_flags")
user = self.get_option("become_user")
return (
f"{become} --user={user} {flags} {self._build_success_command(cmd, shell)}"
)
def check_success(self, b_output):
b_output = self.remove_ansi_codes(b_output)
return super().check_success(b_output)
def check_incorrect_password(self, b_output):
b_output = self.remove_ansi_codes(b_output)
return super().check_incorrect_password(b_output)
def check_missing_password(self, b_output):
b_output = self.remove_ansi_codes(b_output)
return super().check_missing_password(b_output)

View File

@@ -5,73 +5,69 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
name: sesu
short_description: CA Privileged Access Manager
description:
- This become plugins allows your remote/login user to execute commands as another user using the C(sesu) utility.
author: ansible (@nekonyuu)
options:
become_user:
description: User you 'become' to execute the task.
type: string
default: ''
ini:
- section: privilege_escalation
key: become_user
- section: sesu_become_plugin
key: user
vars:
- name: ansible_become_user
- name: ansible_sesu_user
env:
- name: ANSIBLE_BECOME_USER
- name: ANSIBLE_SESU_USER
become_exe:
description: C(sesu) executable.
type: string
default: sesu
ini:
- section: privilege_escalation
key: become_exe
- section: sesu_become_plugin
key: executable
vars:
- name: ansible_become_exe
- name: ansible_sesu_exe
env:
- name: ANSIBLE_BECOME_EXE
- name: ANSIBLE_SESU_EXE
become_flags:
description: Options to pass to C(sesu).
type: string
default: -H -S -n
ini:
- section: privilege_escalation
key: become_flags
- section: sesu_become_plugin
key: flags
vars:
- name: ansible_become_flags
- name: ansible_sesu_flags
env:
- name: ANSIBLE_BECOME_FLAGS
- name: ANSIBLE_SESU_FLAGS
become_pass:
description: Password to pass to C(sesu).
type: string
required: false
vars:
- name: ansible_become_password
- name: ansible_become_pass
- name: ansible_sesu_pass
env:
- name: ANSIBLE_BECOME_PASS
- name: ANSIBLE_SESU_PASS
ini:
- section: sesu_become_plugin
key: password
"""
DOCUMENTATION = '''
name: sesu
short_description: CA Privileged Access Manager
description:
- This become plugins allows your remote/login user to execute commands as another user via the sesu utility.
author: ansible (@nekonyuu)
options:
become_user:
description: User you 'become' to execute the task
default: ''
ini:
- section: privilege_escalation
key: become_user
- section: sesu_become_plugin
key: user
vars:
- name: ansible_become_user
- name: ansible_sesu_user
env:
- name: ANSIBLE_BECOME_USER
- name: ANSIBLE_SESU_USER
become_exe:
description: sesu executable
default: sesu
ini:
- section: privilege_escalation
key: become_exe
- section: sesu_become_plugin
key: executable
vars:
- name: ansible_become_exe
- name: ansible_sesu_exe
env:
- name: ANSIBLE_BECOME_EXE
- name: ANSIBLE_SESU_EXE
become_flags:
description: Options to pass to sesu
default: -H -S -n
ini:
- section: privilege_escalation
key: become_flags
- section: sesu_become_plugin
key: flags
vars:
- name: ansible_become_flags
- name: ansible_sesu_flags
env:
- name: ANSIBLE_BECOME_FLAGS
- name: ANSIBLE_SESU_FLAGS
become_pass:
description: Password to pass to sesu
required: false
vars:
- name: ansible_become_password
- name: ansible_become_pass
- name: ansible_sesu_pass
env:
- name: ANSIBLE_BECOME_PASS
- name: ANSIBLE_SESU_PASS
ini:
- section: sesu_become_plugin
key: password
'''
from ansible.plugins.become import BecomeBase
@@ -93,4 +89,4 @@ class BecomeModule(BecomeBase):
flags = self.get_option('become_flags')
user = self.get_option('become_user')
return f'{become} {flags} {user} -c {self._build_success_command(cmd, shell)}'
return '%s %s %s -c %s' % (become, flags, user, self._build_success_command(cmd, shell))

View File

@@ -5,75 +5,56 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
name: sudosu
short_description: Run tasks using sudo su -
description:
- This become plugin allows your remote/login user to execute commands as another user using the C(sudo) and C(su) utilities
combined.
author:
- Dag Wieers (@dagwieers)
version_added: 2.4.0
options:
become_user:
description: User you 'become' to execute the task.
type: string
default: root
ini:
- section: privilege_escalation
key: become_user
- section: sudo_become_plugin
key: user
vars:
- name: ansible_become_user
- name: ansible_sudo_user
env:
- name: ANSIBLE_BECOME_USER
- name: ANSIBLE_SUDO_USER
become_flags:
description: Options to pass to C(sudo).
type: string
default: -H -S -n
ini:
- section: privilege_escalation
key: become_flags
- section: sudo_become_plugin
key: flags
vars:
- name: ansible_become_flags
- name: ansible_sudo_flags
env:
- name: ANSIBLE_BECOME_FLAGS
- name: ANSIBLE_SUDO_FLAGS
become_pass:
description: Password to pass to C(sudo).
type: string
required: false
vars:
- name: ansible_become_password
- name: ansible_become_pass
- name: ansible_sudo_pass
env:
- name: ANSIBLE_BECOME_PASS
- name: ANSIBLE_SUDO_PASS
ini:
- section: sudo_become_plugin
key: password
alt_method:
DOCUMENTATION = """
name: sudosu
short_description: Run tasks using sudo su -
description:
- Whether to use an alternative method to call C(su). Instead of running C(su -l user /path/to/shell -c command), it
runs C(su -l user -c command).
- Use this when the default one is not working on your system.
required: false
type: boolean
ini:
- section: community.general.sudosu
key: alternative_method
vars:
- name: ansible_sudosu_alt_method
env:
- name: ANSIBLE_SUDOSU_ALT_METHOD
version_added: 9.2.0
- This become plugin allows your remote/login user to execute commands as another user via the C(sudo) and C(su) utilities combined.
author:
- Dag Wieers (@dagwieers)
version_added: 2.4.0
options:
become_user:
description: User you 'become' to execute the task.
default: root
ini:
- section: privilege_escalation
key: become_user
- section: sudo_become_plugin
key: user
vars:
- name: ansible_become_user
- name: ansible_sudo_user
env:
- name: ANSIBLE_BECOME_USER
- name: ANSIBLE_SUDO_USER
become_flags:
description: Options to pass to C(sudo).
default: -H -S -n
ini:
- section: privilege_escalation
key: become_flags
- section: sudo_become_plugin
key: flags
vars:
- name: ansible_become_flags
- name: ansible_sudo_flags
env:
- name: ANSIBLE_BECOME_FLAGS
- name: ANSIBLE_SUDO_FLAGS
become_pass:
description: Password to pass to C(sudo).
required: false
vars:
- name: ansible_become_password
- name: ansible_become_pass
- name: ansible_sudo_pass
env:
- name: ANSIBLE_BECOME_PASS
- name: ANSIBLE_SUDO_PASS
ini:
- section: sudo_become_plugin
key: password
"""
@@ -99,16 +80,13 @@ class BecomeModule(BecomeBase):
flags = self.get_option('become_flags') or ''
prompt = ''
if self.get_option('become_pass'):
self.prompt = f'[sudo via ansible, key={self._id}] password:'
self.prompt = '[sudo via ansible, key=%s] password:' % self._id
if flags: # this could be simplified, but kept as is for now for backwards string matching
flags = flags.replace('-n', '')
prompt = f'-p "{self.prompt}"'
prompt = '-p "%s"' % (self.prompt)
user = self.get_option('become_user') or ''
if user:
user = f'{user}'
user = '%s' % (user)
if self.get_option('alt_method'):
return f"{becomecmd} {flags} {prompt} su -l {user} -c {self._build_success_command(cmd, shell, True)}"
else:
return f"{becomecmd} {flags} {prompt} su -l {user} {self._build_success_command(cmd, shell)}"
return ' '.join([becomecmd, flags, prompt, 'su -l', user, self._build_success_command(cmd, shell)])

View File

@@ -7,46 +7,44 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Unknown (!UNKNOWN)
name: memcached
short_description: Use memcached DB for cache
description:
- This cache uses JSON formatted, per host records saved in memcached.
requirements:
- memcache (python lib)
options:
_uri:
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: memcached
short_description: Use memcached DB for cache
description:
- List of connection information for the memcached DBs.
default: ['127.0.0.1:11211']
type: list
elements: string
env:
- name: ANSIBLE_CACHE_PLUGIN_CONNECTION
ini:
- key: fact_caching_connection
section: defaults
_prefix:
description: User defined prefix to use when creating the DB entries.
type: string
default: ansible_facts
env:
- name: ANSIBLE_CACHE_PLUGIN_PREFIX
ini:
- key: fact_caching_prefix
section: defaults
_timeout:
default: 86400
type: integer
# TODO: determine whether it is OK to change to: type: float
description: Expiration timeout in seconds for the cache plugin data. Set to 0 to never expire.
env:
- name: ANSIBLE_CACHE_PLUGIN_TIMEOUT
ini:
- key: fact_caching_timeout
section: defaults
"""
- This cache uses JSON formatted, per host records saved in memcached.
requirements:
- memcache (python lib)
options:
_uri:
description:
- List of connection information for the memcached DBs
default: ['127.0.0.1:11211']
type: list
elements: string
env:
- name: ANSIBLE_CACHE_PLUGIN_CONNECTION
ini:
- key: fact_caching_connection
section: defaults
_prefix:
description: User defined prefix to use when creating the DB entries
default: ansible_facts
env:
- name: ANSIBLE_CACHE_PLUGIN_PREFIX
ini:
- key: fact_caching_prefix
section: defaults
_timeout:
default: 86400
description: Expiration timeout in seconds for the cache plugin data. Set to 0 to never expire
env:
- name: ANSIBLE_CACHE_PLUGIN_TIMEOUT
ini:
- key: fact_caching_timeout
section: defaults
type: integer
'''
import collections
import os
@@ -191,7 +189,7 @@ class CacheModule(BaseCacheModule):
self._keys = CacheModuleKeys(self._db, self._db.get(CacheModuleKeys.PREFIX) or [])
def _make_key(self, key):
return f"{self._prefix}{key}"
return "{0}{1}".format(self._prefix, key)
def _expire_keys(self):
if self._timeout > 0:

View File

@@ -8,41 +8,38 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
name: pickle
short_description: Pickle formatted files
description:
- This cache uses Python's pickle serialization format, in per host files, saved to the filesystem.
author: Brian Coca (@bcoca)
options:
_uri:
required: true
DOCUMENTATION = '''
name: pickle
short_description: Pickle formatted files.
description:
- Path in which the cache plugin will save the files.
env:
- name: ANSIBLE_CACHE_PLUGIN_CONNECTION
ini:
- key: fact_caching_connection
section: defaults
type: path
_prefix:
description: User defined prefix to use when creating the files.
env:
- name: ANSIBLE_CACHE_PLUGIN_PREFIX
ini:
- key: fact_caching_prefix
section: defaults
type: string
_timeout:
default: 86400
description: Expiration timeout in seconds for the cache plugin data. Set to 0 to never expire.
env:
- name: ANSIBLE_CACHE_PLUGIN_TIMEOUT
ini:
- key: fact_caching_timeout
section: defaults
type: float
"""
- This cache uses Python's pickle serialization format, in per host files, saved to the filesystem.
author: Brian Coca (@bcoca)
options:
_uri:
required: true
description:
- Path in which the cache plugin will save the files
env:
- name: ANSIBLE_CACHE_PLUGIN_CONNECTION
ini:
- key: fact_caching_connection
section: defaults
_prefix:
description: User defined prefix to use when creating the files
env:
- name: ANSIBLE_CACHE_PLUGIN_PREFIX
ini:
- key: fact_caching_prefix
section: defaults
_timeout:
default: 86400
description: Expiration timeout in seconds for the cache plugin data. Set to 0 to never expire
env:
- name: ANSIBLE_CACHE_PLUGIN_TIMEOUT
ini:
- key: fact_caching_timeout
section: defaults
'''
try:
import cPickle as pickle

124
plugins/cache/redis.py vendored
View File

@@ -6,73 +6,69 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Unknown (!UNKNOWN)
name: redis
short_description: Use Redis DB for cache
description:
- This cache uses JSON formatted, per host records saved in Redis.
requirements:
- redis>=2.4.5 (python lib)
options:
_uri:
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: redis
short_description: Use Redis DB for cache
description:
- A colon separated string of connection information for Redis.
- The format is V(host:port:db:password), for example V(localhost:6379:0:changeme).
- To use encryption in transit, prefix the connection with V(tls://), as in V(tls://localhost:6379:0:changeme).
- To use redis sentinel, use separator V(;), for example V(localhost:26379;localhost:26379;0:changeme). Requires redis>=2.9.0.
type: string
required: true
env:
- name: ANSIBLE_CACHE_PLUGIN_CONNECTION
ini:
- key: fact_caching_connection
section: defaults
_prefix:
description: User defined prefix to use when creating the DB entries.
type: string
default: ansible_facts
env:
- name: ANSIBLE_CACHE_PLUGIN_PREFIX
ini:
- key: fact_caching_prefix
section: defaults
_keyset_name:
description: User defined name for cache keyset name.
type: string
default: ansible_cache_keys
env:
- name: ANSIBLE_CACHE_REDIS_KEYSET_NAME
ini:
- key: fact_caching_redis_keyset_name
section: defaults
version_added: 1.3.0
_sentinel_service_name:
description: The redis sentinel service name (or referenced as cluster name).
type: string
env:
- name: ANSIBLE_CACHE_REDIS_SENTINEL
ini:
- key: fact_caching_redis_sentinel
section: defaults
version_added: 1.3.0
_timeout:
default: 86400
type: integer
# TODO: determine whether it is OK to change to: type: float
description: Expiration timeout in seconds for the cache plugin data. Set to 0 to never expire.
env:
- name: ANSIBLE_CACHE_PLUGIN_TIMEOUT
ini:
- key: fact_caching_timeout
section: defaults
"""
- This cache uses JSON formatted, per host records saved in Redis.
requirements:
- redis>=2.4.5 (python lib)
options:
_uri:
description:
- A colon separated string of connection information for Redis.
- The format is V(host:port:db:password), for example V(localhost:6379:0:changeme).
- To use encryption in transit, prefix the connection with V(tls://), as in V(tls://localhost:6379:0:changeme).
- To use redis sentinel, use separator V(;), for example V(localhost:26379;localhost:26379;0:changeme). Requires redis>=2.9.0.
required: true
env:
- name: ANSIBLE_CACHE_PLUGIN_CONNECTION
ini:
- key: fact_caching_connection
section: defaults
_prefix:
description: User defined prefix to use when creating the DB entries
default: ansible_facts
env:
- name: ANSIBLE_CACHE_PLUGIN_PREFIX
ini:
- key: fact_caching_prefix
section: defaults
_keyset_name:
description: User defined name for cache keyset name.
default: ansible_cache_keys
env:
- name: ANSIBLE_CACHE_REDIS_KEYSET_NAME
ini:
- key: fact_caching_redis_keyset_name
section: defaults
version_added: 1.3.0
_sentinel_service_name:
description: The redis sentinel service name (or referenced as cluster name).
env:
- name: ANSIBLE_CACHE_REDIS_SENTINEL
ini:
- key: fact_caching_redis_sentinel
section: defaults
version_added: 1.3.0
_timeout:
default: 86400
description: Expiration timeout in seconds for the cache plugin data. Set to 0 to never expire
env:
- name: ANSIBLE_CACHE_PLUGIN_TIMEOUT
ini:
- key: fact_caching_timeout
section: defaults
type: integer
'''
import re
import time
import json
from ansible.errors import AnsibleError
from ansible.module_utils.common.text.converters import to_native
from ansible.parsing.ajson import AnsibleJSONEncoder, AnsibleJSONDecoder
from ansible.plugins.cache import BaseCacheModule
from ansible.utils.display import Display
@@ -130,7 +126,7 @@ class CacheModule(BaseCacheModule):
connection = self._parse_connection(self.re_url_conn, uri)
self._db = StrictRedis(*connection, **kw)
display.vv(f'Redis connection: {self._db}')
display.vv('Redis connection: %s' % self._db)
@staticmethod
def _parse_connection(re_patt, uri):
@@ -163,12 +159,12 @@ class CacheModule(BaseCacheModule):
pass # password is optional
sentinels = [self._parse_connection(self.re_sent_conn, shost) for shost in connections]
display.vv(f'\nUsing redis sentinels: {sentinels}')
display.vv('\nUsing redis sentinels: %s' % sentinels)
scon = Sentinel(sentinels, **kw)
try:
return scon.master_for(self._sentinel_service_name, socket_timeout=0.2)
except Exception as exc:
raise AnsibleError(f'Could not connect to redis sentinel: {exc}')
raise AnsibleError('Could not connect to redis sentinel: %s' % to_native(exc))
def _make_key(self, key):
return self._prefix + key
@@ -226,7 +222,7 @@ class CacheModule(BaseCacheModule):
def copy(self):
# TODO: there is probably a better way to do this in redis
ret = {k: self.get(k) for k in self.keys()}
ret = dict([(k, self.get(k)) for k in self.keys()])
return ret
def __getstate__(self):

67
plugins/cache/yaml.py vendored
View File

@@ -8,42 +8,39 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
name: yaml
short_description: YAML formatted files
description:
- This cache uses YAML formatted, per host, files saved to the filesystem.
author: Brian Coca (@bcoca)
options:
_uri:
required: true
DOCUMENTATION = '''
name: yaml
short_description: YAML formatted files.
description:
- Path in which the cache plugin will save the files.
env:
- name: ANSIBLE_CACHE_PLUGIN_CONNECTION
ini:
- key: fact_caching_connection
section: defaults
type: string
_prefix:
description: User defined prefix to use when creating the files.
env:
- name: ANSIBLE_CACHE_PLUGIN_PREFIX
ini:
- key: fact_caching_prefix
section: defaults
type: string
_timeout:
default: 86400
description: Expiration timeout in seconds for the cache plugin data. Set to 0 to never expire.
env:
- name: ANSIBLE_CACHE_PLUGIN_TIMEOUT
ini:
- key: fact_caching_timeout
section: defaults
type: integer
# TODO: determine whether it is OK to change to: type: float
"""
- This cache uses YAML formatted, per host, files saved to the filesystem.
author: Brian Coca (@bcoca)
options:
_uri:
required: true
description:
- Path in which the cache plugin will save the files
env:
- name: ANSIBLE_CACHE_PLUGIN_CONNECTION
ini:
- key: fact_caching_connection
section: defaults
_prefix:
description: User defined prefix to use when creating the files
env:
- name: ANSIBLE_CACHE_PLUGIN_PREFIX
ini:
- key: fact_caching_prefix
section: defaults
_timeout:
default: 86400
description: Expiration timeout in seconds for the cache plugin data. Set to 0 to never expire
env:
- name: ANSIBLE_CACHE_PLUGIN_TIMEOUT
ini:
- key: fact_caching_timeout
section: defaults
type: integer
'''
import codecs

View File

@@ -7,41 +7,38 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Unknown (!UNKNOWN)
name: cgroup_memory_recap
type: aggregate
requirements:
- whitelist in configuration
- cgroups
short_description: Profiles maximum memory usage of tasks and full execution using cgroups
description:
- This is an Ansible callback plugin that profiles maximum memory usage of Ansible and individual tasks, and displays a
recap at the end using cgroups.
notes:
- Requires ansible to be run from within a C(cgroup), such as with C(cgexec -g memory:ansible_profile ansible-playbook ...).
- This C(cgroup) should only be used by Ansible to get accurate results.
- To create the C(cgroup), first use a command such as C(sudo cgcreate -a ec2-user:ec2-user -t ec2-user:ec2-user -g memory:ansible_profile).
options:
max_mem_file:
required: true
description: Path to cgroups C(memory.max_usage_in_bytes) file. Example V(/sys/fs/cgroup/memory/ansible_profile/memory.max_usage_in_bytes).
type: str
env:
- name: CGROUP_MAX_MEM_FILE
ini:
- section: callback_cgroupmemrecap
key: max_mem_file
cur_mem_file:
required: true
description: Path to C(memory.usage_in_bytes) file. Example V(/sys/fs/cgroup/memory/ansible_profile/memory.usage_in_bytes).
type: str
env:
- name: CGROUP_CUR_MEM_FILE
ini:
- section: callback_cgroupmemrecap
key: cur_mem_file
"""
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: cgroup_memory_recap
type: aggregate
requirements:
- whitelist in configuration
- cgroups
short_description: Profiles maximum memory usage of tasks and full execution using cgroups
description:
- This is an ansible callback plugin that profiles maximum memory usage of ansible and individual tasks, and displays a recap at the end using cgroups.
notes:
- Requires ansible to be run from within a cgroup, such as with C(cgexec -g memory:ansible_profile ansible-playbook ...).
- This cgroup should only be used by ansible to get accurate results.
- To create the cgroup, first use a command such as C(sudo cgcreate -a ec2-user:ec2-user -t ec2-user:ec2-user -g memory:ansible_profile).
options:
max_mem_file:
required: true
description: Path to cgroups C(memory.max_usage_in_bytes) file. Example V(/sys/fs/cgroup/memory/ansible_profile/memory.max_usage_in_bytes).
env:
- name: CGROUP_MAX_MEM_FILE
ini:
- section: callback_cgroupmemrecap
key: max_mem_file
cur_mem_file:
required: true
description: Path to C(memory.usage_in_bytes) file. Example V(/sys/fs/cgroup/memory/ansible_profile/memory.usage_in_bytes).
env:
- name: CGROUP_CUR_MEM_FILE
ini:
- section: callback_cgroupmemrecap
key: cur_mem_file
'''
import time
import threading
@@ -115,7 +112,7 @@ class CallbackModule(CallbackBase):
max_results = int(f.read().strip()) / 1024 / 1024
self._display.banner('CGROUP MEMORY RECAP')
self._display.display(f'Execution Maximum: {max_results:0.2f}MB\n\n')
self._display.display('Execution Maximum: %0.2fMB\n\n' % max_results)
for task, memory in self.task_results:
self._display.display(f'{task.get_name()} ({task._uuid}): {memory:0.2f}MB')
self._display.display('%s (%s): %0.2fMB' % (task.get_name(), task._uuid, memory))

View File

@@ -7,17 +7,17 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Unknown (!UNKNOWN)
name: context_demo
type: aggregate
short_description: demo callback that adds play/task context
description:
- Displays some play and task context along with normal output.
- This is mostly for demo purposes.
requirements:
- whitelist in configuration
"""
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: context_demo
type: aggregate
short_description: demo callback that adds play/task context
description:
- Displays some play and task context along with normal output.
- This is mostly for demo purposes.
requirements:
- whitelist in configuration
'''
from ansible.plugins.callback import CallbackBase
@@ -38,15 +38,15 @@ class CallbackModule(CallbackBase):
self.play = None
def v2_on_any(self, *args, **kwargs):
self._display.display(f"--- play: {getattr(self.play, 'name', None)} task: {self.task} ---")
self._display.display("--- play: {0} task: {1} ---".format(getattr(self.play, 'name', None), self.task))
self._display.display(" --- ARGS ")
for i, a in enumerate(args):
self._display.display(f' {i}: {a}')
self._display.display(' %s: %s' % (i, a))
self._display.display(" --- KWARGS ")
for k in kwargs:
self._display.display(f' {k}: {kwargs[k]}')
self._display.display(' %s: %s' % (k, kwargs[k]))
def v2_playbook_on_play_start(self, play):
self.play = play

View File

@@ -9,20 +9,20 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Unknown (!UNKNOWN)
name: counter_enabled
type: stdout
short_description: adds counters to the output items (tasks and hosts/task)
description:
- Use this callback when you need a kind of progress bar on a large environments.
- You will know how many tasks has the playbook to run, and which one is actually running.
- You will know how many hosts may run a task, and which of them is actually running.
extends_documentation_fragment:
- default_callback
requirements:
- set as stdout callback in C(ansible.cfg) (C(stdout_callback = counter_enabled))
"""
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: counter_enabled
type: stdout
short_description: adds counters to the output items (tasks and hosts/task)
description:
- Use this callback when you need a kind of progress bar on a large environments.
- You will know how many tasks has the playbook to run, and which one is actually running.
- You will know how many hosts may run a task, and which of them is actually running.
extends_documentation_fragment:
- default_callback
requirements:
- set as stdout callback in C(ansible.cfg) (C(stdout_callback = counter_enabled))
'''
from ansible import constants as C
from ansible.plugins.callback import CallbackBase
@@ -71,7 +71,7 @@ class CallbackModule(CallbackBase):
if not name:
msg = u"play"
else:
msg = f"PLAY [{name}]"
msg = u"PLAY [%s]" % name
self._play = play
@@ -91,17 +91,25 @@ class CallbackModule(CallbackBase):
for host in hosts:
stat = stats.summarize(host)
self._display.display(
f"{hostcolor(host, stat)} : {colorize('ok', stat['ok'], C.COLOR_OK)} {colorize('changed', stat['changed'], C.COLOR_CHANGED)} "
f"{colorize('unreachable', stat['unreachable'], C.COLOR_UNREACHABLE)} {colorize('failed', stat['failures'], C.COLOR_ERROR)} "
f"{colorize('rescued', stat['rescued'], C.COLOR_OK)} {colorize('ignored', stat['ignored'], C.COLOR_WARN)}",
self._display.display(u"%s : %s %s %s %s %s %s" % (
hostcolor(host, stat),
colorize(u'ok', stat['ok'], C.COLOR_OK),
colorize(u'changed', stat['changed'], C.COLOR_CHANGED),
colorize(u'unreachable', stat['unreachable'], C.COLOR_UNREACHABLE),
colorize(u'failed', stat['failures'], C.COLOR_ERROR),
colorize(u'rescued', stat['rescued'], C.COLOR_OK),
colorize(u'ignored', stat['ignored'], C.COLOR_WARN)),
screen_only=True
)
self._display.display(
f"{hostcolor(host, stat, False)} : {colorize('ok', stat['ok'], None)} {colorize('changed', stat['changed'], None)} "
f"{colorize('unreachable', stat['unreachable'], None)} {colorize('failed', stat['failures'], None)} "
f"{colorize('rescued', stat['rescued'], None)} {colorize('ignored', stat['ignored'], None)}",
self._display.display(u"%s : %s %s %s %s %s %s" % (
hostcolor(host, stat, False),
colorize(u'ok', stat['ok'], None),
colorize(u'changed', stat['changed'], None),
colorize(u'unreachable', stat['unreachable'], None),
colorize(u'failed', stat['failures'], None),
colorize(u'rescued', stat['rescued'], None),
colorize(u'ignored', stat['ignored'], None)),
log_only=True
)
@@ -116,14 +124,12 @@ class CallbackModule(CallbackBase):
for k in sorted(stats.custom.keys()):
if k == '_run':
continue
_custom_stats = self._dump_results(stats.custom[k], indent=1).replace('\n', '')
self._display.display(f'\t{k}: {_custom_stats}')
self._display.display('\t%s: %s' % (k, self._dump_results(stats.custom[k], indent=1).replace('\n', '')))
# print per run custom stats
if '_run' in stats.custom:
self._display.display("", screen_only=True)
_custom_stats_run = self._dump_results(stats.custom['_run'], indent=1).replace('\n', '')
self._display.display(f'\tRUN: {_custom_stats_run}')
self._display.display('\tRUN: %s' % self._dump_results(stats.custom['_run'], indent=1).replace('\n', ''))
self._display.display("", screen_only=True)
def v2_playbook_on_task_start(self, task, is_conditional):
@@ -137,13 +143,13 @@ class CallbackModule(CallbackBase):
# that they can secure this if they feel that their stdout is insecure
# (shoulder surfing, logging stdout straight to a file, etc).
if not task.no_log and C.DISPLAY_ARGS_TO_STDOUT:
args = ', '.join(('{k}={v}' for k, v in task.args.items()))
args = f' {args}'
self._display.banner(f"TASK {self._task_counter}/{self._task_total} [{task.get_name().strip()}{args}]")
args = ', '.join(('%s=%s' % a for a in task.args.items()))
args = ' %s' % args
self._display.banner("TASK %d/%d [%s%s]" % (self._task_counter, self._task_total, task.get_name().strip(), args))
if self._display.verbosity >= 2:
path = task.get_path()
if path:
self._display.display(f"task path: {path}", color=C.COLOR_DEBUG)
self._display.display("task path: %s" % path, color=C.COLOR_DEBUG)
self._host_counter = self._previous_batch_total
self._task_counter += 1
@@ -160,15 +166,15 @@ class CallbackModule(CallbackBase):
return
elif result._result.get('changed', False):
if delegated_vars:
msg = f"changed: {self._host_counter}/{self._host_total} [{result._host.get_name()} -> {delegated_vars['ansible_host']}]"
msg = "changed: %d/%d [%s -> %s]" % (self._host_counter, self._host_total, result._host.get_name(), delegated_vars['ansible_host'])
else:
msg = f"changed: {self._host_counter}/{self._host_total} [{result._host.get_name()}]"
msg = "changed: %d/%d [%s]" % (self._host_counter, self._host_total, result._host.get_name())
color = C.COLOR_CHANGED
else:
if delegated_vars:
msg = f"ok: {self._host_counter}/{self._host_total} [{result._host.get_name()} -> {delegated_vars['ansible_host']}]"
msg = "ok: %d/%d [%s -> %s]" % (self._host_counter, self._host_total, result._host.get_name(), delegated_vars['ansible_host'])
else:
msg = f"ok: {self._host_counter}/{self._host_total} [{result._host.get_name()}]"
msg = "ok: %d/%d [%s]" % (self._host_counter, self._host_total, result._host.get_name())
color = C.COLOR_OK
self._handle_warnings(result._result)
@@ -179,7 +185,7 @@ class CallbackModule(CallbackBase):
self._clean_results(result._result, result._task.action)
if self._run_is_verbose(result):
msg += f" => {self._dump_results(result._result)}"
msg += " => %s" % (self._dump_results(result._result),)
self._display.display(msg, color=color)
def v2_runner_on_failed(self, result, ignore_errors=False):
@@ -200,16 +206,14 @@ class CallbackModule(CallbackBase):
else:
if delegated_vars:
self._display.display(
f"fatal: {self._host_counter}/{self._host_total} [{result._host.get_name()} -> "
f"{delegated_vars['ansible_host']}]: FAILED! => {self._dump_results(result._result)}",
color=C.COLOR_ERROR
)
self._display.display("fatal: %d/%d [%s -> %s]: FAILED! => %s" % (self._host_counter, self._host_total,
result._host.get_name(), delegated_vars['ansible_host'],
self._dump_results(result._result)),
color=C.COLOR_ERROR)
else:
self._display.display(
f"fatal: {self._host_counter}/{self._host_total} [{result._host.get_name()}]: FAILED! => {self._dump_results(result._result)}",
color=C.COLOR_ERROR
)
self._display.display("fatal: %d/%d [%s]: FAILED! => %s" % (self._host_counter, self._host_total,
result._host.get_name(), self._dump_results(result._result)),
color=C.COLOR_ERROR)
if ignore_errors:
self._display.display("...ignoring", color=C.COLOR_SKIP)
@@ -227,9 +231,9 @@ class CallbackModule(CallbackBase):
if result._task.loop and 'results' in result._result:
self._process_items(result)
else:
msg = f"skipping: {self._host_counter}/{self._host_total} [{result._host.get_name()}]"
msg = "skipping: %d/%d [%s]" % (self._host_counter, self._host_total, result._host.get_name())
if self._run_is_verbose(result):
msg += f" => {self._dump_results(result._result)}"
msg += " => %s" % self._dump_results(result._result)
self._display.display(msg, color=C.COLOR_SKIP)
def v2_runner_on_unreachable(self, result):
@@ -240,13 +244,11 @@ class CallbackModule(CallbackBase):
delegated_vars = result._result.get('_ansible_delegated_vars', None)
if delegated_vars:
self._display.display(
f"fatal: {self._host_counter}/{self._host_total} [{result._host.get_name()} -> "
f"{delegated_vars['ansible_host']}]: UNREACHABLE! => {self._dump_results(result._result)}",
color=C.COLOR_UNREACHABLE
)
self._display.display("fatal: %d/%d [%s -> %s]: UNREACHABLE! => %s" % (self._host_counter, self._host_total,
result._host.get_name(), delegated_vars['ansible_host'],
self._dump_results(result._result)),
color=C.COLOR_UNREACHABLE)
else:
self._display.display(
f"fatal: {self._host_counter}/{self._host_total} [{result._host.get_name()}]: UNREACHABLE! => {self._dump_results(result._result)}",
color=C.COLOR_UNREACHABLE
)
self._display.display("fatal: %d/%d [%s]: UNREACHABLE! => %s" % (self._host_counter, self._host_total,
result._host.get_name(), self._dump_results(result._result)),
color=C.COLOR_UNREACHABLE)

View File

@@ -7,22 +7,23 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
name: default_without_diff
type: stdout
short_description: The default ansible callback without diff output
version_added: 8.4.0
description:
- This is basically the default ansible callback plugin (P(ansible.builtin.default#callback)) without showing diff output.
This can be useful when using another callback which sends more detailed information to another service, like the L(ARA,
https://ara.recordsansible.org/) callback, and you want diff output sent to that plugin but not shown on the console output.
author: Felix Fontein (@felixfontein)
extends_documentation_fragment:
- ansible.builtin.default_callback
- ansible.builtin.result_format_callback
"""
DOCUMENTATION = r'''
name: default_without_diff
type: stdout
short_description: The default ansible callback without diff output
version_added: 8.4.0
description:
- This is basically the default ansible callback plugin (P(ansible.builtin.default#callback)) without
showing diff output. This can be useful when using another callback which sends more detailed information
to another service, like the L(ARA, https://ara.recordsansible.org/) callback, and you want diff output
sent to that plugin but not shown on the console output.
author: Felix Fontein (@felixfontein)
extends_documentation_fragment:
- ansible.builtin.default_callback
- ansible.builtin.result_format_callback
'''
EXAMPLES = r"""
EXAMPLES = r'''
# Enable callback in ansible.cfg:
ansible_config: |
[defaults]
@@ -31,7 +32,7 @@ ansible_config: |
# Enable callback with environment variables:
environment_variable: |
ANSIBLE_STDOUT_CALLBACK=community.general.default_without_diff
"""
'''
from ansible.plugins.callback.default import CallbackModule as Default

View File

@@ -7,19 +7,19 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
DOCUMENTATION = '''
name: dense
type: stdout
short_description: minimal stdout output
extends_documentation_fragment:
- default_callback
- default_callback
description:
- When in verbose mode it will act the same as the default callback.
- When in verbose mode it will act the same as the default callback.
author:
- Dag Wieers (@dagwieers)
- Dag Wieers (@dagwieers)
requirements:
- set as stdout in configuration
"""
- set as stdout in configuration
'''
HAS_OD = False
try:
@@ -195,7 +195,7 @@ class CallbackModule(CallbackModule_default):
self.disabled = True
def __del__(self):
sys.stdout.write(f"{vt100.restore}{vt100.reset}\n{vt100.save}{vt100.clearline}")
sys.stdout.write(vt100.restore + vt100.reset + '\n' + vt100.save + vt100.clearline)
def _add_host(self, result, status):
name = result._host.get_name()
@@ -243,7 +243,7 @@ class CallbackModule(CallbackModule_default):
def _handle_exceptions(self, result):
if 'exception' in result:
# Remove the exception from the result so it is not shown every time
# Remove the exception from the result so it's not shown every time
del result['exception']
if self._display.verbosity == 1:
@@ -252,7 +252,7 @@ class CallbackModule(CallbackModule_default):
def _display_progress(self, result=None):
# Always rewrite the complete line
sys.stdout.write(vt100.restore + vt100.reset + vt100.clearline + vt100.nolinewrap + vt100.underline)
sys.stdout.write(f'{self.type} {self.count[self.type]}:')
sys.stdout.write('%s %d:' % (self.type, self.count[self.type]))
sys.stdout.write(vt100.reset)
sys.stdout.flush()
@@ -260,7 +260,7 @@ class CallbackModule(CallbackModule_default):
for name in self.hosts:
sys.stdout.write(' ')
if self.hosts[name].get('delegate', None):
sys.stdout.write(f"{self.hosts[name]['delegate']}>")
sys.stdout.write(self.hosts[name]['delegate'] + '>')
sys.stdout.write(colors[self.hosts[name]['state']] + name + vt100.reset)
sys.stdout.flush()
@@ -274,8 +274,8 @@ class CallbackModule(CallbackModule_default):
if not self.shown_title:
self.shown_title = True
sys.stdout.write(vt100.restore + vt100.reset + vt100.clearline + vt100.underline)
sys.stdout.write(f'{self.type} {self.count[self.type]}: {self.task.get_name().strip()}')
sys.stdout.write(f"{vt100.restore}{vt100.reset}\n{vt100.save}{vt100.clearline}")
sys.stdout.write('%s %d: %s' % (self.type, self.count[self.type], self.task.get_name().strip()))
sys.stdout.write(vt100.restore + vt100.reset + '\n' + vt100.save + vt100.clearline)
sys.stdout.flush()
else:
sys.stdout.write(vt100.restore + vt100.reset + vt100.clearline)
@@ -284,7 +284,7 @@ class CallbackModule(CallbackModule_default):
def _display_results(self, result, status):
# Leave the previous task on screen (as it has changes/errors)
if self._display.verbosity == 0 and self.keep:
sys.stdout.write(f"{vt100.restore}{vt100.reset}\n{vt100.save}{vt100.clearline}")
sys.stdout.write(vt100.restore + vt100.reset + '\n' + vt100.save + vt100.clearline)
else:
sys.stdout.write(vt100.restore + vt100.reset + vt100.clearline)
self.keep = False
@@ -309,15 +309,15 @@ class CallbackModule(CallbackModule_default):
if result._task.loop and 'results' in result._result:
self._process_items(result)
else:
sys.stdout.write(f"{colors[status] + status}: ")
sys.stdout.write(colors[status] + status + ': ')
delegated_vars = result._result.get('_ansible_delegated_vars', None)
if delegated_vars:
sys.stdout.write(f"{vt100.reset + result._host.get_name()}>{colors[status]}{delegated_vars['ansible_host']}")
sys.stdout.write(vt100.reset + result._host.get_name() + '>' + colors[status] + delegated_vars['ansible_host'])
else:
sys.stdout.write(result._host.get_name())
sys.stdout.write(f": {dump}\n")
sys.stdout.write(': ' + dump + '\n')
sys.stdout.write(vt100.reset + vt100.save + vt100.clearline)
sys.stdout.flush()
@@ -327,7 +327,7 @@ class CallbackModule(CallbackModule_default):
def v2_playbook_on_play_start(self, play):
# Leave the previous task on screen (as it has changes/errors)
if self._display.verbosity == 0 and self.keep:
sys.stdout.write(f"{vt100.restore}{vt100.reset}\n{vt100.save}{vt100.clearline}{vt100.bold}")
sys.stdout.write(vt100.restore + vt100.reset + '\n' + vt100.save + vt100.clearline + vt100.bold)
else:
sys.stdout.write(vt100.restore + vt100.reset + vt100.clearline + vt100.bold)
@@ -341,14 +341,14 @@ class CallbackModule(CallbackModule_default):
name = play.get_name().strip()
if not name:
name = 'unnamed'
sys.stdout.write(f"PLAY {self.count['play']}: {name.upper()}")
sys.stdout.write(f"{vt100.restore}{vt100.reset}\n{vt100.save}{vt100.clearline}")
sys.stdout.write('PLAY %d: %s' % (self.count['play'], name.upper()))
sys.stdout.write(vt100.restore + vt100.reset + '\n' + vt100.save + vt100.clearline)
sys.stdout.flush()
def v2_playbook_on_task_start(self, task, is_conditional):
# Leave the previous task on screen (as it has changes/errors)
if self._display.verbosity == 0 and self.keep:
sys.stdout.write(f"{vt100.restore}{vt100.reset}\n{vt100.save}{vt100.clearline}{vt100.underline}")
sys.stdout.write(vt100.restore + vt100.reset + '\n' + vt100.save + vt100.clearline + vt100.underline)
else:
# Do not clear line, since we want to retain the previous output
sys.stdout.write(vt100.restore + vt100.reset + vt100.underline)
@@ -365,14 +365,14 @@ class CallbackModule(CallbackModule_default):
self.count['task'] += 1
# Write the next task on screen (behind the prompt is the previous output)
sys.stdout.write(f'{self.type} {self.count[self.type]}.')
sys.stdout.write('%s %d.' % (self.type, self.count[self.type]))
sys.stdout.write(vt100.reset)
sys.stdout.flush()
def v2_playbook_on_handler_task_start(self, task):
# Leave the previous task on screen (as it has changes/errors)
if self._display.verbosity == 0 and self.keep:
sys.stdout.write(f"{vt100.restore}{vt100.reset}\n{vt100.save}{vt100.clearline}{vt100.underline}")
sys.stdout.write(vt100.restore + vt100.reset + '\n' + vt100.save + vt100.clearline + vt100.underline)
else:
sys.stdout.write(vt100.restore + vt100.reset + vt100.clearline + vt100.underline)
@@ -388,7 +388,7 @@ class CallbackModule(CallbackModule_default):
self.count[self.type] += 1
# Write the next task on screen (behind the prompt is the previous output)
sys.stdout.write(f'{self.type} {self.count[self.type]}.')
sys.stdout.write('%s %d.' % (self.type, self.count[self.type]))
sys.stdout.write(vt100.reset)
sys.stdout.flush()
@@ -451,13 +451,13 @@ class CallbackModule(CallbackModule_default):
def v2_playbook_on_no_hosts_remaining(self):
if self._display.verbosity == 0 and self.keep:
sys.stdout.write(f"{vt100.restore}{vt100.reset}\n{vt100.save}{vt100.clearline}")
sys.stdout.write(vt100.restore + vt100.reset + '\n' + vt100.save + vt100.clearline)
else:
sys.stdout.write(vt100.restore + vt100.reset + vt100.clearline)
self.keep = False
sys.stdout.write(f"{vt100.white + vt100.redbg}NO MORE HOSTS LEFT")
sys.stdout.write(f"{vt100.restore}{vt100.reset}\n{vt100.save}{vt100.clearline}")
sys.stdout.write(vt100.white + vt100.redbg + 'NO MORE HOSTS LEFT')
sys.stdout.write(vt100.restore + vt100.reset + '\n' + vt100.save + vt100.clearline)
sys.stdout.flush()
def v2_playbook_on_include(self, included_file):
@@ -465,7 +465,7 @@ class CallbackModule(CallbackModule_default):
def v2_playbook_on_stats(self, stats):
if self._display.verbosity == 0 and self.keep:
sys.stdout.write(f"{vt100.restore}{vt100.reset}\n{vt100.save}{vt100.clearline}")
sys.stdout.write(vt100.restore + vt100.reset + '\n' + vt100.save + vt100.clearline)
else:
sys.stdout.write(vt100.restore + vt100.reset + vt100.clearline)
@@ -476,16 +476,22 @@ class CallbackModule(CallbackModule_default):
sys.stdout.write(vt100.bold + vt100.underline)
sys.stdout.write('SUMMARY')
sys.stdout.write(f"{vt100.restore}{vt100.reset}\n{vt100.save}{vt100.clearline}")
sys.stdout.write(vt100.restore + vt100.reset + '\n' + vt100.save + vt100.clearline)
sys.stdout.flush()
hosts = sorted(stats.processed.keys())
for h in hosts:
t = stats.summarize(h)
self._display.display(
f"{hostcolor(h, t)} : {colorize('ok', t['ok'], C.COLOR_OK)} {colorize('changed', t['changed'], C.COLOR_CHANGED)} "
f"{colorize('unreachable', t['unreachable'], C.COLOR_UNREACHABLE)} {colorize('failed', t['failures'], C.COLOR_ERROR)} "
f"{colorize('rescued', t['rescued'], C.COLOR_OK)} {colorize('ignored', t['ignored'], C.COLOR_WARN)}",
u"%s : %s %s %s %s %s %s" % (
hostcolor(h, t),
colorize(u'ok', t['ok'], C.COLOR_OK),
colorize(u'changed', t['changed'], C.COLOR_CHANGED),
colorize(u'unreachable', t['unreachable'], C.COLOR_UNREACHABLE),
colorize(u'failed', t['failures'], C.COLOR_ERROR),
colorize(u'rescued', t['rescued'], C.COLOR_OK),
colorize(u'ignored', t['ignored'], C.COLOR_WARN),
),
screen_only=True
)

File diff suppressed because it is too large Load Diff

View File

@@ -5,69 +5,69 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Victor Martinez (@v1v) <VictorMartinezRubio@gmail.com>
name: elastic
type: notification
short_description: Create distributed traces for each Ansible task in Elastic APM
version_added: 3.8.0
description:
- This callback creates distributed traces for each Ansible task in Elastic APM.
- You can configure the plugin with environment variables.
- See U(https://www.elastic.co/guide/en/apm/agent/python/current/configuration.html).
options:
hide_task_arguments:
default: false
type: bool
DOCUMENTATION = '''
author: Victor Martinez (@v1v) <VictorMartinezRubio@gmail.com>
name: elastic
type: notification
short_description: Create distributed traces for each Ansible task in Elastic APM
version_added: 3.8.0
description:
- Hide the arguments for a task.
env:
- name: ANSIBLE_OPENTELEMETRY_HIDE_TASK_ARGUMENTS
apm_service_name:
default: ansible
type: str
description:
- The service name resource attribute.
env:
- name: ELASTIC_APM_SERVICE_NAME
apm_server_url:
type: str
description:
- Use the APM server and its environment variables.
env:
- name: ELASTIC_APM_SERVER_URL
apm_secret_token:
type: str
description:
- Use the APM server token.
env:
- name: ELASTIC_APM_SECRET_TOKEN
apm_api_key:
type: str
description:
- Use the APM API key.
env:
- name: ELASTIC_APM_API_KEY
apm_verify_server_cert:
default: true
type: bool
description:
- Verifies the SSL certificate if an HTTPS connection.
env:
- name: ELASTIC_APM_VERIFY_SERVER_CERT
traceparent:
type: str
description:
- The L(W3C Trace Context header traceparent,https://www.w3.org/TR/trace-context-1/#traceparent-header).
env:
- name: TRACEPARENT
requirements:
- elastic-apm (Python library)
"""
- This callback creates distributed traces for each Ansible task in Elastic APM.
- You can configure the plugin with environment variables.
- See U(https://www.elastic.co/guide/en/apm/agent/python/current/configuration.html).
options:
hide_task_arguments:
default: false
type: bool
description:
- Hide the arguments for a task.
env:
- name: ANSIBLE_OPENTELEMETRY_HIDE_TASK_ARGUMENTS
apm_service_name:
default: ansible
type: str
description:
- The service name resource attribute.
env:
- name: ELASTIC_APM_SERVICE_NAME
apm_server_url:
type: str
description:
- Use the APM server and its environment variables.
env:
- name: ELASTIC_APM_SERVER_URL
apm_secret_token:
type: str
description:
- Use the APM server token
env:
- name: ELASTIC_APM_SECRET_TOKEN
apm_api_key:
type: str
description:
- Use the APM API key
env:
- name: ELASTIC_APM_API_KEY
apm_verify_server_cert:
default: true
type: bool
description:
- Verifies the SSL certificate if an HTTPS connection.
env:
- name: ELASTIC_APM_VERIFY_SERVER_CERT
traceparent:
type: str
description:
- The L(W3C Trace Context header traceparent,https://www.w3.org/TR/trace-context-1/#traceparent-header).
env:
- name: TRACEPARENT
requirements:
- elastic-apm (Python library)
'''
EXAMPLES = r"""
examples: |-
EXAMPLES = '''
examples: |
Enable the plugin in ansible.cfg:
[defaults]
callbacks_enabled = community.general.elastic
@@ -76,7 +76,7 @@ examples: |-
export ELASTIC_APM_SERVER_URL=<your APM server URL)>
export ELASTIC_APM_SERVICE_NAME=your_service_name
export ELASTIC_APM_API_KEY=your_APM_API_KEY
"""
'''
import getpass
import socket
@@ -118,7 +118,7 @@ class TaskData:
if host.uuid in self.host_data:
if host.status == 'included':
# concatenate task include output from multiple items
host.result = f'{self.host_data[host.uuid].result}\n{host.result}'
host.result = '%s\n%s' % (self.host_data[host.uuid].result, host.result)
else:
return
@@ -166,7 +166,7 @@ class ElasticSource(object):
args = None
if not task.no_log and not hide_task_arguments:
args = ', '.join((f'{k}={v}' for k, v in task.args.items()))
args = ', '.join(('%s=%s' % a for a in task.args.items()))
tasks_data[uuid] = TaskData(uuid, name, path, play_name, action, args)
@@ -225,7 +225,7 @@ class ElasticSource(object):
def create_span_data(self, apm_cli, task_data, host_data):
""" create the span with the given TaskData and HostData """
name = f'[{host_data.name}] {task_data.play}: {task_data.name}'
name = '[%s] %s: %s' % (host_data.name, task_data.play, task_data.name)
message = "success"
status = "success"
@@ -259,7 +259,7 @@ class ElasticSource(object):
"ansible.task.host.status": host_data.status}) as span:
span.outcome = status
if 'failure' in status:
exception = AnsibleRuntimeError(message=f"{task_data.action}: {name} failed with error message {enriched_error_message}")
exception = AnsibleRuntimeError(message="{0}: {1} failed with error message {2}".format(task_data.action, name, enriched_error_message))
apm_cli.capture_exception(exc_info=(type(exception), exception, exception.__traceback__), handled=True)
def init_apm_client(self, apm_server_url, apm_service_name, apm_verify_server_cert, apm_secret_token, apm_api_key):
@@ -288,7 +288,7 @@ class ElasticSource(object):
message = result.get('msg', 'failed')
exception = result.get('exception')
stderr = result.get('stderr')
return f"message: \"{message}\"\nexception: \"{exception}\"\nstderr: \"{stderr}\""
return ('message: "{0}"\nexception: "{1}"\nstderr: "{2}"').format(message, exception, stderr)
class CallbackModule(CallbackBase):

233
plugins/callback/hipchat.py Normal file
View File

@@ -0,0 +1,233 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2014, Matt Martz <matt@sivel.net>
# Copyright (c) 2017 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
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: hipchat
type: notification
requirements:
- whitelist in configuration.
- prettytable (python lib)
short_description: post task events to hipchat
description:
- This callback plugin sends status updates to a HipChat channel during playbook execution.
- Before 2.4 only environment variables were available for configuring this plugin.
deprecated:
removed_in: 10.0.0
why: The hipchat service has been discontinued and the self-hosted variant has been End of Life since 2020.
alternative: There is none.
options:
token:
description: HipChat API token for v1 or v2 API.
required: true
env:
- name: HIPCHAT_TOKEN
ini:
- section: callback_hipchat
key: token
api_version:
description: HipChat API version, v1 or v2.
required: false
default: v1
env:
- name: HIPCHAT_API_VERSION
ini:
- section: callback_hipchat
key: api_version
room:
description: HipChat room to post in.
default: ansible
env:
- name: HIPCHAT_ROOM
ini:
- section: callback_hipchat
key: room
from:
description: Name to post as
default: ansible
env:
- name: HIPCHAT_FROM
ini:
- section: callback_hipchat
key: from
notify:
description: Add notify flag to important messages
type: bool
default: true
env:
- name: HIPCHAT_NOTIFY
ini:
- section: callback_hipchat
key: notify
'''
import os
import json
try:
import prettytable
HAS_PRETTYTABLE = True
except ImportError:
HAS_PRETTYTABLE = False
from ansible.plugins.callback import CallbackBase
from ansible.module_utils.six.moves.urllib.parse import urlencode
from ansible.module_utils.urls import open_url
class CallbackModule(CallbackBase):
"""This is an example ansible callback plugin that sends status
updates to a HipChat channel during playbook execution.
"""
CALLBACK_VERSION = 2.0
CALLBACK_TYPE = 'notification'
CALLBACK_NAME = 'community.general.hipchat'
CALLBACK_NEEDS_WHITELIST = True
API_V1_URL = 'https://api.hipchat.com/v1/rooms/message'
API_V2_URL = 'https://api.hipchat.com/v2/'
def __init__(self):
super(CallbackModule, self).__init__()
if not HAS_PRETTYTABLE:
self.disabled = True
self._display.warning('The `prettytable` python module is not installed. '
'Disabling the HipChat callback plugin.')
self.printed_playbook = False
self.playbook_name = None
self.play = None
def set_options(self, task_keys=None, var_options=None, direct=None):
super(CallbackModule, self).set_options(task_keys=task_keys, var_options=var_options, direct=direct)
self.token = self.get_option('token')
self.api_version = self.get_option('api_version')
self.from_name = self.get_option('from')
self.allow_notify = self.get_option('notify')
self.room = self.get_option('room')
if self.token is None:
self.disabled = True
self._display.warning('HipChat token could not be loaded. The HipChat '
'token can be provided using the `HIPCHAT_TOKEN` '
'environment variable.')
# Pick the request handler.
if self.api_version == 'v2':
self.send_msg = self.send_msg_v2
else:
self.send_msg = self.send_msg_v1
def send_msg_v2(self, msg, msg_format='text', color='yellow', notify=False):
"""Method for sending a message to HipChat"""
headers = {'Authorization': 'Bearer %s' % self.token, 'Content-Type': 'application/json'}
body = {}
body['room_id'] = self.room
body['from'] = self.from_name[:15] # max length is 15
body['message'] = msg
body['message_format'] = msg_format
body['color'] = color
body['notify'] = self.allow_notify and notify
data = json.dumps(body)
url = self.API_V2_URL + "room/{room_id}/notification".format(room_id=self.room)
try:
response = open_url(url, data=data, headers=headers, method='POST')
return response.read()
except Exception as ex:
self._display.warning('Could not submit message to hipchat: {0}'.format(ex))
def send_msg_v1(self, msg, msg_format='text', color='yellow', notify=False):
"""Method for sending a message to HipChat"""
params = {}
params['room_id'] = self.room
params['from'] = self.from_name[:15] # max length is 15
params['message'] = msg
params['message_format'] = msg_format
params['color'] = color
params['notify'] = int(self.allow_notify and notify)
url = ('%s?auth_token=%s' % (self.API_V1_URL, self.token))
try:
response = open_url(url, data=urlencode(params))
return response.read()
except Exception as ex:
self._display.warning('Could not submit message to hipchat: {0}'.format(ex))
def v2_playbook_on_play_start(self, play):
"""Display Playbook and play start messages"""
self.play = play
name = play.name
# This block sends information about a playbook when it starts
# The playbook object is not immediately available at
# playbook_on_start so we grab it via the play
#
# Displays info about playbook being started by a person on an
# inventory, as well as Tags, Skip Tags and Limits
if not self.printed_playbook:
self.playbook_name, dummy = os.path.splitext(os.path.basename(self.play.playbook.filename))
host_list = self.play.playbook.inventory.host_list
inventory = os.path.basename(os.path.realpath(host_list))
self.send_msg("%s: Playbook initiated by %s against %s" %
(self.playbook_name,
self.play.playbook.remote_user,
inventory), notify=True)
self.printed_playbook = True
subset = self.play.playbook.inventory._subset
skip_tags = self.play.playbook.skip_tags
self.send_msg("%s:\nTags: %s\nSkip Tags: %s\nLimit: %s" %
(self.playbook_name,
', '.join(self.play.playbook.only_tags),
', '.join(skip_tags) if skip_tags else None,
', '.join(subset) if subset else subset))
# This is where we actually say we are starting a play
self.send_msg("%s: Starting play: %s" %
(self.playbook_name, name))
def playbook_on_stats(self, stats):
"""Display info about playbook statistics"""
hosts = sorted(stats.processed.keys())
t = prettytable.PrettyTable(['Host', 'Ok', 'Changed', 'Unreachable',
'Failures'])
failures = False
unreachable = False
for h in hosts:
s = stats.summarize(h)
if s['failures'] > 0:
failures = True
if s['unreachable'] > 0:
unreachable = True
t.add_row([h] + [s[k] for k in ['ok', 'changed', 'unreachable',
'failures']])
self.send_msg("%s: Playbook complete" % self.playbook_name,
notify=True)
if failures or unreachable:
color = 'red'
self.send_msg("%s: Failures detected" % self.playbook_name,
color=color, notify=True)
else:
color = 'green'
self.send_msg("/code %s:\n%s" % (self.playbook_name, t), color=color)

View File

@@ -7,42 +7,38 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Unknown (!UNKNOWN)
name: jabber
type: notification
short_description: post task events to a Jabber server
description:
- The chatty part of ChatOps with a Hipchat server as a target.
- This callback plugin sends status updates to a HipChat channel during playbook execution.
requirements:
- xmpp (Python library U(https://github.com/ArchipelProject/xmpppy))
options:
server:
description: Connection info to Jabber server.
type: str
required: true
env:
- name: JABBER_SERV
user:
description: Jabber user to authenticate as.
type: str
required: true
env:
- name: JABBER_USER
password:
description: Password for the user to the Jabber server.
type: str
required: true
env:
- name: JABBER_PASS
to:
description: Chat identifier that will receive the message.
type: str
required: true
env:
- name: JABBER_TO
"""
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: jabber
type: notification
short_description: post task events to a jabber server
description:
- The chatty part of ChatOps with a Hipchat server as a target.
- This callback plugin sends status updates to a HipChat channel during playbook execution.
requirements:
- xmpp (Python library U(https://github.com/ArchipelProject/xmpppy))
options:
server:
description: connection info to jabber server
required: true
env:
- name: JABBER_SERV
user:
description: Jabber user to authenticate as
required: true
env:
- name: JABBER_USER
password:
description: Password for the user to the jabber server
required: true
env:
- name: JABBER_PASS
to:
description: chat identifier that will receive the message
required: true
env:
- name: JABBER_TO
'''
import os
@@ -102,7 +98,7 @@ class CallbackModule(CallbackBase):
"""Display Playbook and play start messages"""
self.play = play
name = play.name
self.send_msg(f"Ansible starting play: {name}")
self.send_msg("Ansible starting play: %s" % (name))
def playbook_on_stats(self, stats):
name = self.play
@@ -118,7 +114,7 @@ class CallbackModule(CallbackBase):
if failures or unreachable:
out = self.debug
self.send_msg(f"{name}: Failures detected \n{self.task} \nHost: {h}\n Failed at:\n{out}")
self.send_msg("%s: Failures detected \n%s \nHost: %s\n Failed at:\n%s" % (name, self.task, h, out))
else:
out = self.debug
self.send_msg(f"Great! \n Playbook {name} completed:\n{s} \n Last task debug:\n {out}")
self.send_msg("Great! \n Playbook %s completed:\n%s \n Last task debug:\n %s" % (name, s, out))

View File

@@ -7,27 +7,26 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Unknown (!UNKNOWN)
name: log_plays
type: notification
short_description: write playbook output to log file
description:
- This callback writes playbook output to a file per host in the C(/var/log/ansible/hosts) directory.
requirements:
- Whitelist in configuration
- A writeable C(/var/log/ansible/hosts) directory by the user executing Ansible on the controller
options:
log_folder:
default: /var/log/ansible/hosts
description: The folder where log files will be created.
type: str
env:
- name: ANSIBLE_LOG_FOLDER
ini:
- section: callback_log_plays
key: log_folder
"""
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: log_plays
type: notification
short_description: write playbook output to log file
description:
- This callback writes playbook output to a file per host in the C(/var/log/ansible/hosts) directory.
requirements:
- Whitelist in configuration
- A writeable C(/var/log/ansible/hosts) directory by the user executing Ansible on the controller
options:
log_folder:
default: /var/log/ansible/hosts
description: The folder where log files will be created.
env:
- name: ANSIBLE_LOG_FOLDER
ini:
- section: callback_log_plays
key: log_folder
'''
import os
import time
@@ -57,10 +56,7 @@ class CallbackModule(CallbackBase):
CALLBACK_NEEDS_WHITELIST = True
TIME_FORMAT = "%b %d %Y %H:%M:%S"
@staticmethod
def _make_msg(now, playbook, task_name, task_action, category, data):
return f"{now} - {playbook} - {task_name} - {task_action} - {category} - {data}\n\n"
MSG_FORMAT = "%(now)s - %(playbook)s - %(task_name)s - %(task_action)s - %(category)s - %(data)s\n\n"
def __init__(self):
@@ -85,12 +81,22 @@ class CallbackModule(CallbackBase):
invocation = data.pop('invocation', None)
data = json.dumps(data, cls=AnsibleJSONEncoder)
if invocation is not None:
data = f"{json.dumps(invocation)} => {data} "
data = json.dumps(invocation) + " => %s " % data
path = os.path.join(self.log_folder, result._host.get_name())
now = time.strftime(self.TIME_FORMAT, time.localtime())
msg = to_bytes(self._make_msg(now, self.playbook, result._task.name, result._task.action, category, data))
msg = to_bytes(
self.MSG_FORMAT
% dict(
now=now,
playbook=self.playbook,
task_name=result._task.name,
task_action=result._task.action,
category=category,
data=data,
)
)
with open(path, "ab") as fd:
fd.write(msg)

View File

@@ -6,41 +6,39 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
name: loganalytics
type: notification
short_description: Posts task results to Azure Log Analytics
author: "Cyrus Li (@zhcli) <cyrus1006@gmail.com>"
description:
- This callback plugin will post task results in JSON formatted to an Azure Log Analytics workspace.
- Credits to authors of splunk callback plugin.
version_added: "2.4.0"
requirements:
- Whitelisting this callback plugin.
- An Azure log analytics work space has been established.
options:
workspace_id:
description: Workspace ID of the Azure log analytics workspace.
type: str
required: true
env:
- name: WORKSPACE_ID
ini:
- section: callback_loganalytics
key: workspace_id
shared_key:
description: Shared key to connect to Azure log analytics workspace.
type: str
required: true
env:
- name: WORKSPACE_SHARED_KEY
ini:
- section: callback_loganalytics
key: shared_key
"""
DOCUMENTATION = '''
name: loganalytics
type: notification
short_description: Posts task results to Azure Log Analytics
author: "Cyrus Li (@zhcli) <cyrus1006@gmail.com>"
description:
- This callback plugin will post task results in JSON formatted to an Azure Log Analytics workspace.
- Credits to authors of splunk callback plugin.
version_added: "2.4.0"
requirements:
- Whitelisting this callback plugin.
- An Azure log analytics work space has been established.
options:
workspace_id:
description: Workspace ID of the Azure log analytics workspace.
required: true
env:
- name: WORKSPACE_ID
ini:
- section: callback_loganalytics
key: workspace_id
shared_key:
description: Shared key to connect to Azure log analytics workspace.
required: true
env:
- name: WORKSPACE_SHARED_KEY
ini:
- section: callback_loganalytics
key: shared_key
'''
EXAMPLES = r"""
examples: |-
EXAMPLES = '''
examples: |
Whitelist the plugin in ansible.cfg:
[defaults]
callback_whitelist = community.general.loganalytics
@@ -51,7 +49,7 @@ examples: |-
[callback_loganalytics]
workspace_id = 01234567-0123-0123-0123-01234567890a
shared_key = dZD0kCbKl3ehZG6LHFMuhtE0yHiFCmetzFMc2u+roXIUQuatqU924SsAAAAPemhjbGlAemhjbGktTUJQAQIDBA==
"""
'''
import hashlib
import hmac
@@ -84,17 +82,18 @@ class AzureLogAnalyticsSource(object):
def __build_signature(self, date, workspace_id, shared_key, content_length):
# Build authorisation signature for Azure log analytics API call
sigs = f"POST\n{content_length}\napplication/json\nx-ms-date:{date}\n/api/logs"
sigs = "POST\n{0}\napplication/json\nx-ms-date:{1}\n/api/logs".format(
str(content_length), date)
utf8_sigs = sigs.encode('utf-8')
decoded_shared_key = base64.b64decode(shared_key)
hmac_sha256_sigs = hmac.new(
decoded_shared_key, utf8_sigs, digestmod=hashlib.sha256).digest()
encoded_hash = base64.b64encode(hmac_sha256_sigs).decode('utf-8')
signature = f"SharedKey {workspace_id}:{encoded_hash}"
signature = "SharedKey {0}:{1}".format(workspace_id, encoded_hash)
return signature
def __build_workspace_url(self, workspace_id):
return f"https://{workspace_id}.ods.opinsights.azure.com/api/logs?api-version=2016-04-01"
return "https://{0}.ods.opinsights.azure.com/api/logs?api-version=2016-04-01".format(workspace_id)
def __rfc1123date(self):
return now().strftime('%a, %d %b %Y %H:%M:%S GMT')

View File

@@ -6,56 +6,56 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Unknown (!UNKNOWN)
name: logdna
type: notification
short_description: Sends playbook logs to LogDNA
description:
- This callback will report logs from playbook actions, tasks, and events to LogDNA (U(https://app.logdna.com)).
requirements:
- LogDNA Python Library (U(https://github.com/logdna/python))
- whitelisting in configuration
options:
conf_key:
required: true
description: LogDNA Ingestion Key.
type: string
env:
- name: LOGDNA_INGESTION_KEY
ini:
- section: callback_logdna
key: conf_key
plugin_ignore_errors:
required: false
description: Whether to ignore errors on failing or not.
type: boolean
env:
- name: ANSIBLE_IGNORE_ERRORS
ini:
- section: callback_logdna
key: plugin_ignore_errors
default: false
conf_hostname:
required: false
description: Alternative Host Name; the current host name by default.
type: string
env:
- name: LOGDNA_HOSTNAME
ini:
- section: callback_logdna
key: conf_hostname
conf_tags:
required: false
description: Tags.
type: string
env:
- name: LOGDNA_TAGS
ini:
- section: callback_logdna
key: conf_tags
default: ansible
"""
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: logdna
type: notification
short_description: Sends playbook logs to LogDNA
description:
- This callback will report logs from playbook actions, tasks, and events to LogDNA (U(https://app.logdna.com)).
requirements:
- LogDNA Python Library (U(https://github.com/logdna/python))
- whitelisting in configuration
options:
conf_key:
required: true
description: LogDNA Ingestion Key.
type: string
env:
- name: LOGDNA_INGESTION_KEY
ini:
- section: callback_logdna
key: conf_key
plugin_ignore_errors:
required: false
description: Whether to ignore errors on failing or not.
type: boolean
env:
- name: ANSIBLE_IGNORE_ERRORS
ini:
- section: callback_logdna
key: plugin_ignore_errors
default: false
conf_hostname:
required: false
description: Alternative Host Name; the current host name by default.
type: string
env:
- name: LOGDNA_HOSTNAME
ini:
- section: callback_logdna
key: conf_hostname
conf_tags:
required: false
description: Tags.
type: string
env:
- name: LOGDNA_TAGS
ini:
- section: callback_logdna
key: conf_tags
default: ansible
'''
import logging
import json
@@ -73,7 +73,7 @@ except ImportError:
# Getting MAC Address of system:
def get_mac():
mac = f"{getnode():012x}"
mac = "%012x" % getnode()
return ":".join(map(lambda index: mac[index:index + 2], range(int(len(mac) / 2))))
@@ -161,7 +161,7 @@ class CallbackModule(CallbackBase):
if ninvalidKeys > 0:
for key in invalidKeys:
del meta[key]
meta['__errors'] = f"These keys have been sanitized: {', '.join(invalidKeys)}"
meta['__errors'] = 'These keys have been sanitized: ' + ', '.join(invalidKeys)
return meta
def sanitizeJSON(self, data):

View File

@@ -6,77 +6,75 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Unknown (!UNKNOWN)
name: logentries
type: notification
short_description: Sends events to Logentries
description:
- This callback plugin will generate JSON objects and send them to Logentries using TCP for auditing/debugging purposes.
requirements:
- whitelisting in configuration
- certifi (Python library)
- flatdict (Python library), if you want to use the O(flatten) option
options:
api:
description: URI to the Logentries API.
type: str
env:
- name: LOGENTRIES_API
default: data.logentries.com
ini:
- section: callback_logentries
key: api
port:
description: HTTP port to use when connecting to the API.
type: int
env:
- name: LOGENTRIES_PORT
default: 80
ini:
- section: callback_logentries
key: port
tls_port:
description: Port to use when connecting to the API when TLS is enabled.
type: int
env:
- name: LOGENTRIES_TLS_PORT
default: 443
ini:
- section: callback_logentries
key: tls_port
token:
description: The logentries C(TCP token).
type: str
env:
- name: LOGENTRIES_ANSIBLE_TOKEN
required: true
ini:
- section: callback_logentries
key: token
use_tls:
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: logentries
type: notification
short_description: Sends events to Logentries
description:
- Toggle to decide whether to use TLS to encrypt the communications with the API server.
env:
- name: LOGENTRIES_USE_TLS
default: false
type: boolean
ini:
- section: callback_logentries
key: use_tls
flatten:
description: Flatten complex data structures into a single dictionary with complex keys.
type: boolean
default: false
env:
- name: LOGENTRIES_FLATTEN
ini:
- section: callback_logentries
key: flatten
"""
- This callback plugin will generate JSON objects and send them to Logentries via TCP for auditing/debugging purposes.
- Before 2.4, if you wanted to use an ini configuration, the file must be placed in the same directory as this plugin and named C(logentries.ini).
- In 2.4 and above you can just put it in the main Ansible configuration file.
requirements:
- whitelisting in configuration
- certifi (Python library)
- flatdict (Python library), if you want to use the O(flatten) option
options:
api:
description: URI to the Logentries API.
env:
- name: LOGENTRIES_API
default: data.logentries.com
ini:
- section: callback_logentries
key: api
port:
description: HTTP port to use when connecting to the API.
env:
- name: LOGENTRIES_PORT
default: 80
ini:
- section: callback_logentries
key: port
tls_port:
description: Port to use when connecting to the API when TLS is enabled.
env:
- name: LOGENTRIES_TLS_PORT
default: 443
ini:
- section: callback_logentries
key: tls_port
token:
description: The logentries C(TCP token).
env:
- name: LOGENTRIES_ANSIBLE_TOKEN
required: true
ini:
- section: callback_logentries
key: token
use_tls:
description:
- Toggle to decide whether to use TLS to encrypt the communications with the API server.
env:
- name: LOGENTRIES_USE_TLS
default: false
type: boolean
ini:
- section: callback_logentries
key: use_tls
flatten:
description: Flatten complex data structures into a single dictionary with complex keys.
type: boolean
default: false
env:
- name: LOGENTRIES_FLATTEN
ini:
- section: callback_logentries
key: flatten
'''
EXAMPLES = r"""
examples: >-
EXAMPLES = '''
examples: >
To enable, add this to your ansible.cfg file in the defaults block
[defaults]
@@ -95,7 +93,7 @@ examples: >-
use_tls = true
token = dd21fc88-f00a-43ff-b977-e3a4233c53af
flatten = false
"""
'''
import os
import socket
@@ -133,7 +131,7 @@ class PlainTextSocketAppender(object):
# Error message displayed when an incorrect Token has been detected
self.INVALID_TOKEN = "\n\nIt appears the LOGENTRIES_TOKEN parameter you entered is incorrect!\n\n"
# Unicode Line separator character \u2028
self.LINE_SEP = '\u2028'
self.LINE_SEP = u'\u2028'
self._display = display
self._conn = None
@@ -151,7 +149,7 @@ class PlainTextSocketAppender(object):
self.open_connection()
return
except Exception as e:
self._display.vvvv(f"Unable to connect to Logentries: {e}")
self._display.vvvv(u"Unable to connect to Logentries: %s" % to_text(e))
root_delay *= 2
if root_delay > self.MAX_DELAY:
@@ -160,7 +158,7 @@ class PlainTextSocketAppender(object):
wait_for = root_delay + random.uniform(0, root_delay)
try:
self._display.vvvv(f"sleeping {wait_for} before retry")
self._display.vvvv("sleeping %s before retry" % wait_for)
time.sleep(wait_for)
except KeyboardInterrupt:
raise
@@ -173,8 +171,8 @@ class PlainTextSocketAppender(object):
# Replace newlines with Unicode line separator
# for multi-line events
data = to_text(data, errors='surrogate_or_strict')
multiline = data.replace('\n', self.LINE_SEP)
multiline += "\n"
multiline = data.replace(u'\n', self.LINE_SEP)
multiline += u"\n"
# Send data, reconnect if needed
while True:
try:
@@ -247,7 +245,7 @@ class CallbackModule(CallbackBase):
self.use_tls = self.get_option('use_tls')
self.flatten = self.get_option('flatten')
except KeyError as e:
self._display.warning(f"Missing option for Logentries callback plugin: {e}")
self._display.warning(u"Missing option for Logentries callback plugin: %s" % to_text(e))
self.disabled = True
try:
@@ -266,10 +264,10 @@ class CallbackModule(CallbackBase):
if not self.disabled:
if self.use_tls:
self._display.vvvv(f"Connecting to {self.api_url}:{self.api_tls_port} with TLS")
self._display.vvvv("Connecting to %s:%s with TLS" % (self.api_url, self.api_tls_port))
self._appender = TLSSocketAppender(display=self._display, LE_API=self.api_url, LE_TLS_PORT=self.api_tls_port)
else:
self._display.vvvv(f"Connecting to {self.api_url}:{self.api_port}")
self._display.vvvv("Connecting to %s:%s" % (self.api_url, self.api_port))
self._appender = PlainTextSocketAppender(display=self._display, LE_API=self.api_url, LE_PORT=self.api_port)
self._appender.reopen_connection()
@@ -282,7 +280,7 @@ class CallbackModule(CallbackBase):
def emit(self, record):
msg = record.rstrip('\n')
msg = f"{self.token} {msg}"
msg = "{0} {1}".format(self.token, msg)
self._appender.put(msg)
self._display.vvvv("Sent event to logentries")

View File

@@ -7,94 +7,91 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Yevhen Khmelenko (@ujenmr)
name: logstash
type: notification
short_description: Sends events to Logstash
description:
- This callback will report facts and task events to Logstash U(https://www.elastic.co/products/logstash).
requirements:
- whitelisting in configuration
- logstash (Python library)
options:
server:
description: Address of the Logstash server.
type: str
env:
- name: LOGSTASH_SERVER
ini:
- section: callback_logstash
key: server
version_added: 1.0.0
default: localhost
port:
description: Port on which logstash is listening.
type: int
env:
- name: LOGSTASH_PORT
ini:
- section: callback_logstash
key: port
version_added: 1.0.0
default: 5000
type:
description: Message type.
type: str
env:
- name: LOGSTASH_TYPE
ini:
- section: callback_logstash
key: type
version_added: 1.0.0
default: ansible
pre_command:
description: Executes command before run and its result is added to the C(ansible_pre_command_output) logstash field.
type: str
version_added: 2.0.0
ini:
- section: callback_logstash
key: pre_command
env:
- name: LOGSTASH_PRE_COMMAND
format_version:
description: Logging format.
type: str
version_added: 2.0.0
ini:
- section: callback_logstash
key: format_version
env:
- name: LOGSTASH_FORMAT_VERSION
default: v1
choices:
- v1
- v2
"""
DOCUMENTATION = r'''
author: Yevhen Khmelenko (@ujenmr)
name: logstash
type: notification
short_description: Sends events to Logstash
description:
- This callback will report facts and task events to Logstash U(https://www.elastic.co/products/logstash).
requirements:
- whitelisting in configuration
- logstash (Python library)
options:
server:
description: Address of the Logstash server.
env:
- name: LOGSTASH_SERVER
ini:
- section: callback_logstash
key: server
version_added: 1.0.0
default: localhost
port:
description: Port on which logstash is listening.
env:
- name: LOGSTASH_PORT
ini:
- section: callback_logstash
key: port
version_added: 1.0.0
default: 5000
type:
description: Message type.
env:
- name: LOGSTASH_TYPE
ini:
- section: callback_logstash
key: type
version_added: 1.0.0
default: ansible
pre_command:
description: Executes command before run and its result is added to the C(ansible_pre_command_output) logstash field.
version_added: 2.0.0
ini:
- section: callback_logstash
key: pre_command
env:
- name: LOGSTASH_PRE_COMMAND
format_version:
description: Logging format.
type: str
version_added: 2.0.0
ini:
- section: callback_logstash
key: format_version
env:
- name: LOGSTASH_FORMAT_VERSION
default: v1
choices:
- v1
- v2
EXAMPLES = r"""
'''
EXAMPLES = r'''
ansible.cfg: |
# Enable Callback plugin
[defaults]
callback_whitelist = community.general.logstash
# Enable Callback plugin
[defaults]
callback_whitelist = community.general.logstash
[callback_logstash]
server = logstash.example.com
port = 5000
pre_command = git rev-parse HEAD
type = ansible
[callback_logstash]
server = logstash.example.com
port = 5000
pre_command = git rev-parse HEAD
type = ansible
11-input-tcp.conf: |-
# Enable Logstash TCP Input
input {
tcp {
port => 5000
codec => json
add_field => { "[@metadata][beat]" => "notify" }
add_field => { "[@metadata][type]" => "ansible" }
}
}
"""
11-input-tcp.conf: |
# Enable Logstash TCP Input
input {
tcp {
port => 5000
codec => json
add_field => { "[@metadata][beat]" => "notify" }
add_field => { "[@metadata][type]" => "ansible" }
}
}
'''
import os
import json

View File

@@ -7,80 +7,81 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
DOCUMENTATION = '''
name: mail
type: notification
short_description: Sends failure events through email
short_description: Sends failure events via email
description:
- This callback will report failures through email.
- This callback will report failures via email.
author:
- Dag Wieers (@dagwieers)
- Dag Wieers (@dagwieers)
requirements:
- whitelisting in configuration
- whitelisting in configuration
options:
mta:
description:
- Mail Transfer Agent, server that accepts SMTP.
- Mail Transfer Agent, server that accepts SMTP.
type: str
env:
- name: SMTPHOST
- name: SMTPHOST
ini:
- section: callback_mail
key: smtphost
- section: callback_mail
key: smtphost
default: localhost
mtaport:
description:
- Mail Transfer Agent Port.
- Port at which server SMTP.
- Mail Transfer Agent Port.
- Port at which server SMTP.
type: int
ini:
- section: callback_mail
key: smtpport
- section: callback_mail
key: smtpport
default: 25
to:
description:
- Mail recipient.
- Mail recipient.
type: list
elements: str
ini:
- section: callback_mail
key: to
- section: callback_mail
key: to
default: [root]
sender:
description:
- Mail sender.
- This is required since community.general 6.0.0.
- Mail sender.
- This is required since community.general 6.0.0.
type: str
required: true
ini:
- section: callback_mail
key: sender
- section: callback_mail
key: sender
cc:
description:
- CC'd recipients.
- CC'd recipients.
type: list
elements: str
ini:
- section: callback_mail
key: cc
- section: callback_mail
key: cc
bcc:
description:
- BCC'd recipients.
- BCC'd recipients.
type: list
elements: str
ini:
- section: callback_mail
key: bcc
- section: callback_mail
key: bcc
message_id_domain:
description:
- The domain name to use for the L(Message-ID header, https://en.wikipedia.org/wiki/Message-ID).
- The default is the hostname of the control node.
- The domain name to use for the L(Message-ID header, https://en.wikipedia.org/wiki/Message-ID).
- The default is the hostname of the control node.
type: str
ini:
- section: callback_mail
key: message_id_domain
- section: callback_mail
key: message_id_domain
version_added: 8.2.0
"""
'''
import json
import os
@@ -134,14 +135,14 @@ class CallbackModule(CallbackBase):
if self.bcc:
bcc_addresses = email.utils.getaddresses(self.bcc)
content = f'Date: {email.utils.formatdate()}\n'
content += f'From: {email.utils.formataddr(sender_address)}\n'
content = 'Date: %s\n' % email.utils.formatdate()
content += 'From: %s\n' % email.utils.formataddr(sender_address)
if self.to:
content += f"To: {', '.join([email.utils.formataddr(pair) for pair in to_addresses])}\n"
content += 'To: %s\n' % ', '.join([email.utils.formataddr(pair) for pair in to_addresses])
if self.cc:
content += f"Cc: {', '.join([email.utils.formataddr(pair) for pair in cc_addresses])}\n"
content += f"Message-ID: {email.utils.make_msgid(domain=self.get_option('message_id_domain'))}\n"
content += f'Subject: {subject.strip()}\n\n'
content += 'Cc: %s\n' % ', '.join([email.utils.formataddr(pair) for pair in cc_addresses])
content += 'Message-ID: %s\n' % email.utils.make_msgid(domain=self.get_option('message_id_domain'))
content += 'Subject: %s\n\n' % subject.strip()
content += body
addresses = to_addresses
@@ -158,22 +159,23 @@ class CallbackModule(CallbackBase):
smtp.quit()
def subject_msg(self, multiline, failtype, linenr):
msg = multiline.strip('\r\n').splitlines()[linenr]
return f'{failtype}: {msg}'
return '%s: %s' % (failtype, multiline.strip('\r\n').splitlines()[linenr])
def indent(self, multiline, indent=8):
return re.sub('^', ' ' * indent, multiline, flags=re.MULTILINE)
def body_blob(self, multiline, texttype):
''' Turn some text output in a well-indented block for sending in a mail body '''
intro = f'with the following {texttype}:\n\n'
blob = "\n".join(multiline.strip('\r\n').splitlines())
return f"{intro}{self.indent(blob)}\n"
intro = 'with the following %s:\n\n' % texttype
blob = ''
for line in multiline.strip('\r\n').splitlines():
blob += '%s\n' % line
return intro + self.indent(blob) + '\n'
def mail_result(self, result, failtype):
host = result._host.get_name()
if not self.sender:
self.sender = f'"Ansible: {host}" <root>'
self.sender = '"Ansible: %s" <root>' % host
# Add subject
if self.itembody:
@@ -189,32 +191,31 @@ class CallbackModule(CallbackBase):
elif result._result.get('exception'): # Unrelated exceptions are added to output :-/
subject = self.subject_msg(result._result['exception'], failtype, -1)
else:
subject = f'{failtype}: {result._task.name or result._task.action}'
subject = '%s: %s' % (failtype, result._task.name or result._task.action)
# Make playbook name visible (e.g. in Outlook/Gmail condensed view)
body = f'Playbook: {os.path.basename(self.playbook._file_name)}\n'
body = 'Playbook: %s\n' % os.path.basename(self.playbook._file_name)
if result._task.name:
body += f'Task: {result._task.name}\n'
body += f'Module: {result._task.action}\n'
body += f'Host: {host}\n'
body += 'Task: %s\n' % result._task.name
body += 'Module: %s\n' % result._task.action
body += 'Host: %s\n' % host
body += '\n'
# Add task information (as much as possible)
body += 'The following task failed:\n\n'
if 'invocation' in result._result:
body += self.indent(f"{result._task.action}: {json.dumps(result._result['invocation']['module_args'], indent=4)}\n")
body += self.indent('%s: %s\n' % (result._task.action, json.dumps(result._result['invocation']['module_args'], indent=4)))
elif result._task.name:
body += self.indent(f'{result._task.name} ({result._task.action})\n')
body += self.indent('%s (%s)\n' % (result._task.name, result._task.action))
else:
body += self.indent(f'{result._task.action}\n')
body += self.indent('%s\n' % result._task.action)
body += '\n'
# Add item / message
if self.itembody:
body += self.itembody
elif result._result.get('failed_when_result') is True:
fail_cond = self.indent('failed_when:\n- ' + '\n- '.join(result._task.failed_when))
body += f"due to the following condition:\n\n{fail_cond}\n\n"
body += "due to the following condition:\n\n" + self.indent('failed_when:\n- ' + '\n- '.join(result._task.failed_when)) + '\n\n'
elif result._result.get('msg'):
body += self.body_blob(result._result['msg'], 'message')
@@ -227,13 +228,13 @@ class CallbackModule(CallbackBase):
body += self.body_blob(result._result['exception'], 'exception')
if result._result.get('warnings'):
for i in range(len(result._result.get('warnings'))):
body += self.body_blob(result._result['warnings'][i], f'exception {i + 1}')
body += self.body_blob(result._result['warnings'][i], 'exception %d' % (i + 1))
if result._result.get('deprecations'):
for i in range(len(result._result.get('deprecations'))):
body += self.body_blob(result._result['deprecations'][i], f'exception {i + 1}')
body += self.body_blob(result._result['deprecations'][i], 'exception %d' % (i + 1))
body += 'and a complete dump of the error:\n\n'
body += self.indent(f'{failtype}: {json.dumps(result._result, cls=AnsibleJSONEncoder, indent=4)}')
body += self.indent('%s: %s' % (failtype, json.dumps(result._result, cls=AnsibleJSONEncoder, indent=4)))
self.mail(subject=subject, body=body)
@@ -256,4 +257,4 @@ class CallbackModule(CallbackBase):
def v2_runner_item_on_failed(self, result):
# Pass item information to task failure
self.itemsubject = result._result['msg']
self.itembody += self.body_blob(json.dumps(result._result, cls=AnsibleJSONEncoder, indent=4), f"failed item dump '{result._result['item']}'")
self.itembody += self.body_blob(json.dumps(result._result, cls=AnsibleJSONEncoder, indent=4), "failed item dump '%(item)s'" % result._result)

View File

@@ -7,65 +7,65 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
name: nrdp
type: notification
author: "Remi VERCHERE (@rverchere)"
short_description: Post task results to a Nagios server through nrdp
description:
- This callback send playbook result to Nagios.
- Nagios shall use NRDP to receive passive events.
- The passive check is sent to a dedicated host/service for Ansible.
options:
url:
description: URL of the nrdp server.
required: true
env:
- name: NRDP_URL
ini:
- section: callback_nrdp
key: url
type: string
validate_certs:
description: Validate the SSL certificate of the nrdp server. (Used for HTTPS URLs).
env:
- name: NRDP_VALIDATE_CERTS
ini:
- section: callback_nrdp
key: validate_nrdp_certs
- section: callback_nrdp
key: validate_certs
type: boolean
default: false
aliases: [validate_nrdp_certs]
token:
description: Token to be allowed to push nrdp events.
required: true
env:
- name: NRDP_TOKEN
ini:
- section: callback_nrdp
key: token
type: string
hostname:
description: Hostname where the passive check is linked to.
required: true
env:
- name: NRDP_HOSTNAME
ini:
- section: callback_nrdp
key: hostname
type: string
servicename:
description: Service where the passive check is linked to.
required: true
env:
- name: NRDP_SERVICENAME
ini:
- section: callback_nrdp
key: servicename
type: string
"""
DOCUMENTATION = '''
name: nrdp
type: notification
author: "Remi VERCHERE (@rverchere)"
short_description: Post task results to a Nagios server through nrdp
description:
- This callback send playbook result to Nagios.
- Nagios shall use NRDP to receive passive events.
- The passive check is sent to a dedicated host/service for Ansible.
options:
url:
description: URL of the nrdp server.
required: true
env:
- name : NRDP_URL
ini:
- section: callback_nrdp
key: url
type: string
validate_certs:
description: Validate the SSL certificate of the nrdp server. (Used for HTTPS URLs.)
env:
- name: NRDP_VALIDATE_CERTS
ini:
- section: callback_nrdp
key: validate_nrdp_certs
- section: callback_nrdp
key: validate_certs
type: boolean
default: false
aliases: [ validate_nrdp_certs ]
token:
description: Token to be allowed to push nrdp events.
required: true
env:
- name: NRDP_TOKEN
ini:
- section: callback_nrdp
key: token
type: string
hostname:
description: Hostname where the passive check is linked to.
required: true
env:
- name : NRDP_HOSTNAME
ini:
- section: callback_nrdp
key: hostname
type: string
servicename:
description: Service where the passive check is linked to.
required: true
env:
- name : NRDP_SERVICENAME
ini:
- section: callback_nrdp
key: servicename
type: string
'''
from ansible.module_utils.six.moves.urllib.parse import urlencode
from ansible.module_utils.common.text.converters import to_bytes
@@ -132,10 +132,10 @@ class CallbackModule(CallbackBase):
xmldata = "<?xml version='1.0'?>\n"
xmldata += "<checkresults>\n"
xmldata += "<checkresult type='service'>\n"
xmldata += f"<hostname>{self.hostname}</hostname>\n"
xmldata += f"<servicename>{self.servicename}</servicename>\n"
xmldata += f"<state>{state}</state>\n"
xmldata += f"<output>{msg}</output>\n"
xmldata += "<hostname>%s</hostname>\n" % self.hostname
xmldata += "<servicename>%s</servicename>\n" % self.servicename
xmldata += "<state>%d</state>\n" % state
xmldata += "<output>%s</output>\n" % msg
xmldata += "</checkresult>\n"
xmldata += "</checkresults>\n"
@@ -152,7 +152,7 @@ class CallbackModule(CallbackBase):
validate_certs=self.validate_nrdp_certs)
return response.read()
except Exception as ex:
self._display.warning(f"NRDP callback cannot send result {ex}")
self._display.warning("NRDP callback cannot send result {0}".format(ex))
def v2_playbook_on_play_start(self, play):
'''
@@ -170,16 +170,17 @@ class CallbackModule(CallbackBase):
critical = warning = 0
for host in hosts:
stat = stats.summarize(host)
gstats += (
f"'{host}_ok'={stat['ok']} '{host}_changed'={stat['changed']} '{host}_unreachable'={stat['unreachable']} '{host}_failed'={stat['failures']} "
)
gstats += "'%s_ok'=%d '%s_changed'=%d \
'%s_unreachable'=%d '%s_failed'=%d " % \
(host, stat['ok'], host, stat['changed'],
host, stat['unreachable'], host, stat['failures'])
# Critical when failed tasks or unreachable host
critical += stat['failures']
critical += stat['unreachable']
# Warning when changed tasks
warning += stat['changed']
msg = f"{name} | {gstats}"
msg = "%s | %s" % (name, gstats)
if critical:
# Send Critical
self._send_nrdp(self.CRITICAL, msg)

View File

@@ -7,16 +7,16 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Unknown (!UNKNOWN)
name: 'null'
type: stdout
requirements:
- set as main display callback
short_description: do not display stuff to screen
description:
- This callback prevents outputting events to screen.
"""
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: 'null'
type: stdout
requirements:
- set as main display callback
short_description: Don't display stuff to screen
description:
- This callback prevents outputting events to screen.
'''
from ansible.plugins.callback import CallbackBase

View File

@@ -6,120 +6,93 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Victor Martinez (@v1v) <VictorMartinezRubio@gmail.com>
name: opentelemetry
type: notification
short_description: Create distributed traces with OpenTelemetry
version_added: 3.7.0
description:
- This callback creates distributed traces for each Ansible task with OpenTelemetry.
- You can configure the OpenTelemetry exporter and SDK with environment variables.
- See U(https://opentelemetry-python.readthedocs.io/en/latest/exporter/otlp/otlp.html).
- See
U(https://opentelemetry-python.readthedocs.io/en/latest/sdk/environment_variables.html#opentelemetry-sdk-environment-variables).
options:
hide_task_arguments:
default: false
type: bool
DOCUMENTATION = '''
author: Victor Martinez (@v1v) <VictorMartinezRubio@gmail.com>
name: opentelemetry
type: notification
short_description: Create distributed traces with OpenTelemetry
version_added: 3.7.0
description:
- Hide the arguments for a task.
env:
- name: ANSIBLE_OPENTELEMETRY_HIDE_TASK_ARGUMENTS
ini:
- section: callback_opentelemetry
key: hide_task_arguments
version_added: 5.3.0
enable_from_environment:
type: str
description:
- Whether to enable this callback only if the given environment variable exists and it is set to V(true).
- This is handy when you use Configuration as Code and want to send distributed traces if running in the CI rather when
running Ansible locally.
- For such, it evaluates the given O(enable_from_environment) value as environment variable and if set to true this
plugin will be enabled.
env:
- name: ANSIBLE_OPENTELEMETRY_ENABLE_FROM_ENVIRONMENT
ini:
- section: callback_opentelemetry
key: enable_from_environment
version_added: 5.3.0
version_added: 3.8.0
otel_service_name:
default: ansible
type: str
description:
- The service name resource attribute.
env:
- name: OTEL_SERVICE_NAME
ini:
- section: callback_opentelemetry
key: otel_service_name
version_added: 5.3.0
traceparent:
default: None
type: str
description:
- The L(W3C Trace Context header traceparent,https://www.w3.org/TR/trace-context-1/#traceparent-header).
env:
- name: TRACEPARENT
disable_logs:
default: false
type: bool
description:
- Disable sending logs.
env:
- name: ANSIBLE_OPENTELEMETRY_DISABLE_LOGS
ini:
- section: callback_opentelemetry
key: disable_logs
version_added: 5.8.0
disable_attributes_in_logs:
default: false
type: bool
description:
- Disable populating span attributes to the logs.
env:
- name: ANSIBLE_OPENTELEMETRY_DISABLE_ATTRIBUTES_IN_LOGS
ini:
- section: callback_opentelemetry
key: disable_attributes_in_logs
version_added: 7.1.0
store_spans_in_file:
type: str
description:
- It stores the exported spans in the given file.
env:
- name: ANSIBLE_OPENTELEMETRY_STORE_SPANS_IN_FILE
ini:
- section: callback_opentelemetry
key: store_spans_in_file
version_added: 9.0.0
otel_exporter_otlp_traces_protocol:
type: str
description:
- E(OTEL_EXPORTER_OTLP_TRACES_PROTOCOL) represents the the transport protocol for spans.
- See
U(https://opentelemetry-python.readthedocs.io/en/latest/sdk/environment_variables.html#envvar-OTEL_EXPORTER_OTLP_TRACES_PROTOCOL).
default: grpc
choices:
- grpc
- http/protobuf
env:
- name: OTEL_EXPORTER_OTLP_TRACES_PROTOCOL
ini:
- section: callback_opentelemetry
key: otel_exporter_otlp_traces_protocol
version_added: 9.0.0
requirements:
- opentelemetry-api (Python library)
- opentelemetry-exporter-otlp (Python library)
- opentelemetry-sdk (Python library)
"""
- This callback creates distributed traces for each Ansible task with OpenTelemetry.
- You can configure the OpenTelemetry exporter and SDK with environment variables.
- See U(https://opentelemetry-python.readthedocs.io/en/latest/exporter/otlp/otlp.html).
- See U(https://opentelemetry-python.readthedocs.io/en/latest/sdk/environment_variables.html#opentelemetry-sdk-environment-variables).
options:
hide_task_arguments:
default: false
type: bool
description:
- Hide the arguments for a task.
env:
- name: ANSIBLE_OPENTELEMETRY_HIDE_TASK_ARGUMENTS
ini:
- section: callback_opentelemetry
key: hide_task_arguments
version_added: 5.3.0
enable_from_environment:
type: str
description:
- Whether to enable this callback only if the given environment variable exists and it is set to V(true).
- This is handy when you use Configuration as Code and want to send distributed traces
if running in the CI rather when running Ansible locally.
- For such, it evaluates the given O(enable_from_environment) value as environment variable
and if set to true this plugin will be enabled.
env:
- name: ANSIBLE_OPENTELEMETRY_ENABLE_FROM_ENVIRONMENT
ini:
- section: callback_opentelemetry
key: enable_from_environment
version_added: 5.3.0
version_added: 3.8.0
otel_service_name:
default: ansible
type: str
description:
- The service name resource attribute.
env:
- name: OTEL_SERVICE_NAME
ini:
- section: callback_opentelemetry
key: otel_service_name
version_added: 5.3.0
traceparent:
default: None
type: str
description:
- The L(W3C Trace Context header traceparent,https://www.w3.org/TR/trace-context-1/#traceparent-header).
env:
- name: TRACEPARENT
disable_logs:
default: false
type: bool
description:
- Disable sending logs.
env:
- name: ANSIBLE_OPENTELEMETRY_DISABLE_LOGS
ini:
- section: callback_opentelemetry
key: disable_logs
version_added: 5.8.0
disable_attributes_in_logs:
default: false
type: bool
description:
- Disable populating span attributes to the logs.
env:
- name: ANSIBLE_OPENTELEMETRY_DISABLE_ATTRIBUTES_IN_LOGS
ini:
- section: callback_opentelemetry
key: disable_attributes_in_logs
version_added: 7.1.0
requirements:
- opentelemetry-api (Python library)
- opentelemetry-exporter-otlp (Python library)
- opentelemetry-sdk (Python library)
'''
EXAMPLES = r"""
examples: |-
EXAMPLES = '''
examples: |
Enable the plugin in ansible.cfg:
[defaults]
callbacks_enabled = community.general.opentelemetry
@@ -131,14 +104,14 @@ examples: |-
export OTEL_EXPORTER_OTLP_HEADERS="authorization=Bearer your_otel_token"
export OTEL_SERVICE_NAME=your_service_name
export ANSIBLE_OPENTELEMETRY_ENABLED=true
"""
'''
import getpass
import json
import os
import socket
import sys
import time
import uuid
from time import time_ns
from collections import OrderedDict
from os.path import basename
@@ -151,25 +124,40 @@ from ansible.plugins.callback import CallbackBase
try:
from opentelemetry import trace
from opentelemetry.trace import SpanKind
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter as GRPCOTLPSpanExporter
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter as HTTPOTLPSpanExporter
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
from opentelemetry.trace.status import Status, StatusCode
from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import (
BatchSpanProcessor,
SimpleSpanProcessor
)
from opentelemetry.sdk.trace.export.in_memory_span_exporter import (
InMemorySpanExporter
BatchSpanProcessor
)
# Support for opentelemetry-api <= 1.12
try:
from opentelemetry.util._time import _time_ns
except ImportError as imp_exc:
OTEL_LIBRARY_TIME_NS_ERROR = imp_exc
else:
OTEL_LIBRARY_TIME_NS_ERROR = None
except ImportError as imp_exc:
OTEL_LIBRARY_IMPORT_ERROR = imp_exc
OTEL_LIBRARY_TIME_NS_ERROR = imp_exc
else:
OTEL_LIBRARY_IMPORT_ERROR = None
if sys.version_info >= (3, 7):
time_ns = time.time_ns
elif not OTEL_LIBRARY_TIME_NS_ERROR:
time_ns = _time_ns
else:
def time_ns():
# Support versions older than 3.7 with opentelemetry-api > 1.12
return int(time.time() * 1e9)
class TaskData:
"""
Data about an individual task.
@@ -190,7 +178,7 @@ class TaskData:
if host.uuid in self.host_data:
if host.status == 'included':
# concatenate task include output from multiple items
host.result = f'{self.host_data[host.uuid].result}\n{host.result}'
host.result = '%s\n%s' % (self.host_data[host.uuid].result, host.result)
else:
return
@@ -267,16 +255,7 @@ class OpenTelemetrySource(object):
task.dump = dump
task.add_host(HostData(host_uuid, host_name, status, result))
def generate_distributed_traces(self,
otel_service_name,
ansible_playbook,
tasks_data,
status,
traceparent,
disable_logs,
disable_attributes_in_logs,
otel_exporter_otlp_traces_protocol,
store_spans_in_file):
def generate_distributed_traces(self, otel_service_name, ansible_playbook, tasks_data, status, traceparent, disable_logs, disable_attributes_in_logs):
""" generate distributed traces from the collected TaskData and HostData """
tasks = []
@@ -292,16 +271,7 @@ class OpenTelemetrySource(object):
)
)
otel_exporter = None
if store_spans_in_file:
otel_exporter = InMemorySpanExporter()
processor = SimpleSpanProcessor(otel_exporter)
else:
if otel_exporter_otlp_traces_protocol == 'grpc':
otel_exporter = GRPCOTLPSpanExporter()
else:
otel_exporter = HTTPOTLPSpanExporter()
processor = BatchSpanProcessor(otel_exporter)
processor = BatchSpanProcessor(OTLPSpanExporter())
trace.get_tracer_provider().add_span_processor(processor)
@@ -323,12 +293,10 @@ class OpenTelemetrySource(object):
with tracer.start_as_current_span(task.name, start_time=task.start, end_on_exit=False) as span:
self.update_span_data(task, host_data, span, disable_logs, disable_attributes_in_logs)
return otel_exporter
def update_span_data(self, task_data, host_data, span, disable_logs, disable_attributes_in_logs):
""" update the span with the given TaskData and HostData """
name = f'[{host_data.name}] {task_data.play}: {task_data.name}'
name = '[%s] %s: %s' % (host_data.name, task_data.play, task_data.name)
message = 'success'
res = {}
@@ -336,7 +304,6 @@ class OpenTelemetrySource(object):
status = Status(status_code=StatusCode.OK)
if host_data.status != 'included':
# Support loops
enriched_error_message = None
if 'results' in host_data.result._result:
if host_data.status == 'failed':
message = self.get_error_message_from_results(host_data.result._result['results'], task_data.action)
@@ -451,7 +418,7 @@ class OpenTelemetrySource(object):
def get_error_message_from_results(results, action):
for result in results:
if result.get('failed', False):
return f"{action}({result.get('item', 'none')}) - {OpenTelemetrySource.get_error_message(result)}"
return ('{0}({1}) - {2}').format(action, result.get('item', 'none'), OpenTelemetrySource.get_error_message(result))
@staticmethod
def _last_line(text):
@@ -463,14 +430,14 @@ class OpenTelemetrySource(object):
message = result.get('msg', 'failed')
exception = result.get('exception')
stderr = result.get('stderr')
return f"message: \"{message}\"\nexception: \"{exception}\"\nstderr: \"{stderr}\""
return ('message: "{0}"\nexception: "{1}"\nstderr: "{2}"').format(message, exception, stderr)
@staticmethod
def enrich_error_message_from_results(results, action):
message = ""
for result in results:
if result.get('failed', False):
message = f"{action}({result.get('item', 'none')}) - {OpenTelemetrySource.enrich_error_message(result)}\n{message}"
message = ('{0}({1}) - {2}\n{3}').format(action, result.get('item', 'none'), OpenTelemetrySource.enrich_error_message(result), message)
return message
@@ -496,8 +463,6 @@ class CallbackModule(CallbackBase):
self.errors = 0
self.disabled = False
self.traceparent = False
self.store_spans_in_file = False
self.otel_exporter_otlp_traces_protocol = None
if OTEL_LIBRARY_IMPORT_ERROR:
raise_from(
@@ -516,9 +481,8 @@ class CallbackModule(CallbackBase):
environment_variable = self.get_option('enable_from_environment')
if environment_variable is not None and os.environ.get(environment_variable, 'false').lower() != 'true':
self.disabled = True
self._display.warning(
f"The `enable_from_environment` option has been set and {environment_variable} is not enabled. Disabling the `opentelemetry` callback plugin."
)
self._display.warning("The `enable_from_environment` option has been set and {0} is not enabled. "
"Disabling the `opentelemetry` callback plugin.".format(environment_variable))
self.hide_task_arguments = self.get_option('hide_task_arguments')
@@ -526,8 +490,6 @@ class CallbackModule(CallbackBase):
self.disable_logs = self.get_option('disable_logs')
self.store_spans_in_file = self.get_option('store_spans_in_file')
self.otel_service_name = self.get_option('otel_service_name')
if not self.otel_service_name:
@@ -536,8 +498,6 @@ class CallbackModule(CallbackBase):
# See https://github.com/open-telemetry/opentelemetry-specification/issues/740
self.traceparent = self.get_option('traceparent')
self.otel_exporter_otlp_traces_protocol = self.get_option('otel_exporter_otlp_traces_protocol')
def dump_results(self, task, result):
""" dump the results if disable_logs is not enabled """
if self.disable_logs:
@@ -633,22 +593,15 @@ class CallbackModule(CallbackBase):
status = Status(status_code=StatusCode.OK)
else:
status = Status(status_code=StatusCode.ERROR)
otel_exporter = self.opentelemetry.generate_distributed_traces(
self.opentelemetry.generate_distributed_traces(
self.otel_service_name,
self.ansible_playbook,
self.tasks_data,
status,
self.traceparent,
self.disable_logs,
self.disable_attributes_in_logs,
self.otel_exporter_otlp_traces_protocol,
self.store_spans_in_file
self.disable_attributes_in_logs
)
if self.store_spans_in_file:
spans = [json.loads(span.to_json()) for span in otel_exporter.get_finished_spans()]
with open(self.store_spans_in_file, "w", encoding="utf-8") as output:
json.dump({"spans": spans}, output, indent=4)
def v2_runner_on_async_failed(self, result, **kwargs):
self.errors += 1

View File

@@ -8,17 +8,17 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Unknown (!UNKNOWN)
name: say
type: notification
requirements:
- whitelisting in configuration
- the C(/usr/bin/say) command line program (standard on macOS) or C(espeak) command line program
short_description: notify using software speech synthesizer
description:
- This plugin will use the C(say) or C(espeak) program to "speak" about play events.
"""
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: say
type: notification
requirements:
- whitelisting in configuration
- the C(/usr/bin/say) command line program (standard on macOS) or C(espeak) command line program
short_description: notify using software speech synthesizer
description:
- This plugin will use the C(say) or C(espeak) program to "speak" about play events.
'''
import platform
import subprocess
@@ -50,7 +50,7 @@ class CallbackModule(CallbackBase):
self.synthesizer = get_bin_path('say')
if platform.system() != 'Darwin':
# 'say' binary available, it might be GNUstep tool which doesn't support 'voice' parameter
self._display.warning(f"'say' executable found but system is '{platform.system()}': ignoring voice parameter")
self._display.warning("'say' executable found but system is '%s': ignoring voice parameter" % platform.system())
else:
self.FAILED_VOICE = 'Zarvox'
self.REGULAR_VOICE = 'Trinoids'
@@ -69,7 +69,7 @@ class CallbackModule(CallbackBase):
# ansible will not call any callback if disabled is set to True
if not self.synthesizer:
self.disabled = True
self._display.warning(f"Unable to find either 'say' or 'espeak' executable, plugin {os.path.basename(__file__)} disabled")
self._display.warning("Unable to find either 'say' or 'espeak' executable, plugin %s disabled" % os.path.basename(__file__))
def say(self, msg, voice):
cmd = [self.synthesizer, msg]
@@ -78,7 +78,7 @@ class CallbackModule(CallbackBase):
subprocess.call(cmd)
def runner_on_failed(self, host, res, ignore_errors=False):
self.say(f"Failure on host {host}", self.FAILED_VOICE)
self.say("Failure on host %s" % host, self.FAILED_VOICE)
def runner_on_ok(self, host, res):
self.say("pew", self.LASER_VOICE)
@@ -87,13 +87,13 @@ class CallbackModule(CallbackBase):
self.say("pew", self.LASER_VOICE)
def runner_on_unreachable(self, host, res):
self.say(f"Failure on host {host}", self.FAILED_VOICE)
self.say("Failure on host %s" % host, self.FAILED_VOICE)
def runner_on_async_ok(self, host, res, jid):
self.say("pew", self.LASER_VOICE)
def runner_on_async_failed(self, host, res, jid):
self.say(f"Failure on host {host}", self.FAILED_VOICE)
self.say("Failure on host %s" % host, self.FAILED_VOICE)
def playbook_on_start(self):
self.say("Running Playbook", self.REGULAR_VOICE)
@@ -103,15 +103,15 @@ class CallbackModule(CallbackBase):
def playbook_on_task_start(self, name, is_conditional):
if not is_conditional:
self.say(f"Starting task: {name}", self.REGULAR_VOICE)
self.say("Starting task: %s" % name, self.REGULAR_VOICE)
else:
self.say(f"Notifying task: {name}", self.REGULAR_VOICE)
self.say("Notifying task: %s" % name, self.REGULAR_VOICE)
def playbook_on_setup(self):
self.say("Gathering facts", self.REGULAR_VOICE)
def playbook_on_play_start(self, name):
self.say(f"Starting play: {name}", self.HAPPY_VOICE)
self.say("Starting play: %s" % name, self.HAPPY_VOICE)
def playbook_on_stats(self, stats):
self.say("Play complete", self.HAPPY_VOICE)

View File

@@ -7,35 +7,35 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Unknown (!UNKNOWN)
name: selective
type: stdout
requirements:
- set as main display callback
short_description: only print certain tasks
description:
- This callback only prints tasks that have been tagged with C(print_action) or that have failed. This allows operators
to focus on the tasks that provide value only.
- Tasks that are not printed are placed with a C(.).
- If you increase verbosity all tasks are printed.
options:
nocolor:
default: false
description: This setting allows suppressing colorizing output.
env:
- name: ANSIBLE_NOCOLOR
- name: ANSIBLE_SELECTIVE_DONT_COLORIZE
ini:
- section: defaults
key: nocolor
type: boolean
"""
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: selective
type: stdout
requirements:
- set as main display callback
short_description: only print certain tasks
description:
- This callback only prints tasks that have been tagged with C(print_action) or that have failed.
This allows operators to focus on the tasks that provide value only.
- Tasks that are not printed are placed with a C(.).
- If you increase verbosity all tasks are printed.
options:
nocolor:
default: false
description: This setting allows suppressing colorizing output.
env:
- name: ANSIBLE_NOCOLOR
- name: ANSIBLE_SELECTIVE_DONT_COLORIZE
ini:
- section: defaults
key: nocolor
type: boolean
'''
EXAMPLES = r"""
- ansible.builtin.debug: msg="This will not be printed"
- ansible.builtin.debug: msg="But this will"
tags: [print_action]
EXAMPLES = """
- ansible.builtin.debug: msg="This will not be printed"
- ansible.builtin.debug: msg="But this will"
tags: [print_action]
"""
import difflib
@@ -48,13 +48,13 @@ from ansible.module_utils.common.text.converters import to_text
DONT_COLORIZE = False
COLORS = {
'normal': '\033[0m',
'ok': f'\x1b[{C.COLOR_CODES[C.COLOR_OK]}m',
'ok': '\033[{0}m'.format(C.COLOR_CODES[C.COLOR_OK]),
'bold': '\033[1m',
'not_so_bold': '\033[1m\033[34m',
'changed': f'\x1b[{C.COLOR_CODES[C.COLOR_CHANGED]}m',
'failed': f'\x1b[{C.COLOR_CODES[C.COLOR_ERROR]}m',
'changed': '\033[{0}m'.format(C.COLOR_CODES[C.COLOR_CHANGED]),
'failed': '\033[{0}m'.format(C.COLOR_CODES[C.COLOR_ERROR]),
'endc': '\033[0m',
'skipped': f'\x1b[{C.COLOR_CODES[C.COLOR_SKIP]}m',
'skipped': '\033[{0}m'.format(C.COLOR_CODES[C.COLOR_SKIP]),
}
@@ -73,7 +73,7 @@ def colorize(msg, color):
if DONT_COLORIZE:
return msg
else:
return f"{COLORS[color]}{msg}{COLORS['endc']}"
return '{0}{1}{2}'.format(COLORS[color], msg, COLORS['endc'])
class CallbackModule(CallbackBase):
@@ -106,15 +106,15 @@ class CallbackModule(CallbackBase):
line_length = 120
if self.last_skipped:
print()
line = f"# {task_name} "
msg = colorize(f"{line}{'*' * (line_length - len(line))}", 'bold')
line = "# {0} ".format(task_name)
msg = colorize("{0}{1}".format(line, '*' * (line_length - len(line))), 'bold')
print(msg)
def _indent_text(self, text, indent_level):
lines = text.splitlines()
result_lines = []
for l in lines:
result_lines.append(f"{' ' * indent_level}{l}")
result_lines.append("{0}{1}".format(' ' * indent_level, l))
return '\n'.join(result_lines)
def _print_diff(self, diff, indent_level):
@@ -147,19 +147,19 @@ class CallbackModule(CallbackBase):
change_string = colorize('FAILED!!!', color)
else:
color = 'changed' if changed else 'ok'
change_string = colorize(f"changed={changed}", color)
change_string = colorize("changed={0}".format(changed), color)
msg = colorize(msg, color)
line_length = 120
spaces = ' ' * (40 - len(name) - indent_level)
line = f"{' ' * indent_level} * {name}{spaces}- {change_string}"
line = "{0} * {1}{2}- {3}".format(' ' * indent_level, name, spaces, change_string)
if len(msg) < 50:
line += f' -- {msg}'
print(f"{line} {'-' * (line_length - len(line))}---------")
line += ' -- {0}'.format(msg)
print("{0} {1}---------".format(line, '-' * (line_length - len(line))))
else:
print(f"{line} {'-' * (line_length - len(line))}")
print("{0} {1}".format(line, '-' * (line_length - len(line))))
print(self._indent_text(msg, indent_level + 4))
if diff:
@@ -239,10 +239,8 @@ class CallbackModule(CallbackBase):
else:
color = 'ok'
msg = (
f"{host} : ok={s['ok']}\tchanged={s['changed']}\tfailed={s['failures']}\tunreachable="
f"{s['unreachable']}\trescued={s['rescued']}\tignored={s['ignored']}"
)
msg = '{0} : ok={1}\tchanged={2}\tfailed={3}\tunreachable={4}\trescued={5}\tignored={6}'.format(
host, s['ok'], s['changed'], s['failures'], s['unreachable'], s['rescued'], s['ignored'])
print(colorize(msg, color))
def v2_runner_on_skipped(self, result, **kwargs):
@@ -254,15 +252,17 @@ class CallbackModule(CallbackBase):
line_length = 120
spaces = ' ' * (31 - len(result._host.name) - 4)
line = f" * {colorize(result._host.name, 'not_so_bold')}{spaces}- {colorize('skipped', 'skipped')}"
line = " * {0}{1}- {2}".format(colorize(result._host.name, 'not_so_bold'),
spaces,
colorize("skipped", 'skipped'),)
reason = result._result.get('skipped_reason', '') or \
result._result.get('skip_reason', '')
if len(reason) < 50:
line += f' -- {reason}'
print(f"{line} {'-' * (line_length - len(line))}---------")
line += ' -- {0}'.format(reason)
print("{0} {1}---------".format(line, '-' * (line_length - len(line))))
else:
print(f"{line} {'-' * (line_length - len(line))}")
print("{0} {1}".format(line, '-' * (line_length - len(line))))
print(self._indent_text(reason, 8))
print(reason)

View File

@@ -8,60 +8,58 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Unknown (!UNKNOWN)
name: slack
type: notification
requirements:
- whitelist in configuration
- prettytable (python library)
short_description: Sends play events to a Slack channel
description:
- This is an ansible callback plugin that sends status updates to a Slack channel during playbook execution.
options:
webhook_url:
required: true
description: Slack Webhook URL.
type: str
env:
- name: SLACK_WEBHOOK_URL
ini:
- section: callback_slack
key: webhook_url
channel:
default: "#ansible"
description: Slack room to post in.
type: str
env:
- name: SLACK_CHANNEL
ini:
- section: callback_slack
key: channel
username:
description: Username to post as.
type: str
env:
- name: SLACK_USERNAME
default: ansible
ini:
- section: callback_slack
key: username
validate_certs:
description: Validate the SSL certificate of the Slack server for HTTPS URLs.
env:
- name: SLACK_VALIDATE_CERTS
ini:
- section: callback_slack
key: validate_certs
default: true
type: bool
"""
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: slack
type: notification
requirements:
- whitelist in configuration
- prettytable (python library)
short_description: Sends play events to a Slack channel
description:
- This is an ansible callback plugin that sends status updates to a Slack channel during playbook execution.
options:
webhook_url:
required: true
description: Slack Webhook URL.
env:
- name: SLACK_WEBHOOK_URL
ini:
- section: callback_slack
key: webhook_url
channel:
default: "#ansible"
description: Slack room to post in.
env:
- name: SLACK_CHANNEL
ini:
- section: callback_slack
key: channel
username:
description: Username to post as.
env:
- name: SLACK_USERNAME
default: ansible
ini:
- section: callback_slack
key: username
validate_certs:
description: Validate the SSL certificate of the Slack server for HTTPS URLs.
env:
- name: SLACK_VALIDATE_CERTS
ini:
- section: callback_slack
key: validate_certs
default: true
type: bool
'''
import json
import os
import uuid
from ansible import context
from ansible.module_utils.common.text.converters import to_text
from ansible.module_utils.urls import open_url
from ansible.plugins.callback import CallbackBase
@@ -137,13 +135,14 @@ class CallbackModule(CallbackBase):
headers=headers)
return response.read()
except Exception as e:
self._display.warning(f'Could not submit message to Slack: {e}')
self._display.warning(u'Could not submit message to Slack: %s' %
to_text(e))
def v2_playbook_on_start(self, playbook):
self.playbook_name = os.path.basename(playbook._file_name)
title = [
f'*Playbook initiated* (_{self.guid}_)'
'*Playbook initiated* (_%s_)' % self.guid
]
invocation_items = []
@@ -154,23 +153,23 @@ class CallbackModule(CallbackBase):
subset = context.CLIARGS['subset']
inventory = [os.path.abspath(i) for i in context.CLIARGS['inventory']]
invocation_items.append(f"Inventory: {', '.join(inventory)}")
invocation_items.append('Inventory: %s' % ', '.join(inventory))
if tags and tags != ['all']:
invocation_items.append(f"Tags: {', '.join(tags)}")
invocation_items.append('Tags: %s' % ', '.join(tags))
if skip_tags:
invocation_items.append(f"Skip Tags: {', '.join(skip_tags)}")
invocation_items.append('Skip Tags: %s' % ', '.join(skip_tags))
if subset:
invocation_items.append(f'Limit: {subset}')
invocation_items.append('Limit: %s' % subset)
if extra_vars:
invocation_items.append(f"Extra Vars: {' '.join(extra_vars)}")
invocation_items.append('Extra Vars: %s' %
' '.join(extra_vars))
title.append(f"by *{context.CLIARGS['remote_user']}*")
title.append('by *%s*' % context.CLIARGS['remote_user'])
title.append(f'\n\n*{self.playbook_name}*')
title.append('\n\n*%s*' % self.playbook_name)
msg_items = [' '.join(title)]
if invocation_items:
_inv_item = '\n'.join(invocation_items)
msg_items.append(f'```\n{_inv_item}\n```')
msg_items.append('```\n%s\n```' % '\n'.join(invocation_items))
msg = '\n'.join(msg_items)
@@ -190,8 +189,8 @@ class CallbackModule(CallbackBase):
def v2_playbook_on_play_start(self, play):
"""Display Play start messages"""
name = play.name or f'Play name not specified ({play._uuid})'
msg = f'*Starting play* (_{self.guid}_)\n\n*{name}*'
name = play.name or 'Play name not specified (%s)' % play._uuid
msg = '*Starting play* (_%s_)\n\n*%s*' % (self.guid, name)
attachments = [
{
'fallback': msg,
@@ -226,7 +225,7 @@ class CallbackModule(CallbackBase):
attachments = []
msg_items = [
f'*Playbook Complete* (_{self.guid}_)'
'*Playbook Complete* (_%s_)' % self.guid
]
if failures or unreachable:
color = 'danger'
@@ -235,7 +234,7 @@ class CallbackModule(CallbackBase):
color = 'good'
msg_items.append('\n*Success!*')
msg_items.append(f'```\n{t}\n```')
msg_items.append('```\n%s\n```' % t)
msg = '\n'.join(msg_items)

View File

@@ -6,73 +6,71 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
name: splunk
type: notification
short_description: Sends task result events to Splunk HTTP Event Collector
author: "Stuart Hirst (!UNKNOWN) <support@convergingdata.com>"
description:
- This callback plugin will send task results as JSON formatted events to a Splunk HTTP collector.
- The companion Splunk Monitoring & Diagnostics App is available here U(https://splunkbase.splunk.com/app/4023/).
- Credit to "Ryan Currah (@ryancurrah)" for original source upon which this is based.
requirements:
- Whitelisting this callback plugin
- 'Create a HTTP Event Collector in Splunk'
- 'Define the URL and token in C(ansible.cfg)'
options:
url:
description: URL to the Splunk HTTP collector source.
type: str
env:
- name: SPLUNK_URL
ini:
- section: callback_splunk
key: url
authtoken:
description: Token to authenticate the connection to the Splunk HTTP collector.
type: str
env:
- name: SPLUNK_AUTHTOKEN
ini:
- section: callback_splunk
key: authtoken
validate_certs:
description: Whether to validate certificates for connections to HEC. It is not recommended to set to V(false) except
when you are sure that nobody can intercept the connection between this plugin and HEC, as setting it to V(false) allows
man-in-the-middle attacks!
env:
- name: SPLUNK_VALIDATE_CERTS
ini:
- section: callback_splunk
key: validate_certs
type: bool
default: true
version_added: '1.0.0'
include_milliseconds:
description: Whether to include milliseconds as part of the generated timestamp field in the event sent to the Splunk
HTTP collector.
env:
- name: SPLUNK_INCLUDE_MILLISECONDS
ini:
- section: callback_splunk
key: include_milliseconds
type: bool
default: false
version_added: 2.0.0
batch:
DOCUMENTATION = '''
name: splunk
type: notification
short_description: Sends task result events to Splunk HTTP Event Collector
author: "Stuart Hirst (!UNKNOWN) <support@convergingdata.com>"
description:
- Correlation ID which can be set across multiple playbook executions.
env:
- name: SPLUNK_BATCH
ini:
- section: callback_splunk
key: batch
type: str
version_added: 3.3.0
"""
- This callback plugin will send task results as JSON formatted events to a Splunk HTTP collector.
- The companion Splunk Monitoring & Diagnostics App is available here U(https://splunkbase.splunk.com/app/4023/).
- Credit to "Ryan Currah (@ryancurrah)" for original source upon which this is based.
requirements:
- Whitelisting this callback plugin
- 'Create a HTTP Event Collector in Splunk'
- 'Define the URL and token in C(ansible.cfg)'
options:
url:
description: URL to the Splunk HTTP collector source.
env:
- name: SPLUNK_URL
ini:
- section: callback_splunk
key: url
authtoken:
description: Token to authenticate the connection to the Splunk HTTP collector.
env:
- name: SPLUNK_AUTHTOKEN
ini:
- section: callback_splunk
key: authtoken
validate_certs:
description: Whether to validate certificates for connections to HEC. It is not recommended to set to
V(false) except when you are sure that nobody can intercept the connection
between this plugin and HEC, as setting it to V(false) allows man-in-the-middle attacks!
env:
- name: SPLUNK_VALIDATE_CERTS
ini:
- section: callback_splunk
key: validate_certs
type: bool
default: true
version_added: '1.0.0'
include_milliseconds:
description: Whether to include milliseconds as part of the generated timestamp field in the event
sent to the Splunk HTTP collector.
env:
- name: SPLUNK_INCLUDE_MILLISECONDS
ini:
- section: callback_splunk
key: include_milliseconds
type: bool
default: false
version_added: 2.0.0
batch:
description:
- Correlation ID which can be set across multiple playbook executions.
env:
- name: SPLUNK_BATCH
ini:
- section: callback_splunk
key: batch
type: str
version_added: 3.3.0
'''
EXAMPLES = r"""
examples: >-
EXAMPLES = '''
examples: >
To enable, add this to your ansible.cfg file in the defaults block
[defaults]
callback_whitelist = community.general.splunk
@@ -83,7 +81,7 @@ examples: >-
[callback_splunk]
url = http://mysplunkinstance.datapaas.io:8088/services/collector/event
authtoken = f23blad6-5965-4537-bf69-5b5a545blabla88
"""
'''
import json
import uuid
@@ -153,14 +151,15 @@ class SplunkHTTPCollectorSource(object):
data['ansible_result'] = result._result
# This wraps the json payload in and outer json event needed by Splunk
jsondata = json.dumps({"event": data}, cls=AnsibleJSONEncoder, sort_keys=True)
jsondata = json.dumps(data, cls=AnsibleJSONEncoder, sort_keys=True)
jsondata = '{"event":' + jsondata + "}"
open_url(
url,
jsondata,
headers={
'Content-type': 'application/json',
'Authorization': f"Splunk {authtoken}"
'Authorization': 'Splunk ' + authtoken
},
method='POST',
validate_certs=validate_certs

View File

@@ -6,7 +6,7 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
DOCUMENTATION = r'''
name: sumologic
type: notification
short_description: Sends task result events to Sumologic
@@ -15,21 +15,20 @@ description:
- This callback plugin will send task results as JSON formatted events to a Sumologic HTTP collector source.
requirements:
- Whitelisting this callback plugin
- 'Create a HTTP collector source in Sumologic and specify a custom timestamp format of V(yyyy-MM-dd HH:mm:ss ZZZZ) and
a custom timestamp locator of V("timestamp": "(.*\)")'
- 'Create a HTTP collector source in Sumologic and specify a custom timestamp format of V(yyyy-MM-dd HH:mm:ss ZZZZ) and a custom timestamp locator
of V("timestamp": "(.*\)")'
options:
url:
description: URL to the Sumologic HTTP collector source.
type: str
env:
- name: SUMOLOGIC_URL
ini:
- section: callback_sumologic
key: url
"""
'''
EXAMPLES = r"""
examples: |-
EXAMPLES = '''
examples: |
To enable, add this to your ansible.cfg file in the defaults block
[defaults]
callback_whitelist = community.general.sumologic
@@ -40,7 +39,7 @@ examples: |-
Set the ansible.cfg variable in the callback_sumologic block
[callback_sumologic]
url = https://endpoint1.collection.us2.sumologic.com/receiver/v1/http/R8moSv1d8EW9LAUFZJ6dbxCFxwLH6kfCdcBfddlfxCbLuL-BN5twcTpMk__pYy_cDmp==
"""
'''
import json
import uuid

View File

@@ -7,54 +7,51 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Unknown (!UNKNOWN)
name: syslog_json
type: notification
requirements:
- whitelist in configuration
short_description: sends JSON events to syslog
description:
- This plugin logs ansible-playbook and ansible runs to a syslog server in JSON format.
options:
server:
description: Syslog server that will receive the event.
type: str
env:
- name: SYSLOG_SERVER
default: localhost
ini:
- section: callback_syslog_json
key: syslog_server
port:
description: Port on which the syslog server is listening.
type: int
env:
- name: SYSLOG_PORT
default: 514
ini:
- section: callback_syslog_json
key: syslog_port
facility:
description: Syslog facility to log as.
type: str
env:
- name: SYSLOG_FACILITY
default: user
ini:
- section: callback_syslog_json
key: syslog_facility
setup:
description: Log setup tasks.
env:
- name: ANSIBLE_SYSLOG_SETUP
type: bool
default: true
ini:
- section: callback_syslog_json
key: syslog_setup
version_added: 4.5.0
"""
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: syslog_json
type: notification
requirements:
- whitelist in configuration
short_description: sends JSON events to syslog
description:
- This plugin logs ansible-playbook and ansible runs to a syslog server in JSON format.
options:
server:
description: Syslog server that will receive the event.
env:
- name: SYSLOG_SERVER
default: localhost
ini:
- section: callback_syslog_json
key: syslog_server
port:
description: Port on which the syslog server is listening.
env:
- name: SYSLOG_PORT
default: 514
ini:
- section: callback_syslog_json
key: syslog_port
facility:
description: Syslog facility to log as.
env:
- name: SYSLOG_FACILITY
default: user
ini:
- section: callback_syslog_json
key: syslog_facility
setup:
description: Log setup tasks.
env:
- name: ANSIBLE_SYSLOG_SETUP
type: bool
default: true
ini:
- section: callback_syslog_json
key: syslog_setup
version_added: 4.5.0
'''
import logging
import logging.handlers

View File

@@ -1,126 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2024, kurokobo <kurokobo@protonmail.com>
# Copyright (c) 2014, Michael DeHaan <michael.dehaan@gmail.com>
# 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
DOCUMENTATION = r"""
name: timestamp
type: stdout
short_description: Adds simple timestamp for each header
version_added: 9.0.0
description:
- This callback adds simple timestamp for each header.
author: kurokobo (@kurokobo)
options:
timezone:
description:
- Timezone to use for the timestamp in IANA time zone format.
- For example V(America/New_York), V(Asia/Tokyo)). Ignored on Python < 3.9.
ini:
- section: callback_timestamp
key: timezone
env:
- name: ANSIBLE_CALLBACK_TIMESTAMP_TIMEZONE
type: string
format_string:
description:
- Format of the timestamp shown to user in 1989 C standard format.
- Refer to L(the Python documentation,https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes)
for the available format codes.
ini:
- section: callback_timestamp
key: format_string
env:
- name: ANSIBLE_CALLBACK_TIMESTAMP_FORMAT_STRING
default: "%H:%M:%S"
type: string
seealso:
- plugin: ansible.posix.profile_tasks
plugin_type: callback
description: >-
You can use P(ansible.posix.profile_tasks#callback) callback plugin to time individual tasks and overall execution time
with detailed timestamps.
extends_documentation_fragment:
- ansible.builtin.default_callback
- ansible.builtin.result_format_callback
"""
from ansible.plugins.callback.default import CallbackModule as Default
from ansible.utils.display import get_text_width
from ansible.module_utils.common.text.converters import to_text
from datetime import datetime
import types
import sys
# Store whether the zoneinfo module is available
_ZONEINFO_AVAILABLE = sys.version_info >= (3, 9)
def get_datetime_now(tz):
"""
Returns the current timestamp with the specified timezone
"""
return datetime.now(tz=tz)
def banner(self, msg, color=None, cows=True):
"""
Prints a header-looking line with cowsay or stars with length depending on terminal width (3 minimum) with trailing timestamp
Based on the banner method of Display class from ansible.utils.display
https://github.com/ansible/ansible/blob/4403519afe89138042108e237aef317fd5f09c33/lib/ansible/utils/display.py#L511
"""
timestamp = get_datetime_now(self.timestamp_tzinfo).strftime(self.timestamp_format_string)
timestamp_len = get_text_width(timestamp) + 1 # +1 for leading space
msg = to_text(msg)
if self.b_cowsay and cows:
try:
self.banner_cowsay(f"{msg} @ {timestamp}")
return
except OSError:
self.warning("somebody cleverly deleted cowsay or something during the PB run. heh.")
msg = msg.strip()
try:
star_len = self.columns - get_text_width(msg) - timestamp_len
except EnvironmentError:
star_len = self.columns - len(msg) - timestamp_len
if star_len <= 3:
star_len = 3
stars = "*" * star_len
self.display(f"\n{msg} {stars} {timestamp}", color=color)
class CallbackModule(Default):
CALLBACK_VERSION = 2.0
CALLBACK_TYPE = "stdout"
CALLBACK_NAME = "community.general.timestamp"
def __init__(self):
super(CallbackModule, self).__init__()
# Replace the banner method of the display object with the custom one
self._display.banner = types.MethodType(banner, self._display)
def set_options(self, task_keys=None, var_options=None, direct=None):
super(CallbackModule, self).set_options(task_keys=task_keys, var_options=var_options, direct=direct)
# Store zoneinfo for specified timezone if available
tzinfo = None
if _ZONEINFO_AVAILABLE and self.get_option("timezone"):
from zoneinfo import ZoneInfo
tzinfo = ZoneInfo(self.get_option("timezone"))
# Inject options into the display object
setattr(self._display, "timestamp_tzinfo", tzinfo)
setattr(self._display, "timestamp_format_string", self.get_option("format_string"))

View File

@@ -8,18 +8,18 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
name: unixy
type: stdout
author: Al Bowles (@akatch)
short_description: condensed Ansible output
description:
- Consolidated Ansible output in the style of LINUX/UNIX startup logs.
extends_documentation_fragment:
- default_callback
requirements:
- set as stdout in configuration
"""
DOCUMENTATION = '''
name: unixy
type: stdout
author: Al Bowles (@akatch)
short_description: condensed Ansible output
description:
- Consolidated Ansible output in the style of LINUX/UNIX startup logs.
extends_documentation_fragment:
- default_callback
requirements:
- set as stdout in configuration
'''
from os.path import basename
from ansible import constants as C
@@ -67,24 +67,24 @@ class CallbackModule(CallbackModule_default):
def _process_result_output(self, result, msg):
task_host = result._host.get_name()
task_result = f"{task_host} {msg}"
task_result = "%s %s" % (task_host, msg)
if self._run_is_verbose(result):
task_result = f"{task_host} {msg}: {self._dump_results(result._result, indent=4)}"
task_result = "%s %s: %s" % (task_host, msg, self._dump_results(result._result, indent=4))
return task_result
if self.delegated_vars:
task_delegate_host = self.delegated_vars['ansible_host']
task_result = f"{task_host} -> {task_delegate_host} {msg}"
task_result = "%s -> %s %s" % (task_host, task_delegate_host, msg)
if result._result.get('msg') and result._result.get('msg') != "All items completed":
task_result += f" | msg: {to_text(result._result.get('msg'))}"
task_result += " | msg: " + to_text(result._result.get('msg'))
if result._result.get('stdout'):
task_result += f" | stdout: {result._result.get('stdout')}"
task_result += " | stdout: " + result._result.get('stdout')
if result._result.get('stderr'):
task_result += f" | stderr: {result._result.get('stderr')}"
task_result += " | stderr: " + result._result.get('stderr')
return task_result
@@ -92,30 +92,30 @@ class CallbackModule(CallbackModule_default):
self._get_task_display_name(task)
if self.task_display_name is not None:
if task.check_mode and self.get_option('check_mode_markers'):
self._display.display(f"{self.task_display_name} (check mode)...")
self._display.display("%s (check mode)..." % self.task_display_name)
else:
self._display.display(f"{self.task_display_name}...")
self._display.display("%s..." % self.task_display_name)
def v2_playbook_on_handler_task_start(self, task):
self._get_task_display_name(task)
if self.task_display_name is not None:
if task.check_mode and self.get_option('check_mode_markers'):
self._display.display(f"{self.task_display_name} (via handler in check mode)... ")
self._display.display("%s (via handler in check mode)... " % self.task_display_name)
else:
self._display.display(f"{self.task_display_name} (via handler)... ")
self._display.display("%s (via handler)... " % self.task_display_name)
def v2_playbook_on_play_start(self, play):
name = play.get_name().strip()
if play.check_mode and self.get_option('check_mode_markers'):
if name and play.hosts:
msg = f"\n- {name} (in check mode) on hosts: {','.join(play.hosts)} -"
msg = u"\n- %s (in check mode) on hosts: %s -" % (name, ",".join(play.hosts))
else:
msg = "- check mode -"
msg = u"- check mode -"
else:
if name and play.hosts:
msg = f"\n- {name} on hosts: {','.join(play.hosts)} -"
msg = u"\n- %s on hosts: %s -" % (name, ",".join(play.hosts))
else:
msg = "---"
msg = u"---"
self._display.display(msg)
@@ -126,7 +126,7 @@ class CallbackModule(CallbackModule_default):
msg = "skipped"
task_result = self._process_result_output(result, msg)
self._display.display(f" {task_result}", display_color)
self._display.display(" " + task_result, display_color)
else:
return
@@ -136,10 +136,10 @@ class CallbackModule(CallbackModule_default):
msg = "failed"
item_value = self._get_item_label(result._result)
if item_value:
msg += f" | item: {item_value}"
msg += " | item: %s" % (item_value,)
task_result = self._process_result_output(result, msg)
self._display.display(f" {task_result}", display_color, stderr=self.get_option('display_failed_stderr'))
self._display.display(" " + task_result, display_color, stderr=self.get_option('display_failed_stderr'))
def v2_runner_on_ok(self, result, msg="ok", display_color=C.COLOR_OK):
self._preprocess_result(result)
@@ -149,13 +149,13 @@ class CallbackModule(CallbackModule_default):
msg = "done"
item_value = self._get_item_label(result._result)
if item_value:
msg += f" | item: {item_value}"
msg += " | item: %s" % (item_value,)
display_color = C.COLOR_CHANGED
task_result = self._process_result_output(result, msg)
self._display.display(f" {task_result}", display_color)
self._display.display(" " + task_result, display_color)
elif self.get_option('display_ok_hosts'):
task_result = self._process_result_output(result, msg)
self._display.display(f" {task_result}", display_color)
self._display.display(" " + task_result, display_color)
def v2_runner_item_on_skipped(self, result):
self.v2_runner_on_skipped(result)
@@ -173,7 +173,7 @@ class CallbackModule(CallbackModule_default):
display_color = C.COLOR_UNREACHABLE
task_result = self._process_result_output(result, msg)
self._display.display(f" {task_result}", display_color, stderr=self.get_option('display_failed_stderr'))
self._display.display(" " + task_result, display_color, stderr=self.get_option('display_failed_stderr'))
def v2_on_file_diff(self, result):
if result._task.loop and 'results' in result._result:
@@ -195,17 +195,25 @@ class CallbackModule(CallbackModule_default):
# TODO how else can we display these?
t = stats.summarize(h)
self._display.display(
f" {hostcolor(h, t)} : {colorize('ok', t['ok'], C.COLOR_OK)} {colorize('changed', t['changed'], C.COLOR_CHANGED)} "
f"{colorize('unreachable', t['unreachable'], C.COLOR_UNREACHABLE)} {colorize('failed', t['failures'], C.COLOR_ERROR)} "
f"{colorize('rescued', t['rescued'], C.COLOR_OK)} {colorize('ignored', t['ignored'], C.COLOR_WARN)}",
self._display.display(u" %s : %s %s %s %s %s %s" % (
hostcolor(h, t),
colorize(u'ok', t['ok'], C.COLOR_OK),
colorize(u'changed', t['changed'], C.COLOR_CHANGED),
colorize(u'unreachable', t['unreachable'], C.COLOR_UNREACHABLE),
colorize(u'failed', t['failures'], C.COLOR_ERROR),
colorize(u'rescued', t['rescued'], C.COLOR_OK),
colorize(u'ignored', t['ignored'], C.COLOR_WARN)),
screen_only=True
)
self._display.display(
f" {hostcolor(h, t, False)} : {colorize('ok', t['ok'], None)} {colorize('changed', t['changed'], None)} "
f"{colorize('unreachable', t['unreachable'], None)} {colorize('failed', t['failures'], None)} {colorize('rescued', t['rescued'], None)} "
f"{colorize('ignored', t['ignored'], None)}",
self._display.display(u" %s : %s %s %s %s %s %s" % (
hostcolor(h, t, False),
colorize(u'ok', t['ok'], None),
colorize(u'changed', t['changed'], None),
colorize(u'unreachable', t['unreachable'], None),
colorize(u'failed', t['failures'], None),
colorize(u'rescued', t['rescued'], None),
colorize(u'ignored', t['ignored'], None)),
log_only=True
)
if stats.custom and self.get_option('show_custom_stats'):
@@ -215,14 +223,12 @@ class CallbackModule(CallbackModule_default):
for k in sorted(stats.custom.keys()):
if k == '_run':
continue
stat_val = self._dump_results(stats.custom[k], indent=1).replace('\n', '')
self._display.display(f'\t{k}: {stat_val}')
self._display.display('\t%s: %s' % (k, self._dump_results(stats.custom[k], indent=1).replace('\n', '')))
# print per run custom stats
if '_run' in stats.custom:
self._display.display("", screen_only=True)
stat_val_run = self._dump_results(stats.custom['_run'], indent=1).replace('\n', '')
self._display.display(f'\tRUN: {stat_val_run}')
self._display.display('\tRUN: %s' % self._dump_results(stats.custom['_run'], indent=1).replace('\n', ''))
self._display.display("", screen_only=True)
def v2_playbook_on_no_hosts_matched(self):
@@ -233,23 +239,23 @@ class CallbackModule(CallbackModule_default):
def v2_playbook_on_start(self, playbook):
if context.CLIARGS['check'] and self.get_option('check_mode_markers'):
self._display.display(f"Executing playbook {basename(playbook._file_name)} in check mode")
self._display.display("Executing playbook %s in check mode" % basename(playbook._file_name))
else:
self._display.display(f"Executing playbook {basename(playbook._file_name)}")
self._display.display("Executing playbook %s" % basename(playbook._file_name))
# show CLI arguments
if self._display.verbosity > 3:
if context.CLIARGS.get('args'):
self._display.display(f"Positional arguments: {' '.join(context.CLIARGS['args'])}",
self._display.display('Positional arguments: %s' % ' '.join(context.CLIARGS['args']),
color=C.COLOR_VERBOSE, screen_only=True)
for argument in (a for a in context.CLIARGS if a != 'args'):
val = context.CLIARGS[argument]
if val:
self._display.vvvv(f'{argument}: {val}')
self._display.vvvv('%s: %s' % (argument, val))
def v2_runner_retry(self, result):
msg = f" Retrying... ({result._result['attempts']} of {result._result['retries']})"
msg = " Retrying... (%d of %d)" % (result._result['attempts'], result._result['retries'])
if self._run_is_verbose(result):
msg += f"Result was: {self._dump_results(result._result)}"
msg += "Result was: %s" % self._dump_results(result._result)
self._display.display(msg, color=C.COLOR_DEBUG)

View File

@@ -7,31 +7,29 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Unknown (!UNKNOWN)
name: yaml
type: stdout
short_description: YAML-ized Ansible screen output
deprecated:
removed_in: 13.0.0
why: Starting in ansible-core 2.13, the P(ansible.builtin.default#callback) callback has support for printing output in YAML format.
alternative: Use O(ansible.builtin.default#callback:result_format=yaml).
description:
- Ansible output that can be quite a bit easier to read than the default JSON formatting.
extends_documentation_fragment:
- default_callback
requirements:
- set as stdout in configuration
seealso:
- plugin: ansible.builtin.default
plugin_type: callback
description: >-
There is a parameter O(ansible.builtin.default#callback:result_format) in P(ansible.builtin.default#callback) that allows
you to change the output format to YAML.
notes:
- With ansible-core 2.13 or newer, you can instead specify V(yaml) for the parameter O(ansible.builtin.default#callback:result_format)
in P(ansible.builtin.default#callback).
"""
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: yaml
type: stdout
short_description: YAML-ized Ansible screen output
description:
- Ansible output that can be quite a bit easier to read than the
default JSON formatting.
extends_documentation_fragment:
- default_callback
requirements:
- set as stdout in configuration
seealso:
- plugin: ansible.builtin.default
plugin_type: callback
description: >
There is a parameter O(ansible.builtin.default#callback:result_format) in P(ansible.builtin.default#callback)
that allows you to change the output format to YAML.
notes:
- >
With ansible-core 2.13 or newer, you can instead specify V(yaml) for the parameter O(ansible.builtin.default#callback:result_format)
in P(ansible.builtin.default#callback).
'''
import yaml
import json
@@ -47,7 +45,7 @@ from ansible.plugins.callback.default import CallbackModule as Default
# from http://stackoverflow.com/a/15423007/115478
def should_use_block(value):
"""Returns true if string should be in block format"""
for c in "\u000a\u000d\u001c\u001d\u001e\u0085\u2028\u2029":
for c in u"\u000a\u000d\u001c\u001d\u001e\u0085\u2028\u2029":
if c in value:
return True
return False
@@ -115,11 +113,11 @@ class CallbackModule(Default):
# put changed and skipped into a header line
if 'changed' in abridged_result:
dumped += f"changed={str(abridged_result['changed']).lower()} "
dumped += 'changed=' + str(abridged_result['changed']).lower() + ' '
del abridged_result['changed']
if 'skipped' in abridged_result:
dumped += f"skipped={str(abridged_result['skipped']).lower()} "
dumped += 'skipped=' + str(abridged_result['skipped']).lower() + ' '
del abridged_result['skipped']
# if we already have stdout, we don't need stdout_lines

View File

@@ -10,66 +10,76 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Maykel Moya (!UNKNOWN) <mmoya@speedyrails.com>
name: chroot
short_description: Interact with local chroot
description:
- Run commands or put/fetch files to an existing chroot on the Ansible controller.
options:
remote_addr:
DOCUMENTATION = '''
author: Maykel Moya (!UNKNOWN) <mmoya@speedyrails.com>
name: chroot
short_description: Interact with local chroot
description:
- The path of the chroot you want to access.
type: string
default: inventory_hostname
vars:
- name: inventory_hostname
- name: ansible_host
executable:
description:
- User specified executable shell.
type: string
ini:
- section: defaults
key: executable
env:
- name: ANSIBLE_EXECUTABLE
vars:
- name: ansible_executable
default: /bin/sh
chroot_exe:
description:
- User specified chroot binary.
type: string
ini:
- section: chroot_connection
key: exe
env:
- name: ANSIBLE_CHROOT_EXE
vars:
- name: ansible_chroot_exe
default: chroot
disable_root_check:
description:
- Do not check that the user is not root.
ini:
- section: chroot_connection
key: disable_root_check
env:
- name: ANSIBLE_CHROOT_DISABLE_ROOT_CHECK
vars:
- name: ansible_chroot_disable_root_check
default: false
type: bool
version_added: 7.3.0
"""
- Run commands or put/fetch files to an existing chroot on the Ansible controller.
options:
remote_addr:
description:
- The path of the chroot you want to access.
default: inventory_hostname
vars:
- name: inventory_hostname
- name: ansible_host
executable:
description:
- User specified executable shell
ini:
- section: defaults
key: executable
env:
- name: ANSIBLE_EXECUTABLE
vars:
- name: ansible_executable
default: /bin/sh
chroot_exe:
description:
- User specified chroot binary
ini:
- section: chroot_connection
key: exe
env:
- name: ANSIBLE_CHROOT_EXE
vars:
- name: ansible_chroot_exe
default: chroot
disable_root_check:
description:
- Do not check that the user is not root.
ini:
- section: chroot_connection
key: disable_root_check
env:
- name: ANSIBLE_CHROOT_DISABLE_ROOT_CHECK
vars:
- name: ansible_chroot_disable_root_check
default: false
type: bool
version_added: 7.3.0
'''
EXAMPLES = r"""
# Plugin requires root privileges for chroot, -E preserves your env (and location of ~/.ansible):
# sudo -E ansible-playbook ...
#
# Static inventory file
# [chroots]
# /path/to/debootstrap
# /path/to/feboostrap
# /path/to/lxc-image
# /path/to/chroot
# playbook
---
- hosts: chroots
connection: community.general.chroot
tasks:
- debug:
msg: "This is coming from chroot environment"
"""
import os
@@ -81,7 +91,7 @@ from ansible.errors import AnsibleError
from ansible.module_utils.basic import is_executable
from ansible.module_utils.common.process import get_bin_path
from ansible.module_utils.six.moves import shlex_quote
from ansible.module_utils.common.text.converters import to_bytes
from ansible.module_utils.common.text.converters import to_bytes, to_native
from ansible.plugins.connection import ConnectionBase, BUFSIZE
from ansible.utils.display import Display
@@ -107,15 +117,15 @@ class Connection(ConnectionBase):
# do some trivial checks for ensuring 'host' is actually a chroot'able dir
if not os.path.isdir(self.chroot):
raise AnsibleError(f"{self.chroot} is not a directory")
raise AnsibleError("%s is not a directory" % self.chroot)
chrootsh = os.path.join(self.chroot, 'bin/sh')
# Want to check for a usable bourne shell inside the chroot.
# is_executable() == True is sufficient. For symlinks it
# gets really complicated really fast. So we punt on finding that
# out. As long as it is a symlink we assume that it will work
# out. As long as it's a symlink we assume that it will work
if not (is_executable(chrootsh) or (os.path.lexists(chrootsh) and os.path.islink(chrootsh))):
raise AnsibleError(f"{self.chroot} does not look like a chrootable dir (/bin/sh missing)")
raise AnsibleError("%s does not look like a chrootable dir (/bin/sh missing)" % self.chroot)
def _connect(self):
""" connect to the chroot """
@@ -130,7 +140,7 @@ class Connection(ConnectionBase):
try:
self.chroot_cmd = get_bin_path(self.get_option('chroot_exe'))
except ValueError as e:
raise AnsibleError(str(e))
raise AnsibleError(to_native(e))
super(Connection, self)._connect()
if not self._connected:
@@ -148,7 +158,7 @@ class Connection(ConnectionBase):
executable = self.get_option('executable')
local_cmd = [self.chroot_cmd, self.chroot, executable, '-c', cmd]
display.vvv(f"EXEC {local_cmd}", host=self.chroot)
display.vvv("EXEC %s" % local_cmd, host=self.chroot)
local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
p = subprocess.Popen(local_cmd, shell=False, stdin=stdin,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@@ -173,7 +183,7 @@ class Connection(ConnectionBase):
exist in any given chroot. So for now we're choosing "/" instead.
This also happens to be the former default.
Can revisit using $HOME instead if it is a problem
Can revisit using $HOME instead if it's a problem
"""
if not remote_path.startswith(os.path.sep):
remote_path = os.path.join(os.path.sep, remote_path)
@@ -182,7 +192,7 @@ class Connection(ConnectionBase):
def put_file(self, in_path, out_path):
""" transfer a file from local to chroot """
super(Connection, self).put_file(in_path, out_path)
display.vvv(f"PUT {in_path} TO {out_path}", host=self.chroot)
display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.chroot)
out_path = shlex_quote(self._prefix_login_path(out_path))
try:
@@ -192,27 +202,27 @@ class Connection(ConnectionBase):
else:
count = ''
try:
p = self._buffered_exec_command(f'dd of={out_path} bs={BUFSIZE}{count}', stdin=in_file)
p = self._buffered_exec_command('dd of=%s bs=%s%s' % (out_path, BUFSIZE, count), stdin=in_file)
except OSError:
raise AnsibleError("chroot connection requires dd command in the chroot")
try:
stdout, stderr = p.communicate()
except Exception:
traceback.print_exc()
raise AnsibleError(f"failed to transfer file {in_path} to {out_path}")
raise AnsibleError("failed to transfer file %s to %s" % (in_path, out_path))
if p.returncode != 0:
raise AnsibleError(f"failed to transfer file {in_path} to {out_path}:\n{stdout}\n{stderr}")
raise AnsibleError("failed to transfer file %s to %s:\n%s\n%s" % (in_path, out_path, stdout, stderr))
except IOError:
raise AnsibleError(f"file or module does not exist at: {in_path}")
raise AnsibleError("file or module does not exist at: %s" % in_path)
def fetch_file(self, in_path, out_path):
""" fetch a file from chroot to local """
super(Connection, self).fetch_file(in_path, out_path)
display.vvv(f"FETCH {in_path} TO {out_path}", host=self.chroot)
display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.chroot)
in_path = shlex_quote(self._prefix_login_path(in_path))
try:
p = self._buffered_exec_command(f'dd if={in_path} bs={BUFSIZE}')
p = self._buffered_exec_command('dd if=%s bs=%s' % (in_path, BUFSIZE))
except OSError:
raise AnsibleError("chroot connection requires dd command in the chroot")
@@ -224,10 +234,10 @@ class Connection(ConnectionBase):
chunk = p.stdout.read(BUFSIZE)
except Exception:
traceback.print_exc()
raise AnsibleError(f"failed to transfer file {in_path} to {out_path}")
raise AnsibleError("failed to transfer file %s to %s" % (in_path, out_path))
stdout, stderr = p.communicate()
if p.returncode != 0:
raise AnsibleError(f"failed to transfer file {in_path} to {out_path}:\n{stdout}\n{stderr}")
raise AnsibleError("failed to transfer file %s to %s:\n%s\n%s" % (in_path, out_path, stdout, stderr))
def close(self):
""" terminate the connection; nothing to do here """

View File

@@ -9,24 +9,23 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Michael Scherer (@mscherer) <misc@zarb.org>
name: funcd
short_description: Use funcd to connect to target
description:
- This transport permits you to use Ansible over Func.
- For people who have already setup func and that wish to play with ansible, this permit to move gradually to ansible without
having to redo completely the setup of the network.
options:
remote_addr:
DOCUMENTATION = '''
author: Michael Scherer (@mscherer) <misc@zarb.org>
name: funcd
short_description: Use funcd to connect to target
description:
- The path of the chroot you want to access.
type: string
default: inventory_hostname
vars:
- name: ansible_host
- name: ansible_func_host
"""
- This transport permits you to use Ansible over Func.
- For people who have already setup func and that wish to play with ansible,
this permit to move gradually to ansible without having to redo completely the setup of the network.
options:
remote_addr:
description:
- The path of the chroot you want to access.
default: inventory_hostname
vars:
- name: ansible_host
- name: ansible_func_host
'''
HAVE_FUNC = False
try:
@@ -72,7 +71,7 @@ class Connection(ConnectionBase):
raise AnsibleError("Internal Error: this module does not support optimized module pipelining")
# totally ignores privilege escalation
display.vvv(f"EXEC {cmd}", host=self.host)
display.vvv("EXEC %s" % cmd, host=self.host)
p = self.client.command.run(cmd)[self.host]
return p[0], p[1], p[2]
@@ -87,14 +86,14 @@ class Connection(ConnectionBase):
""" transfer a file from local to remote """
out_path = self._normalize_path(out_path, '/')
display.vvv(f"PUT {in_path} TO {out_path}", host=self.host)
display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.host)
self.client.local.copyfile.send(in_path, out_path)
def fetch_file(self, in_path, out_path):
""" fetch a file from remote to local """
in_path = self._normalize_path(in_path, '/')
display.vvv(f"FETCH {in_path} TO {out_path}", host=self.host)
display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.host)
# need to use a tmp dir due to difference of semantic for getfile
# ( who take a # directory as destination) and fetch_file, who
# take a file directly

View File

@@ -8,47 +8,43 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Stéphane Graber (@stgraber)
name: incus
short_description: Run tasks in Incus instances using the Incus CLI
description:
- Run commands or put/fetch files to an existing Incus instance using Incus CLI.
version_added: "8.2.0"
options:
remote_addr:
DOCUMENTATION = """
author: Stéphane Graber (@stgraber)
name: incus
short_description: Run tasks in Incus instances via the Incus CLI.
description:
- The instance identifier.
type: string
default: inventory_hostname
vars:
- name: inventory_hostname
- name: ansible_host
- name: ansible_incus_host
executable:
description:
- The shell to use for execution inside the instance.
type: string
default: /bin/sh
vars:
- name: ansible_executable
- name: ansible_incus_executable
remote:
description:
- The name of the Incus remote to use (per C(incus remote list)).
- Remotes are used to access multiple servers from a single client.
type: string
default: local
vars:
- name: ansible_incus_remote
project:
description:
- The name of the Incus project to use (per C(incus project list)).
- Projects are used to divide the instances running on a server.
type: string
default: default
vars:
- name: ansible_incus_project
- Run commands or put/fetch files to an existing Incus instance using Incus CLI.
version_added: "8.2.0"
options:
remote_addr:
description:
- The instance identifier.
default: inventory_hostname
vars:
- name: inventory_hostname
- name: ansible_host
- name: ansible_incus_host
executable:
description:
- The shell to use for execution inside the instance.
default: /bin/sh
vars:
- name: ansible_executable
- name: ansible_incus_executable
remote:
description:
- The name of the Incus remote to use (per C(incus remote list)).
- Remotes are used to access multiple servers from a single client.
default: local
vars:
- name: ansible_incus_remote
project:
description:
- The name of the Incus project to use (per C(incus project list)).
- Projects are used to divide the instances running on a server.
default: default
vars:
- name: ansible_incus_project
"""
import os
@@ -80,7 +76,7 @@ class Connection(ConnectionBase):
super(Connection, self)._connect()
if not self._connected:
self._display.vvv("ESTABLISH Incus CONNECTION FOR USER: root",
self._display.vvv(u"ESTABLISH Incus CONNECTION FOR USER: root",
host=self._instance())
self._connected = True
@@ -93,14 +89,14 @@ class Connection(ConnectionBase):
""" execute a command on the Incus host """
super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
self._display.vvv(f"EXEC {cmd}",
self._display.vvv(u"EXEC {0}".format(cmd),
host=self._instance())
local_cmd = [
self._incus_cmd,
"--project", self.get_option("project"),
"exec",
f"{self.get_option('remote')}:{self._instance()}",
"%s:%s" % (self.get_option("remote"), self._instance()),
"--",
self._play_context.executable, "-c", cmd]
@@ -114,10 +110,12 @@ class Connection(ConnectionBase):
stderr = to_text(stderr)
if stderr == "Error: Instance is not running.\n":
raise AnsibleConnectionFailure(f"instance not running: {self._instance()}")
raise AnsibleConnectionFailure("instance not running: %s" %
self._instance())
if stderr == "Error: Instance not found\n":
raise AnsibleConnectionFailure(f"instance not found: {self._instance()}")
raise AnsibleConnectionFailure("instance not found: %s" %
self._instance())
return process.returncode, stdout, stderr
@@ -125,18 +123,20 @@ class Connection(ConnectionBase):
""" put a file from local to Incus """
super(Connection, self).put_file(in_path, out_path)
self._display.vvv(f"PUT {in_path} TO {out_path}",
self._display.vvv(u"PUT {0} TO {1}".format(in_path, out_path),
host=self._instance())
if not os.path.isfile(to_bytes(in_path, errors='surrogate_or_strict')):
raise AnsibleFileNotFound(f"input path is not a file: {in_path}")
raise AnsibleFileNotFound("input path is not a file: %s" % in_path)
local_cmd = [
self._incus_cmd,
"--project", self.get_option("project"),
"file", "push", "--quiet",
in_path,
f"{self.get_option('remote')}:{self._instance()}/{out_path}"]
"%s:%s/%s" % (self.get_option("remote"),
self._instance(),
out_path)]
local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
@@ -146,14 +146,16 @@ class Connection(ConnectionBase):
""" fetch a file from Incus to local """
super(Connection, self).fetch_file(in_path, out_path)
self._display.vvv(f"FETCH {in_path} TO {out_path}",
self._display.vvv(u"FETCH {0} TO {1}".format(in_path, out_path),
host=self._instance())
local_cmd = [
self._incus_cmd,
"--project", self.get_option("project"),
"file", "pull", "--quiet",
f"{self.get_option('remote')}:{self._instance()}/{in_path}",
"%s:%s/%s" % (self.get_option("remote"),
self._instance(),
in_path),
out_path]
local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]

View File

@@ -10,28 +10,26 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Stephan Lohse (!UNKNOWN) <dev-github@ploek.org>
name: iocage
short_description: Run tasks in iocage jails
description:
- Run commands or put/fetch files to an existing iocage jail.
options:
remote_addr:
DOCUMENTATION = '''
author: Stephan Lohse (!UNKNOWN) <dev-github@ploek.org>
name: iocage
short_description: Run tasks in iocage jails
description:
- Path to the jail.
type: string
vars:
- name: ansible_host
- name: ansible_iocage_host
remote_user:
description:
- User to execute as inside the jail.
type: string
vars:
- name: ansible_user
- name: ansible_iocage_user
"""
- Run commands or put/fetch files to an existing iocage jail
options:
remote_addr:
description:
- Path to the jail
vars:
- name: ansible_host
- name: ansible_iocage_host
remote_user:
description:
- User to execute as inside the jail
vars:
- name: ansible_user
- name: ansible_iocage_user
'''
import subprocess
@@ -55,12 +53,11 @@ class Connection(Jail):
jail_uuid = self.get_jail_uuid()
kwargs[Jail.modified_jailname_key] = f'ioc-{jail_uuid}'
kwargs[Jail.modified_jailname_key] = 'ioc-{0}'.format(jail_uuid)
display.vvv(
f"Jail {self.ioc_jail} has been translated to {kwargs[Jail.modified_jailname_key]}",
host=kwargs[Jail.modified_jailname_key]
)
display.vvv(u"Jail {iocjail} has been translated to {rawjail}".format(
iocjail=self.ioc_jail, rawjail=kwargs[Jail.modified_jailname_key]),
host=kwargs[Jail.modified_jailname_key])
super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
@@ -82,6 +79,6 @@ class Connection(Jail):
p.wait()
if p.returncode != 0:
raise AnsibleError(f"iocage returned an error: {stdout}")
raise AnsibleError(u"iocage returned an error: {0}".format(stdout))
return stdout.strip('\n')

View File

@@ -10,30 +10,28 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Ansible Core Team
name: jail
short_description: Run tasks in jails
description:
- Run commands or put/fetch files to an existing jail.
options:
remote_addr:
DOCUMENTATION = '''
author: Ansible Core Team
name: jail
short_description: Run tasks in jails
description:
- Path to the jail.
type: string
default: inventory_hostname
vars:
- name: inventory_hostname
- name: ansible_host
- name: ansible_jail_host
remote_user:
description:
- User to execute as inside the jail.
type: string
vars:
- name: ansible_user
- name: ansible_jail_user
"""
- Run commands or put/fetch files to an existing jail
options:
remote_addr:
description:
- Path to the jail
default: inventory_hostname
vars:
- name: inventory_hostname
- name: ansible_host
- name: ansible_jail_host
remote_user:
description:
- User to execute as inside the jail
vars:
- name: ansible_user
- name: ansible_jail_user
'''
import os
import os.path
@@ -75,14 +73,14 @@ class Connection(ConnectionBase):
self.jexec_cmd = self._search_executable('jexec')
if self.jail not in self.list_jails():
raise AnsibleError(f"incorrect jail name {self.jail}")
raise AnsibleError("incorrect jail name %s" % self.jail)
@staticmethod
def _search_executable(executable):
try:
return get_bin_path(executable)
except ValueError:
raise AnsibleError(f"{executable} command not found in PATH")
raise AnsibleError("%s command not found in PATH" % executable)
def list_jails(self):
p = subprocess.Popen([self.jls_cmd, '-q', 'name'],
@@ -97,7 +95,7 @@ class Connection(ConnectionBase):
""" connect to the jail; nothing to do here """
super(Connection, self)._connect()
if not self._connected:
display.vvv(f"ESTABLISH JAIL CONNECTION FOR USER: {self._play_context.remote_user}", host=self.jail)
display.vvv(u"ESTABLISH JAIL CONNECTION FOR USER: {0}".format(self._play_context.remote_user), host=self.jail)
self._connected = True
def _buffered_exec_command(self, cmd, stdin=subprocess.PIPE):
@@ -115,11 +113,11 @@ class Connection(ConnectionBase):
if self._play_context.remote_user is not None:
local_cmd += ['-U', self._play_context.remote_user]
# update HOME since -U does not update the jail environment
set_env = f"HOME=~{self._play_context.remote_user} "
set_env = 'HOME=~' + self._play_context.remote_user + ' '
local_cmd += [self.jail, self._play_context.executable, '-c', set_env + cmd]
display.vvv(f"EXEC {local_cmd}", host=self.jail)
display.vvv("EXEC %s" % (local_cmd,), host=self.jail)
local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
p = subprocess.Popen(local_cmd, shell=False, stdin=stdin,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@@ -144,7 +142,7 @@ class Connection(ConnectionBase):
exist in any given chroot. So for now we're choosing "/" instead.
This also happens to be the former default.
Can revisit using $HOME instead if it is a problem
Can revisit using $HOME instead if it's a problem
"""
if not remote_path.startswith(os.path.sep):
remote_path = os.path.join(os.path.sep, remote_path)
@@ -153,7 +151,7 @@ class Connection(ConnectionBase):
def put_file(self, in_path, out_path):
""" transfer a file from local to jail """
super(Connection, self).put_file(in_path, out_path)
display.vvv(f"PUT {in_path} TO {out_path}", host=self.jail)
display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.jail)
out_path = shlex_quote(self._prefix_login_path(out_path))
try:
@@ -163,27 +161,27 @@ class Connection(ConnectionBase):
else:
count = ''
try:
p = self._buffered_exec_command(f'dd of={out_path} bs={BUFSIZE}{count}', stdin=in_file)
p = self._buffered_exec_command('dd of=%s bs=%s%s' % (out_path, BUFSIZE, count), stdin=in_file)
except OSError:
raise AnsibleError("jail connection requires dd command in the jail")
try:
stdout, stderr = p.communicate()
except Exception:
traceback.print_exc()
raise AnsibleError(f"failed to transfer file {in_path} to {out_path}")
raise AnsibleError("failed to transfer file %s to %s" % (in_path, out_path))
if p.returncode != 0:
raise AnsibleError(f"failed to transfer file {in_path} to {out_path}:\n{to_native(stdout)}\n{to_native(stderr)}")
raise AnsibleError("failed to transfer file %s to %s:\n%s\n%s" % (in_path, out_path, to_native(stdout), to_native(stderr)))
except IOError:
raise AnsibleError(f"file or module does not exist at: {in_path}")
raise AnsibleError("file or module does not exist at: %s" % in_path)
def fetch_file(self, in_path, out_path):
""" fetch a file from jail to local """
super(Connection, self).fetch_file(in_path, out_path)
display.vvv(f"FETCH {in_path} TO {out_path}", host=self.jail)
display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.jail)
in_path = shlex_quote(self._prefix_login_path(in_path))
try:
p = self._buffered_exec_command(f'dd if={in_path} bs={BUFSIZE}')
p = self._buffered_exec_command('dd if=%s bs=%s' % (in_path, BUFSIZE))
except OSError:
raise AnsibleError("jail connection requires dd command in the jail")
@@ -195,10 +193,10 @@ class Connection(ConnectionBase):
chunk = p.stdout.read(BUFSIZE)
except Exception:
traceback.print_exc()
raise AnsibleError(f"failed to transfer file {in_path} to {out_path}")
raise AnsibleError("failed to transfer file %s to %s" % (in_path, out_path))
stdout, stderr = p.communicate()
if p.returncode != 0:
raise AnsibleError(f"failed to transfer file {in_path} to {out_path}:\n{to_native(stdout)}\n{to_native(stderr)}")
raise AnsibleError("failed to transfer file %s to %s:\n%s\n%s" % (in_path, out_path, to_native(stdout), to_native(stderr)))
def close(self):
""" terminate the connection; nothing to do here """

View File

@@ -7,31 +7,29 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Joerg Thalheim (!UNKNOWN) <joerg@higgsboson.tk>
name: lxc
short_description: Run tasks in LXC containers using lxc python library
description:
- Run commands or put/fetch files to an existing LXC container using lxc python library.
options:
remote_addr:
DOCUMENTATION = '''
author: Joerg Thalheim (!UNKNOWN) <joerg@higgsboson.tk>
name: lxc
short_description: Run tasks in lxc containers via lxc python library
description:
- Container identifier.
type: string
default: inventory_hostname
vars:
- name: inventory_hostname
- name: ansible_host
- name: ansible_lxc_host
executable:
default: /bin/sh
description:
- Shell executable.
type: string
vars:
- name: ansible_executable
- name: ansible_lxc_executable
"""
- Run commands or put/fetch files to an existing lxc container using lxc python library
options:
remote_addr:
description:
- Container identifier
default: inventory_hostname
vars:
- name: inventory_hostname
- name: ansible_host
- name: ansible_lxc_host
executable:
default: /bin/sh
description:
- Shell executable
vars:
- name: ansible_executable
- name: ansible_lxc_executable
'''
import os
import shutil
@@ -82,7 +80,7 @@ class Connection(ConnectionBase):
self._display.vvv("THIS IS A LOCAL LXC DIR", host=self.container_name)
self.container = _lxc.Container(self.container_name)
if self.container.state == "STOPPED":
raise errors.AnsibleError(f"{self.container_name} is not running")
raise errors.AnsibleError("%s is not running" % self.container_name)
@staticmethod
def _communicate(pid, in_data, stdin, stdout, stderr):
@@ -144,10 +142,10 @@ class Connection(ConnectionBase):
read_stdin, write_stdin = os.pipe()
kwargs['stdin'] = self._set_nonblocking(read_stdin)
self._display.vvv(f"EXEC {local_cmd}", host=self.container_name)
self._display.vvv("EXEC %s" % (local_cmd), host=self.container_name)
pid = self.container.attach(_lxc.attach_run_command, local_cmd, **kwargs)
if pid == -1:
msg = f"failed to attach to container {self.container_name}"
msg = "failed to attach to container %s" % self.container_name
raise errors.AnsibleError(msg)
write_stdout = os.close(write_stdout)
@@ -174,18 +172,18 @@ class Connection(ConnectionBase):
def put_file(self, in_path, out_path):
''' transfer a file from local to lxc '''
super(Connection, self).put_file(in_path, out_path)
self._display.vvv(f"PUT {in_path} TO {out_path}", host=self.container_name)
self._display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.container_name)
in_path = to_bytes(in_path, errors='surrogate_or_strict')
out_path = to_bytes(out_path, errors='surrogate_or_strict')
if not os.path.exists(in_path):
msg = f"file or module does not exist: {in_path}"
msg = "file or module does not exist: %s" % in_path
raise errors.AnsibleFileNotFound(msg)
try:
src_file = open(in_path, "rb")
except IOError:
traceback.print_exc()
raise errors.AnsibleError(f"failed to open input file to {in_path}")
raise errors.AnsibleError("failed to open input file to %s" % in_path)
try:
def write_file(args):
with open(out_path, 'wb+') as dst_file:
@@ -194,7 +192,7 @@ class Connection(ConnectionBase):
self.container.attach_wait(write_file, None)
except IOError:
traceback.print_exc()
msg = f"failed to transfer file to {out_path}"
msg = "failed to transfer file to %s" % out_path
raise errors.AnsibleError(msg)
finally:
src_file.close()
@@ -202,7 +200,7 @@ class Connection(ConnectionBase):
def fetch_file(self, in_path, out_path):
''' fetch a file from lxc to local '''
super(Connection, self).fetch_file(in_path, out_path)
self._display.vvv(f"FETCH {in_path} TO {out_path}", host=self.container_name)
self._display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.container_name)
in_path = to_bytes(in_path, errors='surrogate_or_strict')
out_path = to_bytes(out_path, errors='surrogate_or_strict')
@@ -210,7 +208,7 @@ class Connection(ConnectionBase):
dst_file = open(out_path, "wb")
except IOError:
traceback.print_exc()
msg = f"failed to open output file {out_path}"
msg = "failed to open output file %s" % out_path
raise errors.AnsibleError(msg)
try:
def write_file(args):
@@ -225,7 +223,7 @@ class Connection(ConnectionBase):
self.container.attach_wait(write_file, None)
except IOError:
traceback.print_exc()
msg = f"failed to transfer file from {in_path} to {out_path}"
msg = "failed to transfer file from %s to %s" % (in_path, out_path)
raise errors.AnsibleError(msg)
finally:
dst_file.close()

View File

@@ -7,48 +7,44 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Matt Clay (@mattclay) <matt@mystile.com>
name: lxd
short_description: Run tasks in LXD instances using C(lxc) CLI
description:
- Run commands or put/fetch files to an existing instance using C(lxc) CLI.
options:
remote_addr:
DOCUMENTATION = '''
author: Matt Clay (@mattclay) <matt@mystile.com>
name: lxd
short_description: Run tasks in LXD instances via C(lxc) CLI
description:
- Instance (container/VM) identifier.
- Since community.general 8.0.0, a FQDN can be provided; in that case, the first component (the part before C(.)) is
used as the instance identifier.
type: string
default: inventory_hostname
vars:
- name: inventory_hostname
- name: ansible_host
- name: ansible_lxd_host
executable:
description:
- Shell to use for execution inside instance.
type: string
default: /bin/sh
vars:
- name: ansible_executable
- name: ansible_lxd_executable
remote:
description:
- Name of the LXD remote to use.
type: string
default: local
vars:
- name: ansible_lxd_remote
version_added: 2.0.0
project:
description:
- Name of the LXD project to use.
type: string
vars:
- name: ansible_lxd_project
version_added: 2.0.0
"""
- Run commands or put/fetch files to an existing instance using C(lxc) CLI.
options:
remote_addr:
description:
- Instance (container/VM) identifier.
- Since community.general 8.0.0, a FQDN can be provided; in that case, the first component (the part before C(.))
is used as the instance identifier.
default: inventory_hostname
vars:
- name: inventory_hostname
- name: ansible_host
- name: ansible_lxd_host
executable:
description:
- Shell to use for execution inside instance.
default: /bin/sh
vars:
- name: ansible_executable
- name: ansible_lxd_executable
remote:
description:
- Name of the LXD remote to use.
default: local
vars:
- name: ansible_lxd_remote
version_added: 2.0.0
project:
description:
- Name of the LXD project to use.
vars:
- name: ansible_lxd_project
version_added: 2.0.0
'''
import os
from subprocess import Popen, PIPE
@@ -86,26 +82,26 @@ class Connection(ConnectionBase):
super(Connection, self)._connect()
if not self._connected:
self._display.vvv("ESTABLISH LXD CONNECTION FOR USER: root", host=self._host())
self._display.vvv(u"ESTABLISH LXD CONNECTION FOR USER: root", host=self._host())
self._connected = True
def exec_command(self, cmd, in_data=None, sudoable=True):
""" execute a command on the lxd host """
super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
self._display.vvv(f"EXEC {cmd}", host=self._host())
self._display.vvv(u"EXEC {0}".format(cmd), host=self._host())
local_cmd = [self._lxc_cmd]
if self.get_option("project"):
local_cmd.extend(["--project", self.get_option("project")])
local_cmd.extend([
"exec",
f"{self.get_option('remote')}:{self._host()}",
"%s:%s" % (self.get_option("remote"), self._host()),
"--",
self.get_option("executable"), "-c", cmd
])
self._display.vvvvv(f"EXEC {local_cmd}", host=self._host())
self._display.vvvvv(u"EXEC {0}".format(local_cmd), host=self._host())
local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
in_data = to_bytes(in_data, errors='surrogate_or_strict', nonstring='passthru')
@@ -116,13 +112,13 @@ class Connection(ConnectionBase):
stdout = to_text(stdout)
stderr = to_text(stderr)
self._display.vvvvv(f"EXEC lxc output: {stdout} {stderr}", host=self._host())
self._display.vvvvv(u"EXEC lxc output: {0} {1}".format(stdout, stderr), host=self._host())
if "is not running" in stderr:
raise AnsibleConnectionFailure(f"instance not running: {self._host()}")
raise AnsibleConnectionFailure("instance not running: %s" % self._host())
if stderr.strip() == "Error: Instance not found" or stderr.strip() == "error: not found":
raise AnsibleConnectionFailure(f"instance not found: {self._host()}")
raise AnsibleConnectionFailure("instance not found: %s" % self._host())
return process.returncode, stdout, stderr
@@ -130,10 +126,10 @@ class Connection(ConnectionBase):
""" put a file from local to lxd """
super(Connection, self).put_file(in_path, out_path)
self._display.vvv(f"PUT {in_path} TO {out_path}", host=self._host())
self._display.vvv(u"PUT {0} TO {1}".format(in_path, out_path), host=self._host())
if not os.path.isfile(to_bytes(in_path, errors='surrogate_or_strict')):
raise AnsibleFileNotFound(f"input path is not a file: {in_path}")
raise AnsibleFileNotFound("input path is not a file: %s" % in_path)
local_cmd = [self._lxc_cmd]
if self.get_option("project"):
@@ -141,7 +137,7 @@ class Connection(ConnectionBase):
local_cmd.extend([
"file", "push",
in_path,
f"{self.get_option('remote')}:{self._host()}/{out_path}"
"%s:%s/%s" % (self.get_option("remote"), self._host(), out_path)
])
local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
@@ -153,14 +149,14 @@ class Connection(ConnectionBase):
""" fetch a file from lxd to local """
super(Connection, self).fetch_file(in_path, out_path)
self._display.vvv(f"FETCH {in_path} TO {out_path}", host=self._host())
self._display.vvv(u"FETCH {0} TO {1}".format(in_path, out_path), host=self._host())
local_cmd = [self._lxc_cmd]
if self.get_option("project"):
local_cmd.extend(["--project", self.get_option("project")])
local_cmd.extend([
"file", "pull",
f"{self.get_option('remote')}:{self._host()}/{in_path}",
"%s:%s/%s" % (self.get_option("remote"), self._host(), in_path),
out_path
])

View File

@@ -12,33 +12,32 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
name: qubes
short_description: Interact with an existing QubesOS AppVM
DOCUMENTATION = '''
name: qubes
short_description: Interact with an existing QubesOS AppVM
description:
- Run commands or put/fetch files to an existing Qubes AppVM using qubes tools.
author: Kushal Das (@kushaldas)
options:
remote_addr:
description:
- VM name.
type: string
default: inventory_hostname
vars:
- name: ansible_host
remote_user:
description:
- The user to execute as inside the VM.
type: string
default: The I(user) account as default in Qubes OS.
vars:
- name: ansible_user
- Run commands or put/fetch files to an existing Qubes AppVM using qubes tools.
author: Kushal Das (@kushaldas)
options:
remote_addr:
description:
- vm name
default: inventory_hostname
vars:
- name: ansible_host
remote_user:
description:
- The user to execute as inside the vm.
default: The *user* account as default in Qubes OS.
vars:
- name: ansible_user
# keyword:
# - name: hosts
"""
'''
import subprocess
@@ -77,7 +76,7 @@ class Connection(ConnectionBase):
"""
display.vvvv("CMD: ", cmd)
if not cmd.endswith("\n"):
cmd = f"{cmd}\n"
cmd = cmd + "\n"
local_cmd = []
# For dom0
@@ -94,7 +93,7 @@ class Connection(ConnectionBase):
display.vvvv("Local cmd: ", local_cmd)
display.vvv(f"RUN {local_cmd}", host=self._remote_vmname)
display.vvv("RUN %s" % (local_cmd,), host=self._remote_vmname)
p = subprocess.Popen(local_cmd, shell=False, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@@ -113,42 +112,42 @@ class Connection(ConnectionBase):
"""Run specified command in a running QubesVM """
super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
display.vvvv(f"CMD IS: {cmd}")
display.vvvv("CMD IS: %s" % cmd)
rc, stdout, stderr = self._qubes(cmd)
display.vvvvv(f"STDOUT {stdout!r} STDERR {stderr!r}")
display.vvvvv("STDOUT %r STDERR %r" % (stderr, stderr))
return rc, stdout, stderr
def put_file(self, in_path, out_path):
""" Place a local file located in 'in_path' inside VM at 'out_path' """
super(Connection, self).put_file(in_path, out_path)
display.vvv(f"PUT {in_path} TO {out_path}", host=self._remote_vmname)
display.vvv("PUT %s TO %s" % (in_path, out_path), host=self._remote_vmname)
with open(in_path, "rb") as fobj:
source_data = fobj.read()
retcode, dummy, dummy = self._qubes(f'cat > "{out_path}\"\n', source_data, "qubes.VMRootShell")
retcode, dummy, dummy = self._qubes('cat > "{0}"\n'.format(out_path), source_data, "qubes.VMRootShell")
# if qubes.VMRootShell service not supported, fallback to qubes.VMShell and
# hope it will have appropriate permissions
if retcode == 127:
retcode, dummy, dummy = self._qubes(f'cat > "{out_path}\"\n', source_data)
retcode, dummy, dummy = self._qubes('cat > "{0}"\n'.format(out_path), source_data)
if retcode != 0:
raise AnsibleConnectionFailure(f'Failed to put_file to {out_path}')
raise AnsibleConnectionFailure('Failed to put_file to {0}'.format(out_path))
def fetch_file(self, in_path, out_path):
"""Obtain file specified via 'in_path' from the container and place it at 'out_path' """
super(Connection, self).fetch_file(in_path, out_path)
display.vvv(f"FETCH {in_path} TO {out_path}", host=self._remote_vmname)
display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self._remote_vmname)
# We are running in dom0
cmd_args_list = ["qvm-run", "--pass-io", self._remote_vmname, f"cat {in_path}"]
cmd_args_list = ["qvm-run", "--pass-io", self._remote_vmname, "cat {0}".format(in_path)]
with open(out_path, "wb") as fobj:
p = subprocess.Popen(cmd_args_list, shell=False, stdout=fobj)
p.communicate()
if p.returncode != 0:
raise AnsibleConnectionFailure(f'Failed to fetch file to {out_path}')
raise AnsibleConnectionFailure('Failed to fetch file to {0}'.format(out_path))
def close(self):
""" Closing the connection """

View File

@@ -10,13 +10,13 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Michael Scherer (@mscherer) <misc@zarb.org>
name: saltstack
short_description: Allow ansible to piggyback on salt minions
description:
- This allows you to use existing Saltstack infrastructure to connect to targets.
"""
DOCUMENTATION = '''
author: Michael Scherer (@mscherer) <misc@zarb.org>
name: saltstack
short_description: Allow ansible to piggyback on salt minions
description:
- This allows you to use existing Saltstack infrastructure to connect to targets.
'''
import os
import base64
@@ -59,11 +59,11 @@ class Connection(ConnectionBase):
if in_data:
raise errors.AnsibleError("Internal Error: this module does not support optimized module pipelining")
self._display.vvv(f"EXEC {cmd}", host=self.host)
self._display.vvv("EXEC %s" % cmd, host=self.host)
# need to add 'true;' to work around https://github.com/saltstack/salt/issues/28077
res = self.client.cmd(self.host, 'cmd.exec_code_all', ['bash', f"true;{cmd}"])
res = self.client.cmd(self.host, 'cmd.exec_code_all', ['bash', 'true;' + cmd])
if self.host not in res:
raise errors.AnsibleError(f"Minion {self.host} didn't answer, check if salt-minion is running and the name is correct")
raise errors.AnsibleError("Minion %s didn't answer, check if salt-minion is running and the name is correct" % self.host)
p = res[self.host]
return p['retcode'], p['stdout'], p['stderr']
@@ -81,7 +81,7 @@ class Connection(ConnectionBase):
super(Connection, self).put_file(in_path, out_path)
out_path = self._normalize_path(out_path, '/')
self._display.vvv(f"PUT {in_path} TO {out_path}", host=self.host)
self._display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.host)
with open(in_path, 'rb') as in_fh:
content = in_fh.read()
self.client.cmd(self.host, 'hashutil.base64_decodefile', [base64.b64encode(content), out_path])
@@ -93,7 +93,7 @@ class Connection(ConnectionBase):
super(Connection, self).fetch_file(in_path, out_path)
in_path = self._normalize_path(in_path, '/')
self._display.vvv(f"FETCH {in_path} TO {out_path}", host=self.host)
self._display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.host)
content = self.client.cmd(self.host, 'cp.get_file_str', [in_path])[self.host]
open(out_path, 'wb').write(content)

View File

@@ -11,22 +11,21 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r"""
author: Ansible Core Team
name: zone
short_description: Run tasks in a zone instance
description:
- Run commands or put/fetch files to an existing zone.
options:
remote_addr:
DOCUMENTATION = '''
author: Ansible Core Team
name: zone
short_description: Run tasks in a zone instance
description:
- Zone identifier.
type: string
default: inventory_hostname
vars:
- name: ansible_host
- name: ansible_zone_host
"""
- Run commands or put/fetch files to an existing zone
options:
remote_addr:
description:
- Zone identifier
default: inventory_hostname
vars:
- name: ansible_host
- name: ansible_zone_host
'''
import os
import os.path
@@ -62,14 +61,14 @@ class Connection(ConnectionBase):
self.zlogin_cmd = to_bytes(self._search_executable('zlogin'))
if self.zone not in self.list_zones():
raise AnsibleError(f"incorrect zone name {self.zone}")
raise AnsibleError("incorrect zone name %s" % self.zone)
@staticmethod
def _search_executable(executable):
try:
return get_bin_path(executable)
except ValueError:
raise AnsibleError(f"{executable} command not found in PATH")
raise AnsibleError("%s command not found in PATH" % executable)
def list_zones(self):
process = subprocess.Popen([self.zoneadm_cmd, 'list', '-ip'],
@@ -94,7 +93,7 @@ class Connection(ConnectionBase):
# stdout, stderr = p.communicate()
path = process.stdout.readlines()[0].split(':')[3]
return f"{path}/root"
return path + '/root'
def _connect(self):
""" connect to the zone; nothing to do here """
@@ -117,7 +116,7 @@ class Connection(ConnectionBase):
local_cmd = [self.zlogin_cmd, self.zone, cmd]
local_cmd = map(to_bytes, local_cmd)
display.vvv(f"EXEC {local_cmd}", host=self.zone)
display.vvv("EXEC %s" % (local_cmd), host=self.zone)
p = subprocess.Popen(local_cmd, shell=False, stdin=stdin,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@@ -140,7 +139,7 @@ class Connection(ConnectionBase):
exist in any given chroot. So for now we're choosing "/" instead.
This also happens to be the former default.
Can revisit using $HOME instead if it is a problem
Can revisit using $HOME instead if it's a problem
"""
if not remote_path.startswith(os.path.sep):
remote_path = os.path.join(os.path.sep, remote_path)
@@ -149,7 +148,7 @@ class Connection(ConnectionBase):
def put_file(self, in_path, out_path):
""" transfer a file from local to zone """
super(Connection, self).put_file(in_path, out_path)
display.vvv(f"PUT {in_path} TO {out_path}", host=self.zone)
display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.zone)
out_path = shlex_quote(self._prefix_login_path(out_path))
try:
@@ -159,27 +158,27 @@ class Connection(ConnectionBase):
else:
count = ''
try:
p = self._buffered_exec_command(f'dd of={out_path} bs={BUFSIZE}{count}', stdin=in_file)
p = self._buffered_exec_command('dd of=%s bs=%s%s' % (out_path, BUFSIZE, count), stdin=in_file)
except OSError:
raise AnsibleError("jail connection requires dd command in the jail")
try:
stdout, stderr = p.communicate()
except Exception:
traceback.print_exc()
raise AnsibleError(f"failed to transfer file {in_path} to {out_path}")
raise AnsibleError("failed to transfer file %s to %s" % (in_path, out_path))
if p.returncode != 0:
raise AnsibleError(f"failed to transfer file {in_path} to {out_path}:\n{stdout}\n{stderr}")
raise AnsibleError("failed to transfer file %s to %s:\n%s\n%s" % (in_path, out_path, stdout, stderr))
except IOError:
raise AnsibleError(f"file or module does not exist at: {in_path}")
raise AnsibleError("file or module does not exist at: %s" % in_path)
def fetch_file(self, in_path, out_path):
""" fetch a file from zone to local """
super(Connection, self).fetch_file(in_path, out_path)
display.vvv(f"FETCH {in_path} TO {out_path}", host=self.zone)
display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self.zone)
in_path = shlex_quote(self._prefix_login_path(in_path))
try:
p = self._buffered_exec_command(f'dd if={in_path} bs={BUFSIZE}')
p = self._buffered_exec_command('dd if=%s bs=%s' % (in_path, BUFSIZE))
except OSError:
raise AnsibleError("zone connection requires dd command in the zone")
@@ -191,10 +190,10 @@ class Connection(ConnectionBase):
chunk = p.stdout.read(BUFSIZE)
except Exception:
traceback.print_exc()
raise AnsibleError(f"failed to transfer file {in_path} to {out_path}")
raise AnsibleError("failed to transfer file %s to %s" % (in_path, out_path))
stdout, stderr = p.communicate()
if p.returncode != 0:
raise AnsibleError(f"failed to transfer file {in_path} to {out_path}:\n{stdout}\n{stderr}")
raise AnsibleError("failed to transfer file %s to %s:\n%s\n%s" % (in_path, out_path, stdout, stderr))
def close(self):
""" terminate the connection; nothing to do here """

View File

@@ -11,73 +11,75 @@ __metaclass__ = type
class ModuleDocFragment(object):
# Alicloud only documentation fragment
DOCUMENTATION = r"""
DOCUMENTATION = r'''
options:
alicloud_access_key:
description:
- Alibaba Cloud access key. If not set then the value of environment variable E(ALICLOUD_ACCESS_KEY), E(ALICLOUD_ACCESS_KEY_ID)
will be used instead.
- Alibaba Cloud access key. If not set then the value of environment variable E(ALICLOUD_ACCESS_KEY),
E(ALICLOUD_ACCESS_KEY_ID) will be used instead.
aliases: ['access_key_id', 'access_key']
type: str
alicloud_secret_key:
description:
- Alibaba Cloud secret key. If not set then the value of environment variable E(ALICLOUD_SECRET_KEY), E(ALICLOUD_SECRET_ACCESS_KEY)
will be used instead.
- Alibaba Cloud secret key. If not set then the value of environment variable E(ALICLOUD_SECRET_KEY),
E(ALICLOUD_SECRET_ACCESS_KEY) will be used instead.
aliases: ['secret_access_key', 'secret_key']
type: str
alicloud_region:
description:
- The Alibaba Cloud region to use. If not specified then the value of environment variable E(ALICLOUD_REGION), E(ALICLOUD_REGION_ID)
will be used instead.
- The Alibaba Cloud region to use. If not specified then the value of environment variable
E(ALICLOUD_REGION), E(ALICLOUD_REGION_ID) will be used instead.
aliases: ['region', 'region_id']
required: true
type: str
alicloud_security_token:
description:
- The Alibaba Cloud security token. If not specified then the value of environment variable E(ALICLOUD_SECURITY_TOKEN)
will be used instead.
- The Alibaba Cloud security token. If not specified then the value of environment variable
E(ALICLOUD_SECURITY_TOKEN) will be used instead.
aliases: ['security_token']
type: str
alicloud_assume_role:
description:
- If provided with a role ARN, Ansible will attempt to assume this role using the supplied credentials.
- The nested assume_role block supports C(alicloud_assume_role_arn), C(alicloud_assume_role_session_name), C(alicloud_assume_role_session_expiration)
and C(alicloud_assume_role_policy).
- The nested assume_role block supports C(alicloud_assume_role_arn), C(alicloud_assume_role_session_name),
C(alicloud_assume_role_session_expiration) and C(alicloud_assume_role_policy).
type: dict
aliases: ['assume_role']
alicloud_assume_role_arn:
description:
- The Alibaba Cloud C(role_arn). The ARN of the role to assume. If ARN is set to an empty string, it does not perform
role switching. It supports environment variable E(ALICLOUD_ASSUME_ROLE_ARN). ansible will execute with provided credentials.
- The Alibaba Cloud C(role_arn). The ARN of the role to assume. If ARN is set to an empty string,
it does not perform role switching. It supports environment variable E(ALICLOUD_ASSUME_ROLE_ARN).
ansible will execute with provided credentials.
aliases: ['assume_role_arn']
type: str
alicloud_assume_role_session_name:
description:
- The Alibaba Cloud session_name. The session name to use when assuming the role. If omitted, 'ansible' is passed to
the AssumeRole call as session name. It supports environment variable E(ALICLOUD_ASSUME_ROLE_SESSION_NAME).
- The Alibaba Cloud session_name. The session name to use when assuming the role. If omitted,
'ansible' is passed to the AssumeRole call as session name. It supports environment variable
E(ALICLOUD_ASSUME_ROLE_SESSION_NAME).
aliases: ['assume_role_session_name']
type: str
alicloud_assume_role_session_expiration:
description:
- The Alibaba Cloud C(session_expiration). The time after which the established session for assuming role expires. Valid
value range 900-3600 seconds. Default to 3600 (in this case Alicloud use own default value). It supports environment
variable E(ALICLOUD_ASSUME_ROLE_SESSION_EXPIRATION).
- The Alibaba Cloud C(session_expiration). The time after which the established session for assuming
role expires. Valid value range 900-3600 seconds. Default to 3600 (in this case Alicloud use own default
value). It supports environment variable E(ALICLOUD_ASSUME_ROLE_SESSION_EXPIRATION).
aliases: ['assume_role_session_expiration']
type: int
ecs_role_name:
description:
- The RAM Role Name attached on a ECS instance for API operations. You can retrieve this from the 'Access Control' section
of the Alibaba Cloud console.
- If you are running Ansible from an ECS instance with RAM Instance using RAM Role, Ansible will just access the metadata
U(http://100.100.100.200/latest/meta-data/ram/security-credentials/<ecs_role_name>) to obtain the STS credential.
This is a preferred approach over any other when running in ECS as you can avoid hard coding credentials. Instead
these are leased on-the-fly by Ansible which reduces the chance of leakage.
- The RAM Role Name attached on a ECS instance for API operations. You can retrieve this from the 'Access Control'
section of the Alibaba Cloud console.
- If you're running Ansible from an ECS instance with RAM Instance using RAM Role, Ansible will just access the
metadata U(http://100.100.100.200/latest/meta-data/ram/security-credentials/<ecs_role_name>) to obtain the STS
credential. This is a preferred approach over any other when running in ECS as you can avoid hard coding
credentials. Instead these are leased on-the-fly by Ansible which reduces the chance of leakage.
aliases: ['role_name']
type: str
profile:
description:
- This is the Alicloud profile name as set in the shared credentials file. It can also be sourced from the E(ALICLOUD_PROFILE)
environment variable.
- This is the Alicloud profile name as set in the shared credentials file. It can also be sourced from the
E(ALICLOUD_PROFILE) environment variable.
type: str
shared_credentials_file:
description:
@@ -86,14 +88,22 @@ options:
- If this is not set and a profile is specified, C(~/.aliyun/config.json) will be used.
type: str
author:
- "He Guimin (@xiaozhu36)"
- "He Guimin (@xiaozhu36)"
requirements:
- "Python >= 3.6"
- "Python >= 3.6"
notes:
- If parameters are not set within the module, the following environment variables can be used in decreasing order of precedence
E(ALICLOUD_ACCESS_KEY) or E(ALICLOUD_ACCESS_KEY_ID), E(ALICLOUD_SECRET_KEY) or E(ALICLOUD_SECRET_ACCESS_KEY), E(ALICLOUD_REGION)
or E(ALICLOUD_REGION_ID), E(ALICLOUD_SECURITY_TOKEN), E(ALICLOUD_ECS_ROLE_NAME), E(ALICLOUD_SHARED_CREDENTIALS_FILE),
E(ALICLOUD_PROFILE), E(ALICLOUD_ASSUME_ROLE_ARN), E(ALICLOUD_ASSUME_ROLE_SESSION_NAME), E(ALICLOUD_ASSUME_ROLE_SESSION_EXPIRATION).
- E(ALICLOUD_REGION) or E(ALICLOUD_REGION_ID) can be typically be used to specify the Alicloud region, when required, but
this can also be configured in the footmark config file.
"""
- If parameters are not set within the module, the following
environment variables can be used in decreasing order of precedence
E(ALICLOUD_ACCESS_KEY) or E(ALICLOUD_ACCESS_KEY_ID),
E(ALICLOUD_SECRET_KEY) or E(ALICLOUD_SECRET_ACCESS_KEY),
E(ALICLOUD_REGION) or E(ALICLOUD_REGION_ID),
E(ALICLOUD_SECURITY_TOKEN),
E(ALICLOUD_ECS_ROLE_NAME),
E(ALICLOUD_SHARED_CREDENTIALS_FILE),
E(ALICLOUD_PROFILE),
E(ALICLOUD_ASSUME_ROLE_ARN),
E(ALICLOUD_ASSUME_ROLE_SESSION_NAME),
E(ALICLOUD_ASSUME_ROLE_SESSION_EXPIRATION).
- E(ALICLOUD_REGION) or E(ALICLOUD_REGION_ID) can be typically be used to specify the
Alicloud region, when required, but this can also be configured in the footmark config file
'''

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