Compare commits

..

37 Commits
4.7.0 ... 3.0.2

Author SHA1 Message Date
Felix Fontein
80fbcf2f98 Release 3.0.2. 2021-05-11 07:08:11 +02:00
patchback[bot]
a722e038cc Avoid incorrectly marking zfs tasks as changed (#2454) (#2484)
* Avoid incorrectly marking zfs tasks as changed

The zfs module will incorrectly mark certain tasks as having been
changed. For example, if a dataset has a quota of "1G" and the user
changes it to "1024M", the actual quota vale has not changed, but since
the module is doing a simple string comparison between "1G" and "1024M",
it marks the step as "changed".

Instead of trying to handle all the corner cases of zfs (another example
is when the zpool "altroot" property has been set), this change simply
compares the output of "zfs-get" from before and after "zfs-set" is
called

* update changelog format

* Update changelogs/fragments/2454-detect_zfs_changed.yml

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

* add note about check_mode

* Update plugins/modules/storage/zfs/zfs.py

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

* Update plugins/modules/storage/zfs/zfs.py

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

* clarify check mode qualifications

* rephrase to avoid hypothetical

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

Co-authored-by: sam-lunt <samuel.j.lunt@gmail.com>
2021-05-10 18:17:03 +02:00
Felix Fontein
19c8d2164d Prepare 3.0.2 release. 2021-05-10 18:00:08 +02:00
patchback[bot]
d4656ffca2 Clarify Windows (non-)support. (#2476) (#2482)
(cherry picked from commit 2e58dfe52a)

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-10 17:14:34 +02:00
patchback[bot]
b49607f12d fix stackpath_compute validate_config (#2448) (#2475)
* fix stackpath_compute validate_config

get the lenght for the client_id / client_secret to validate inventory configuration

* Add changelog fragment.

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

Co-authored-by: vbarba <victor.barba@gmail.com>
2021-05-09 22:46:17 +02:00
patchback[bot]
af0ce4284f Small Documentation Example Of Cask Leveraging (#2462) (#2470)
* Small Documentation Example Of Cask Leveraging

- Just a lil' demo showing that we can utilize homebrew/cask/foo syntax
for given name of package to grab associated cask pacakge

Resolves: patch/sml-doc-example-update

* Slight Documentation Example Edit

- adjusting documentation example to provide better info surrounding installing
a given formula from brew via cask

Resolves: patch/sml-doc-example-update

* Small Edits To Make PEP8 Happy

- format code with autopep8 in vs code

Resolves: patch/sml-doc-example-update

* Only Making Small PEP8 Change

- reverting previous mass PEP8 format, focus on trimming whitespace on
doc example entry

Resolves: patch/sml-doc-example-update

* Remove Trailing Whitespace PEP8

- removed trailing whitespace on doc example chunk

Resolves: patch/sml-doc-example-update
(cherry picked from commit 7386326258)

Co-authored-by: Mike Russell <michael.j.russell.email@gmail.com>
2021-05-08 12:18:28 +02:00
patchback[bot]
f5f862617a Add more plugin authors to BOTMETA. (#2451) (#2453)
(cherry picked from commit 188a4eeb0c)

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-05 07:52:09 +02:00
Felix Fontein
a1a4ba4337 Next expected release is 3.0.2 next week. 2021-05-04 13:21:05 +02:00
Felix Fontein
b0b783f8ff Release 3.0.1. 2021-05-04 12:45:19 +02:00
patchback[bot]
e670ca666a OpenNebula one_vm.py: Fix missing keys (#2435) (#2447)
* OpenNebula one_vm.py: Fix missing keys

* fixup OpenNebula one_vm.py: Fix missing keys

(cherry picked from commit aaa561163b)

Co-authored-by: Jan Orel <jorel@opennebula.io>
2021-05-04 12:43:25 +02:00
patchback[bot]
49b991527e Remove shippable config. (#2440) (#2444)
(cherry picked from commit 1f41e66f09)

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-03 22:56:40 +02:00
patchback[bot]
e6cc671a0d lvol - bug fix - Convert units to lowercase when using LVS or VGS command (#2369) (#2439)
* Added lower call for units when checking lvs/vgs size

* Changelog

* Size roudning correction

* Rounding

* Changelog

* Remove whitespace

(cherry picked from commit 06bdabcad9)

Co-authored-by: zigaSRC <65527456+zigaSRC@users.noreply.github.com>
2021-05-03 22:07:52 +02:00
patchback[bot]
797ea23e50 Clean up test entries from sysrc tests (#2330) (#2438)
* Clean up test entries from sysrc tests

* sysrc: enable tests

* sysrc: cache the files to be changed and restore them

* Update the ezjail archive host and remove obsolete file

* sysrc: set ezjail to use archives for 12.0 or less

* sysrc: Detect the version to use ftp vs ftp-archive using http

* sysrc: Skip ezjail test on FreeBSD 12.0

(cherry picked from commit 7007c68ab7)

Co-authored-by: David Lundgren <dlundgren@syberisle.net>
2021-05-03 21:34:19 +02:00
patchback[bot]
4d23b7a48b linode_v4 - fixed error message (#2430) (#2433)
* fixed error message

* added changelog fragment

(cherry picked from commit 5064aa8ec6)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-05-03 13:51:38 +02:00
patchback[bot]
020b47a1a9 Make plugins pass validation. (#2414) (#2431)
(cherry picked from commit 6a72c3b338)

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-03 13:51:10 +02:00
patchback[bot]
0da9d956a0 nmcli: Compare MAC addresses case insensitively (#2416) (#2425)
* nmcli: Compare MAC addresses case insensitively

* Update changelogs/fragments/2416-nmcli_compare_mac_addresses_case_insensitively.yml

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

* Update plugins/modules/net_tools/nmcli.py

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

* Add mac to TESTCASE_BRIDGE so test_bridge_connection_unchanged covers case sensitive mac address comparison

* Update plugins/modules/net_tools/nmcli.py

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

* Convert current_value to uppercase as well in case nmcli changes behaviour

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

Co-authored-by: spike77453 <spike77453@users.noreply.github.com>
2021-05-03 08:17:32 +02:00
patchback[bot]
5691e3aff3 nmcli: Add 'slave-type bridge' to nmcli command if type is bridge-slave (#2409) (#2423)
(cherry picked from commit b5f8ae4320)

Co-authored-by: spike77453 <spike77453@users.noreply.github.com>
2021-05-03 08:16:19 +02:00
patchback[bot]
007333dbfe 📝 Document nested node addition with "_" in xml module (#2371) (#2427)
* 📝 Document nested node addition with "_" in xml module

Nested node addition using "_" to indicate sub nodes, and attributes are only documented in tests and issues, where is hard to find.

* 🚨 Fix trailing space

* Apply suggestions from code review

Add missing collection prefix for modules.

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

* Add missing comments

* Update xml.py

* Fix linter warnings

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

Co-authored-by: Daniel-Sanchez-Fabregas <33929811+Daniel-Sanchez-Fabregas@users.noreply.github.com>
2021-05-03 08:12:31 +02:00
patchback[bot]
05666b0e4d puppet - replace stdout with console in logdest option (#2407) (#2421)
* Change stdout to console

* readd stdout, resulting in console

* add changelog

* readd stdout to docs and add a warning when it is used

* version of what???

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

* postpone deprecation in another PR

* remove console option, so it can be backported

* change changelog respectively

* Fix changelog formatting

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

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

Co-authored-by: Amin Vakil <info@aminvakil.com>
2021-05-03 07:59:33 +02:00
patchback[bot]
c934d9aeb5 Fix #2373 - TypeError: a bytes-like object is required, not 'str' (#2375) (#2419)
* Fix #2373

* Changelog fragment for #2373

* Update changelogs/fragments/2373-svr4pkg-fix-typeerror.yml

Co-authored-by: Amin Vakil <info@aminvakil.com>

* Update changelogs/fragments/2373-svr4pkg-fix-typeerror.yml

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

Co-authored-by: Amin Vakil <info@aminvakil.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit cd957fae4c)

Co-authored-by: Daniel Werner <srmlsrml@gmail.com>
2021-05-03 07:56:05 +02:00
Felix Fontein
5b15e4089a Revert "spotinst_aws_elastigroup - fixed elements for many lists (#2355) (#2363)"
This reverts commit ea42b75378.

(Will be re-reverted after the 3.0.1 release.)
2021-05-03 07:48:12 +02:00
Felix Fontein
a6379e45ce Prepare 3.0.1 release. 2021-05-03 07:47:48 +02:00
Felix Fontein
b95176dbc8 Copy schedule to stable branches. 2021-05-02 13:35:45 +02:00
patchback[bot]
b752fea121 BOTMETA.yml: terraform - add a new maintainer (#2290) (#2413)
(cherry picked from commit c0221b75af)

Co-authored-by: Andrew Klychkov <aklychko@redhat.com>
2021-05-02 13:27:43 +02:00
patchback[bot]
cf50990fed Add ansible-test config file. (#2404) (#2406)
(cherry picked from commit 4e90ee752e)

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-01 22:54:44 +02:00
patchback[bot]
45343e6bc0 composer: --no-interaction when discovering available options (#2348) (#2403)
The composer module always uses the no-interaction option if it
discovers it _after_ calling "composer help ..." but not on the help
call itself. The lack of this option caused composer to not exit when
called through the ansible module.

The same example command when ran interactively does not prompt for user
interaction and exits immediately. It is therefore currently unknown why
the same command hangs when called through the ansible composer module
or even directly with the command module.

Example command which hangs:
php /usr/local/bin/composer help install --format=json

(cherry picked from commit eb455c69a2)

Co-authored-by: George Angelopoulos <george@usermod.net>
2021-05-01 18:46:16 +02:00
patchback[bot]
51540f6345 influxdb_retention_policy: fix duration parsing to support INF values (#2396) (#2401)
* influxdb_retention_policy: fix duration parsing to support INF values

* add changelog

(cherry picked from commit 26c3bd25f6)

Co-authored-by: Xabier Napal <xabiernapal@pm.me>
2021-05-01 14:37:19 +02:00
patchback[bot]
74eba52028 Remove resmo as composer maintainer. (#2392) (#2395)
(cherry picked from commit 276880aac1)

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-01 14:11:16 +02:00
patchback[bot]
b920e8abf2 Add Fedora 34 to CI (#2384) (#2391)
* Add fedora 34 and fix typo

* Remove Fedora 32 from devel testing

* Use one newer version of Fedora for fixed ansible versions

* Revert "Use one newer version of Fedora for fixed ansible versions"

This reverts commit cbd006bd38.

* Try to skip task.

* Revert "Try to skip task."

This reverts commit ff0c899a86.

* Temporary disable Fedora 34 on setup_postgresql_db

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

Co-authored-by: Amin Vakil <info@aminvakil.com>
2021-05-01 14:10:07 +02:00
patchback[bot]
75c0004e1e Use Ansible's codecov uploader. (#2377) (#2380)
(cherry picked from commit b3f436aa63)

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-04-30 05:32:23 +02:00
patchback[bot]
be42fd4af7 No longer required for devel's ansible-test. (#2365) (#2367)
ci_complete

(cherry picked from commit 77d4bc2942)

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-04-27 22:44:21 +02:00
patchback[bot]
1c05908ff6 BOTMETA.yml: team_suse - add a maintainer (#2354) (#2362)
(cherry picked from commit 9d13acd68e)

Co-authored-by: Andrew Klychkov <aklychko@redhat.com>
2021-04-27 13:46:28 +02:00
patchback[bot]
ea42b75378 spotinst_aws_elastigroup - fixed elements for many lists (#2355) (#2363)
* fixed elements for many lists

* added changelog fragment

* Removed verbose types in description - still missing formatting and properly documenting dicts

(cherry picked from commit 48ef05def3)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-04-27 11:46:17 +00:00
patchback[bot]
0330f4b52c Make inventory scripts executable (#2337) (#2359)
* Make inventory scripts executable

* Mark inventory scripts in vault folder as executable

* Add changelog entry for making inventory scripts exectuable

* Update changelogs/fragments/2337-mark-inventory-scripts-executable.yml

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

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

Co-authored-by: Alan Rominger <arominge@redhat.com>
2021-04-26 22:24:42 +02:00
Felix Fontein
1d8c659ba2 Next expected release is 3.0.0. 2021-04-26 21:19:55 +02:00
Felix Fontein
e784254679 Release 3.0.0. 2021-04-26 18:40:14 +02:00
Felix Fontein
d5e1edd284 Add release summary. 2021-04-26 18:38:45 +02:00
1485 changed files with 37523 additions and 60526 deletions

View File

@@ -24,15 +24,14 @@ schedules:
always: true always: true
branches: branches:
include: include:
- stable-2
- stable-3 - stable-3
- stable-4
- cron: 0 11 * * 0 - cron: 0 11 * * 0
displayName: Weekly (old stable branches) displayName: Weekly (old stable branches)
always: true always: true
branches: branches:
include: include:
- stable-1 - stable-1
- stable-2
variables: variables:
- name: checkoutPath - name: checkoutPath
@@ -69,32 +68,6 @@ stages:
- test: 3 - test: 3
- test: 4 - test: 4
- test: extra - test: extra
- stage: Sanity_2_13
displayName: Sanity 2.13
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Test {0}
testFormat: 2.13/sanity/{0}
targets:
- test: 1
- test: 2
- test: 3
- test: 4
- stage: Sanity_2_12
displayName: Sanity 2.12
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Test {0}
testFormat: 2.12/sanity/{0}
targets:
- test: 1
- test: 2
- test: 3
- test: 4
- stage: Sanity_2_11 - stage: Sanity_2_11
displayName: Sanity 2.11 displayName: Sanity 2.11
dependsOn: [] dependsOn: []
@@ -144,38 +117,13 @@ stages:
nameFormat: Python {0} nameFormat: Python {0}
testFormat: devel/units/{0}/1 testFormat: devel/units/{0}/1
targets: targets:
- test: 2.6
- test: 2.7 - test: 2.7
- test: 3.5 - test: 3.5
- test: 3.6 - test: 3.6
- test: 3.7 - test: 3.7
- test: 3.8 - test: 3.8
- test: 3.9 - test: 3.9
- test: '3.10'
- stage: Units_2_13
displayName: Units 2.13
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: 2.13/units/{0}/1
targets:
- test: 2.7
- test: 3.6
- test: 3.8
- test: 3.9
- stage: Units_2_12
displayName: Units 2.12
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: 2.12/units/{0}/1
targets:
- test: 2.6
- test: 3.5
- test: 3.8
- stage: Units_2_11 - stage: Units_2_11
displayName: Units 2.11 displayName: Units 2.11
dependsOn: [] dependsOn: []
@@ -188,6 +136,9 @@ stages:
- test: 2.6 - test: 2.6
- test: 2.7 - test: 2.7
- test: 3.5 - test: 3.5
- test: 3.6
- test: 3.7
- test: 3.8
- test: 3.9 - test: 3.9
- stage: Units_2_10 - stage: Units_2_10
displayName: Units 2.10 displayName: Units 2.10
@@ -198,8 +149,13 @@ stages:
nameFormat: Python {0} nameFormat: Python {0}
testFormat: 2.10/units/{0}/1 testFormat: 2.10/units/{0}/1
targets: targets:
- test: 2.6
- test: 2.7 - test: 2.7
- test: 3.5
- test: 3.6 - test: 3.6
- test: 3.7
- test: 3.8
- test: 3.9
- stage: Units_2_9 - stage: Units_2_9
displayName: Units 2.9 displayName: Units 2.9
dependsOn: [] dependsOn: []
@@ -210,7 +166,11 @@ stages:
testFormat: 2.9/units/{0}/1 testFormat: 2.9/units/{0}/1
targets: targets:
- test: 2.6 - test: 2.6
- test: 2.7
- test: 3.5 - test: 3.5
- test: 3.6
- test: 3.7
- test: 3.8
## Remote ## Remote
- stage: Remote_devel - stage: Remote_devel
@@ -220,54 +180,21 @@ stages:
- template: templates/matrix.yml - template: templates/matrix.yml
parameters: parameters:
testFormat: devel/{0} testFormat: devel/{0}
targets:
- name: macOS 12.0
test: macos/12.0
- name: RHEL 7.9
test: rhel/7.9
- name: RHEL 8.5
test: rhel/8.5
- name: FreeBSD 12.3
test: freebsd/12.3
- name: FreeBSD 13.0
test: freebsd/13.0
groups:
- 1
- 2
- 3
- stage: Remote_2_13
displayName: Remote 2.13
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.13/{0}
targets:
- name: macOS 12.0
test: macos/12.0
- name: RHEL 8.5
test: rhel/8.5
groups:
- 1
- 2
- 3
- stage: Remote_2_12
displayName: Remote 2.12
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.12/{0}
targets: targets:
- name: macOS 11.1 - name: macOS 11.1
test: macos/11.1 test: macos/11.1
- name: RHEL 8.4 - name: RHEL 7.9
test: rhel/8.4 test: rhel/7.9
- name: RHEL 8.3
test: rhel/8.3
- name: FreeBSD 12.2
test: freebsd/12.2
- name: FreeBSD 13.0 - name: FreeBSD 13.0
test: freebsd/13.0 test: freebsd/13.0
groups: groups:
- 1 - 1
- 2 - 2
- 3
- stage: Remote_2_11 - stage: Remote_2_11
displayName: Remote 2.11 displayName: Remote 2.11
dependsOn: [] dependsOn: []
@@ -276,6 +203,8 @@ stages:
parameters: parameters:
testFormat: 2.11/{0} testFormat: 2.11/{0}
targets: targets:
- name: macOS 11.1
test: macos/11.1
- name: RHEL 7.9 - name: RHEL 7.9
test: rhel/7.9 test: rhel/7.9
- name: RHEL 8.3 - name: RHEL 8.3
@@ -297,6 +226,14 @@ stages:
test: osx/10.11 test: osx/10.11
- name: macOS 10.15 - name: macOS 10.15
test: macos/10.15 test: macos/10.15
- name: macOS 11.1
test: macos/11.1
- name: RHEL 7.8
test: rhel/7.8
- name: RHEL 8.2
test: rhel/8.2
- name: FreeBSD 12.1
test: freebsd/12.1
groups: groups:
- 1 - 1
- 2 - 2
@@ -310,8 +247,6 @@ stages:
targets: targets:
- name: RHEL 8.2 - name: RHEL 8.2
test: rhel/8.2 test: rhel/8.2
- name: RHEL 7.8
test: rhel/7.8
- name: FreeBSD 12.0 - name: FreeBSD 12.0
test: freebsd/12.0 test: freebsd/12.0
groups: groups:
@@ -327,56 +262,24 @@ stages:
parameters: parameters:
testFormat: devel/linux/{0} testFormat: devel/linux/{0}
targets: targets:
- name: CentOS 6
test: centos6
- name: CentOS 7 - name: CentOS 7
test: centos7 test: centos7
- name: CentOS 8
test: centos8
- name: Fedora 33
test: fedora33
- name: Fedora 34 - name: Fedora 34
test: fedora34 test: fedora34
- name: Fedora 35 - name: openSUSE 15 py2
test: fedora35 test: opensuse15py2
- name: openSUSE 15 - name: openSUSE 15 py3
test: opensuse15 test: opensuse15
- name: Ubuntu 18.04 - name: Ubuntu 18.04
test: ubuntu1804 test: ubuntu1804
- name: Ubuntu 20.04 - name: Ubuntu 20.04
test: ubuntu2004 test: ubuntu2004
- name: Alpine 3
test: alpine3
groups:
- 1
- 2
- 3
- stage: Docker_2_13
displayName: Docker 2.13
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.13/linux/{0}
targets:
- name: Fedora 35
test: fedora35
- name: openSUSE 15 py2
test: opensuse15py2
- name: Alpine 3
test: alpine3
groups:
- 1
- 2
- 3
- stage: Docker_2_12
displayName: Docker 2.12
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.12/linux/{0}
targets:
- name: CentOS 6
test: centos6
- name: Fedora 34
test: fedora34
- name: Ubuntu 20.04
test: ubuntu2004
groups: groups:
- 1 - 1
- 2 - 2
@@ -389,10 +292,14 @@ stages:
parameters: parameters:
testFormat: 2.11/linux/{0} testFormat: 2.11/linux/{0}
targets: targets:
- name: CentOS 8
test: centos8
- name: Fedora 33 - name: Fedora 33
test: fedora33 test: fedora33
- name: Alpine 3 - name: openSUSE 15 py3
test: alpine3 test: opensuse15
- name: Ubuntu 20.04
test: ubuntu2004
groups: groups:
- 2 - 2
- 3 - 3
@@ -404,8 +311,12 @@ stages:
parameters: parameters:
testFormat: 2.10/linux/{0} testFormat: 2.10/linux/{0}
targets: targets:
- name: CentOS 8
test: centos8
- name: Fedora 32 - name: Fedora 32
test: fedora32 test: fedora32
- name: openSUSE 15 py3
test: opensuse15
- name: Ubuntu 16.04 - name: Ubuntu 16.04
test: ubuntu1604 test: ubuntu1604
groups: groups:
@@ -419,32 +330,16 @@ stages:
parameters: parameters:
testFormat: 2.9/linux/{0} testFormat: 2.9/linux/{0}
targets: targets:
- name: CentOS 8
test: centos8
- name: Fedora 31 - name: Fedora 31
test: fedora31 test: fedora31
- name: openSUSE 15 py3
test: opensuse15
groups: groups:
- 2 - 2
- 3 - 3
### Community Docker
- stage: Docker_community_devel
displayName: Docker (community images) devel
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: devel/linux-community/{0}
targets:
- name: Debian Bullseye
test: debian-bullseye/3.9
- name: ArchLinux
test: archlinux/3.10
- name: CentOS Stream 8
test: centos-stream8/3.8
groups:
- 1
- 2
- 3
### Cloud ### Cloud
- stage: Cloud_devel - stage: Cloud_devel
displayName: Cloud devel displayName: Cloud devel
@@ -454,27 +349,6 @@ stages:
parameters: parameters:
nameFormat: Python {0} nameFormat: Python {0}
testFormat: devel/cloud/{0}/1 testFormat: devel/cloud/{0}/1
targets:
- test: 2.7
- test: '3.10'
- stage: Cloud_2_13
displayName: Cloud 2.13
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: 2.13/cloud/{0}/1
targets:
- test: 3.9
- stage: Cloud_2_12
displayName: Cloud 2.12
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: 2.12/cloud/{0}/1
targets: targets:
- test: 3.8 - test: 3.8
- stage: Cloud_2_11 - stage: Cloud_2_11
@@ -486,6 +360,7 @@ stages:
nameFormat: Python {0} nameFormat: Python {0}
testFormat: 2.11/cloud/{0}/1 testFormat: 2.11/cloud/{0}/1
targets: targets:
- test: 2.7
- test: 3.6 - test: 3.6
- stage: Cloud_2_10 - stage: Cloud_2_10
displayName: Cloud 2.10 displayName: Cloud 2.10
@@ -496,7 +371,7 @@ stages:
nameFormat: Python {0} nameFormat: Python {0}
testFormat: 2.10/cloud/{0}/1 testFormat: 2.10/cloud/{0}/1
targets: targets:
- test: 3.5 - test: 3.6
- stage: Cloud_2_9 - stage: Cloud_2_9
displayName: Cloud 2.9 displayName: Cloud 2.9
dependsOn: [] dependsOn: []
@@ -506,7 +381,7 @@ stages:
nameFormat: Python {0} nameFormat: Python {0}
testFormat: 2.9/cloud/{0}/1 testFormat: 2.9/cloud/{0}/1
targets: targets:
- test: 2.7 - test: 3.6
- stage: Summary - stage: Summary
condition: succeededOrFailed() condition: succeededOrFailed()
dependsOn: dependsOn:
@@ -514,32 +389,21 @@ stages:
- Sanity_2_9 - Sanity_2_9
- Sanity_2_10 - Sanity_2_10
- Sanity_2_11 - Sanity_2_11
- Sanity_2_12
- Sanity_2_13
- Units_devel - Units_devel
- Units_2_9 - Units_2_9
- Units_2_10 - Units_2_10
- Units_2_11 - Units_2_11
- Units_2_12
- Units_2_13
- Remote_devel - Remote_devel
- Remote_2_9 - Remote_2_9
- Remote_2_10 - Remote_2_10
- Remote_2_11 - Remote_2_11
- Remote_2_12
- Remote_2_13
- Docker_devel - Docker_devel
- Docker_2_9 - Docker_2_9
- Docker_2_10 - Docker_2_10
- Docker_2_11 - Docker_2_11
- Docker_2_12
- Docker_2_13
- Docker_community_devel
- Cloud_devel - Cloud_devel
- Cloud_2_9 - Cloud_2_9
- Cloud_2_10 - Cloud_2_10
- Cloud_2_11 - Cloud_2_11
- Cloud_2_12
- Cloud_2_13
jobs: jobs:
- template: templates/coverage.yml - template: templates/coverage.yml

View File

@@ -11,7 +11,7 @@ mkdir "${agent_temp_directory}/coverage/"
options=(--venv --venv-system-site-packages --color -v) options=(--venv --venv-system-site-packages --color -v)
ansible-test coverage combine --group-by command --export "${agent_temp_directory}/coverage/" "${options[@]}" ansible-test coverage combine --export "${agent_temp_directory}/coverage/" "${options[@]}"
if ansible-test coverage analyze targets generate --help >/dev/null 2>&1; then if ansible-test coverage analyze targets generate --help >/dev/null 2>&1; then
# Only analyze coverage if the installed version of ansible-test supports it. # Only analyze coverage if the installed version of ansible-test supports it.

View File

@@ -1,101 +0,0 @@
#!/usr/bin/env python
"""
Upload code coverage reports to codecov.io.
Multiple coverage files from multiple languages are accepted and aggregated after upload.
Python coverage, as well as PowerShell and Python stubs can all be uploaded.
"""
import argparse
import dataclasses
import pathlib
import shutil
import subprocess
import tempfile
import typing as t
import urllib.request
@dataclasses.dataclass(frozen=True)
class CoverageFile:
name: str
path: pathlib.Path
flags: t.List[str]
@dataclasses.dataclass(frozen=True)
class Args:
dry_run: bool
path: pathlib.Path
def parse_args() -> Args:
parser = argparse.ArgumentParser()
parser.add_argument('-n', '--dry-run', action='store_true')
parser.add_argument('path', type=pathlib.Path)
args = parser.parse_args()
# Store arguments in a typed dataclass
fields = dataclasses.fields(Args)
kwargs = {field.name: getattr(args, field.name) for field in fields}
return Args(**kwargs)
def process_files(directory: pathlib.Path) -> t.Tuple[CoverageFile, ...]:
processed = []
for file in directory.joinpath('reports').glob('coverage*.xml'):
name = file.stem.replace('coverage=', '')
# Get flags from name
flags = name.replace('-powershell', '').split('=') # Drop '-powershell' suffix
flags = [flag if not flag.startswith('stub') else flag.split('-')[0] for flag in flags] # Remove "-01" from stub files
processed.append(CoverageFile(name, file, flags))
return tuple(processed)
def upload_files(codecov_bin: pathlib.Path, files: t.Tuple[CoverageFile, ...], dry_run: bool = False) -> None:
for file in files:
cmd = [
str(codecov_bin),
'--name', file.name,
'--file', str(file.path),
]
for flag in file.flags:
cmd.extend(['--flags', flag])
if dry_run:
print(f'DRY-RUN: Would run command: {cmd}')
continue
subprocess.run(cmd, check=True)
def download_file(url: str, dest: pathlib.Path, flags: int, dry_run: bool = False) -> None:
if dry_run:
print(f'DRY-RUN: Would download {url} to {dest} and set mode to {flags:o}')
return
with urllib.request.urlopen(url) as resp:
with dest.open('w+b') as f:
# Read data in chunks rather than all at once
shutil.copyfileobj(resp, f, 64 * 1024)
dest.chmod(flags)
def main():
args = parse_args()
url = 'https://ansible-ci-files.s3.amazonaws.com/codecov/linux/codecov'
with tempfile.TemporaryDirectory(prefix='codecov-') as tmpdir:
codecov_bin = pathlib.Path(tmpdir) / 'codecov'
download_file(url, codecov_bin, 0o755, args.dry_run)
files = process_files(args.path)
upload_files(codecov_bin, files, args.dry_run)
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,27 @@
#!/usr/bin/env bash
# Upload code coverage reports to codecov.io.
# Multiple coverage files from multiple languages are accepted and aggregated after upload.
# Python coverage, as well as PowerShell and Python stubs can all be uploaded.
set -o pipefail -eu
output_path="$1"
curl --silent --show-error https://ansible-ci-files.s3.us-east-1.amazonaws.com/codecov/codecov.sh > codecov.sh
for file in "${output_path}"/reports/coverage*.xml; do
name="${file}"
name="${name##*/}" # remove path
name="${name##coverage=}" # remove 'coverage=' prefix if present
name="${name%.xml}" # remove '.xml' suffix
bash codecov.sh \
-f "${file}" \
-n "${name}" \
-X coveragepy \
-X gcov \
-X fix \
-X search \
-X xcode \
|| echo "Failed to upload code coverage report to codecov.io: ${file}"
done

View File

@@ -12,4 +12,4 @@ if ! ansible-test --help >/dev/null 2>&1; then
pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check
fi fi
ansible-test coverage xml --group-by command --stub --venv --venv-system-site-packages --color -v ansible-test coverage xml --stub --venv --venv-system-site-packages --color -v

View File

@@ -33,7 +33,7 @@ jobs:
summaryFileLocation: "$(outputPath)/reports/$(pipelinesCoverage).xml" summaryFileLocation: "$(outputPath)/reports/$(pipelinesCoverage).xml"
displayName: Publish to Azure Pipelines displayName: Publish to Azure Pipelines
condition: gt(variables.coverageFileCount, 0) condition: gt(variables.coverageFileCount, 0)
- bash: .azure-pipelines/scripts/publish-codecov.py "$(outputPath)" - bash: .azure-pipelines/scripts/publish-codecov.sh "$(outputPath)"
displayName: Publish to codecov.io displayName: Publish to codecov.io
condition: gt(variables.coverageFileCount, 0) condition: gt(variables.coverageFileCount, 0)
continueOnError: true continueOnError: true

442
.github/BOTMETA.yml vendored
View File

@@ -1,82 +1,31 @@
notifications: true
automerge: true automerge: true
files: files:
plugins/: plugins/:
supershipit: quidame supershipit: aminvakil russoz
changelogs/: {}
changelogs/fragments/: changelogs/fragments/:
support: community support: community
$actions: $actions:
labels: action labels: action
$actions/system/iptables_state.py: $actions/aireos.py:
maintainers: quidame labels: aireos cisco networking
$actions/system/shutdown.py: $actions/ironware.py:
maintainers: paulquack
labels: ironware networking
$actions/shutdown.py:
maintainers: nitzmahone samdoran aminvakil maintainers: nitzmahone samdoran aminvakil
$becomes/: $becomes/:
labels: become labels: become
$becomes/doas.py:
maintainers: $team_ansible_core
$becomes/dzdo.py:
maintainers: $team_ansible_core
$becomes/ksu.py:
maintainers: $team_ansible_core
$becomes/machinectl.py:
maintainers: $team_ansible_core
$becomes/pbrun.py:
maintainers: $team_ansible_core
$becomes/pfexec.py:
maintainers: $team_ansible_core
$becomes/pmrun.py:
maintainers: $team_ansible_core
$becomes/sesu.py:
maintainers: nekonyuu
$becomes/sudosu.py:
maintainers: dagwieers
$caches/:
labels: cache
$caches/memcached.py: {}
$caches/pickle.py:
maintainers: bcoca
$caches/redis.py: {}
$caches/yaml.py:
maintainers: bcoca
$callbacks/: $callbacks/:
labels: callbacks labels: callbacks
$callbacks/cgroup_memory_recap.py: {}
$callbacks/context_demo.py: {}
$callbacks/counter_enabled.py: {}
$callbacks/dense.py:
maintainers: dagwieers
$callbacks/diy.py:
maintainers: theque5t
$callbacks/elastic.py:
maintainers: v1v
keywords: apm observability
$callbacks/hipchat.py: {}
$callbacks/jabber.py: {}
$callbacks/loganalytics.py: $callbacks/loganalytics.py:
maintainers: zhcli maintainers: zhcli
$callbacks/logdna.py: {}
$callbacks/logentries.py: {}
$callbacks/log_plays.py: {}
$callbacks/logstash.py: $callbacks/logstash.py:
maintainers: ujenmr maintainers: ujenmr
$callbacks/mail.py:
maintainers: dagwieers
$callbacks/nrdp.py:
maintainers: rverchere
$callbacks/null.py: {}
$callbacks/opentelemetry.py:
maintainers: v1v
keywords: opentelemetry observability
$callbacks/say.py: $callbacks/say.py:
notify: chris-short notify: chris-short
maintainers: $team_macos maintainers: $team_macos
labels: macos say labels: macos say
keywords: brew cask darwin homebrew macosx macports osx keywords: brew cask darwin homebrew macosx macports osx
$callbacks/selective.py: {}
$callbacks/slack.py: {}
$callbacks/splunk.py: {}
$callbacks/sumologic.py: $callbacks/sumologic.py:
maintainers: ryancurrah maintainers: ryancurrah
labels: sumologic labels: sumologic
@@ -85,26 +34,16 @@ files:
$callbacks/unixy.py: $callbacks/unixy.py:
maintainers: akatch maintainers: akatch
labels: unixy labels: unixy
$callbacks/yaml.py: {}
$connections/: $connections/:
labels: connections labels: connections
$connections/chroot.py: {} $connections/kubectl.py:
$connections/funcd.py: maintainers: chouseknecht fabianvf flaper87 maxamillion
maintainers: mscherer labels: k8s kubectl
$connections/iocage.py: {}
$connections/jail.py:
maintainers: $team_ansible_core
$connections/lxc.py: {}
$connections/lxd.py: $connections/lxd.py:
maintainers: mattclay maintainers: mattclay
labels: lxd labels: lxd
$connections/qubes.py:
maintainers: kushaldas
$connections/saltstack.py: $connections/saltstack.py:
maintainers: mscherer
labels: saltstack labels: saltstack
$connections/zone.py:
maintainers: $team_ansible_core
$doc_fragments/: $doc_fragments/:
labels: docs_fragments labels: docs_fragments
$doc_fragments/hpe3par.py: $doc_fragments/hpe3par.py:
@@ -118,120 +57,69 @@ files:
$doc_fragments/xenserver.py: $doc_fragments/xenserver.py:
maintainers: bvitnik maintainers: bvitnik
labels: xenserver labels: xenserver
$filters/counter.py:
maintainers: keilr
$filters/dict.py: $filters/dict.py:
maintainers: felixfontein maintainers: felixfontein
$filters/dict_kv.py: $filters/dict_kv.py:
maintainers: giner maintainers: giner
$filters/from_csv.py: $filters/from_csv.py:
maintainers: Ajpantuso maintainers: Ajpantuso
$filters/groupby:
maintainers: felixfontein
$filters/hashids: $filters/hashids:
maintainers: Ajpantuso maintainers: Ajpantuso
$filters/jc.py: $filters/jc.py:
maintainers: kellyjonbrazil maintainers: kellyjonbrazil
$filters/json_query.py: {}
$filters/list.py: $filters/list.py:
maintainers: vbotka maintainers: vbotka
$filters/path_join_shim.py: $filters/path_join_shim.py:
maintainers: felixfontein maintainers: felixfontein
$filters/random_mac.py: {}
$filters/time.py: $filters/time.py:
maintainers: resmo maintainers: resmo
$filters/unicode_normalize.py:
maintainers: Ajpantuso
$filters/version_sort.py: $filters/version_sort.py:
maintainers: ericzolf maintainers: ericzolf
$httpapis/:
maintainers: $team_networking
labels: networking
$httpapis/ftd.py:
maintainers: $team_networking annikulin
labels: cisco ftd networking
keywords: firepower ftd
$inventories/: $inventories/:
labels: inventories labels: inventories
$inventories/cobbler.py:
maintainers: opoplawski
$inventories/gitlab_runners.py:
maintainers: morph027
$inventories/linode.py: $inventories/linode.py:
maintainers: $team_linode maintainers: $team_linode
labels: cloud linode labels: cloud linode
keywords: linode dynamic inventory script keywords: linode dynamic inventory script
$inventories/lxd.py: $inventories/lxd.py:
maintainers: conloos maintainers: conloos
$inventories/nmap.py: {}
$inventories/online.py:
maintainers: remyleone
$inventories/opennebula.py:
maintainers: feldsam
labels: cloud opennebula
keywords: opennebula dynamic inventory script
$inventories/proxmox.py: $inventories/proxmox.py:
maintainers: $team_virt ilijamt maintainers: $team_virt ilijamt
$inventories/xen_orchestra.py:
maintainers: ddelnano shinuza
$inventories/icinga2.py:
maintainers: BongoEADGC6
$inventories/scaleway.py: $inventories/scaleway.py:
maintainers: $team_scaleway maintainers: $team_scaleway
labels: cloud scaleway labels: cloud scaleway
$inventories/stackpath_compute.py:
maintainers: shayrybak
$inventories/virtualbox.py: {}
$lookups/: $lookups/:
labels: lookups labels: lookups
$lookups/cartesian.py: {}
$lookups/chef_databag.py: {}
$lookups/collection_version.py:
maintainers: felixfontein
$lookups/consul_kv.py: {}
$lookups/credstash.py: {}
$lookups/cyberarkpassword.py:
notify: cyberark-bizdev
labels: cyberarkpassword
$lookups/dependent.py:
maintainers: felixfontein
$lookups/dig.py:
maintainers: jpmens
labels: dig
$lookups/dnstxt.py:
maintainers: jpmens
$lookups/dsv.py:
maintainers: amigus endlesstrax
$lookups/etcd3.py:
maintainers: eric-belhomme
$lookups/etcd.py:
maintainers: jpmens
$lookups/filetree.py:
maintainers: dagwieers
$lookups/flattened.py: {}
$lookups/hiera.py:
maintainers: jparrill
$lookups/keyring.py: {}
$lookups/lastpass.py: {}
$lookups/lmdb_kv.py:
maintainers: jpmens
$lookups/manifold.py:
maintainers: galanoff
labels: manifold
$lookups/onepass: $lookups/onepass:
maintainers: samdoran maintainers: samdoran
labels: onepassword labels: onepassword
$lookups/onepassword.py: $lookups/conjur_variable.py:
maintainers: azenk scottsb notify: cyberark-bizdev
$lookups/onepassword_raw.py: maintainers: $team_cyberark_conjur
maintainers: azenk scottsb labels: conjur_variable
$lookups/passwordstore.py: {} $lookups/cyberarkpassword.py:
$lookups/random_pet.py: notify: cyberark-bizdev
maintainers: Akasurde labels: cyberarkpassword
$lookups/random_string.py: $lookups/dig.py:
maintainers: Akasurde maintainers: jpmens
$lookups/random_words.py: labels: dig
maintainers: konstruktoid
$lookups/redis.py:
maintainers: $team_ansible_core jpmens
$lookups/revbitspss.py:
maintainers: RevBits
$lookups/shelvefile.py: {}
$lookups/tss.py: $lookups/tss.py:
maintainers: amigus endlesstrax maintainers: amigus
$lookups/dsv.py:
maintainers: amigus
$lookups/manifold.py:
maintainers: galanoff
labels: manifold
$lookups/nios:
maintainers: $team_networking sganesh-infoblox
labels: infoblox networking
$module_utils/: $module_utils/:
labels: module_utils labels: module_utils
$module_utils/gitlab.py: $module_utils/gitlab.py:
@@ -254,12 +142,12 @@ files:
$module_utils/memset.py: $module_utils/memset.py:
maintainers: glitchcrab maintainers: glitchcrab
labels: cloud memset labels: cloud memset
$module_utils/mh/:
maintainers: russoz
labels: module_helper
$module_utils/module_helper.py: $module_utils/module_helper.py:
maintainers: russoz maintainers: russoz
labels: module_helper labels: module_helper
$module_utils/net_tools/nios/api.py:
maintainers: $team_networking sganesh-infoblox
labels: infoblox networking
$module_utils/oracle/oci_utils.py: $module_utils/oracle/oci_utils.py:
maintainers: $team_oracle maintainers: $team_oracle
labels: cloud labels: cloud
@@ -269,13 +157,11 @@ files:
$module_utils/redfish_utils.py: $module_utils/redfish_utils.py:
maintainers: $team_redfish maintainers: $team_redfish
labels: redfish_utils labels: redfish_utils
$module_utils/remote_management/lxca/common.py: $module_utils/remote_management/lxca/common.py: navalkp prabhosa
maintainers: navalkp prabhosa
$module_utils/scaleway.py: $module_utils/scaleway.py:
maintainers: $team_scaleway maintainers: $team_scaleway
labels: cloud scaleway labels: cloud scaleway
$module_utils/storage/hpe3par/hpe3par.py: $module_utils/storage/hpe3par/hpe3par.py: farhan7500 gautamphegde
maintainers: farhan7500 gautamphegde
$module_utils/utm_utils.py: $module_utils/utm_utils.py:
maintainers: $team_e_spirit maintainers: $team_e_spirit
labels: utm_utils labels: utm_utils
@@ -306,31 +192,33 @@ files:
maintainers: zbal maintainers: zbal
$modules/cloud/lxc/lxc_container.py: $modules/cloud/lxc/lxc_container.py:
maintainers: cloudnull maintainers: cloudnull
$modules/cloud/lxc/lxc_profile.py:
maintainers: conloos
$modules/cloud/lxd/: $modules/cloud/lxd/:
ignore: hnakamur ignore: hnakamur
$modules/cloud/lxd/lxd_profile.py:
maintainers: conloos
$modules/cloud/memset/: $modules/cloud/memset/:
maintainers: glitchcrab maintainers: glitchcrab
$modules/cloud/misc/cloud_init_data_facts.py: $modules/cloud/misc/cloud_init_data_facts.py:
maintainers: resmo maintainers: resmo
$modules/cloud/misc/proxmox: $modules/cloud/misc/proxmox.py:
maintainers: $team_virt UnderGreen
labels: proxmox virt
ignore: skvidal
keywords: kvm libvirt proxmox qemu
$modules/cloud/misc/proxmox_kvm.py:
maintainers: $team_virt helldorado
labels: proxmox_kvm virt
ignore: skvidal
keywords: kvm libvirt proxmox qemu
$modules/cloud/misc/proxmox_snap.py:
maintainers: $team_virt maintainers: $team_virt
labels: proxmox virt labels: proxmox virt
keywords: kvm libvirt proxmox qemu keywords: kvm libvirt proxmox qemu
$modules/cloud/misc/proxmox.py:
maintainers: UnderGreen
ignore: skvidal
$modules/cloud/misc/proxmox_kvm.py:
maintainers: helldorado
ignore: skvidal
$modules/cloud/misc/proxmox_nic.py:
maintainers: Kogelvis
$modules/cloud/misc/proxmox_tasks_info:
maintainers: paginabianca
$modules/cloud/misc/proxmox_template.py: $modules/cloud/misc/proxmox_template.py:
maintainers: UnderGreen maintainers: $team_virt UnderGreen
labels: proxmox_template virt
ignore: skvidal ignore: skvidal
keywords: kvm libvirt proxmox qemu
$modules/cloud/misc/rhevm.py: $modules/cloud/misc/rhevm.py:
maintainers: $team_virt TimothyVandenbrande maintainers: $team_virt TimothyVandenbrande
labels: rhevm virt labels: rhevm virt
@@ -347,7 +235,7 @@ files:
$modules/cloud/oneandone/: $modules/cloud/oneandone/:
maintainers: aajdinov edevenport maintainers: aajdinov edevenport
$modules/cloud/online/: $modules/cloud/online/:
maintainers: remyleone maintainers: sieben
$modules/cloud/opennebula/: $modules/cloud/opennebula/:
maintainers: $team_opennebula maintainers: $team_opennebula
$modules/cloud/opennebula/one_host.py: $modules/cloud/opennebula/one_host.py:
@@ -372,40 +260,16 @@ files:
maintainers: omgjlk sivel maintainers: omgjlk sivel
$modules/cloud/rackspace/: $modules/cloud/rackspace/:
ignore: ryansb sivel ignore: ryansb sivel
$modules/cloud/rackspace/rax_cbs.py:
maintainers: claco
$modules/cloud/rackspace/rax_cbs_attachments.py:
maintainers: claco
$modules/cloud/rackspace/rax_cdb.py:
maintainers: jails
$modules/cloud/rackspace/rax_cdb_user.py:
maintainers: jails
$modules/cloud/rackspace/rax_cdb_database.py:
maintainers: jails
$modules/cloud/rackspace/rax_clb.py: $modules/cloud/rackspace/rax_clb.py:
maintainers: claco maintainers: claco
$modules/cloud/rackspace/rax_clb_nodes.py: $modules/cloud/rackspace/rax_clb_nodes.py:
maintainers: neuroid maintainers: neuroid
$modules/cloud/rackspace/rax_clb_ssl.py: $modules/cloud/rackspace/rax_clb_ssl.py:
maintainers: smashwilson maintainers: smashwilson
$modules/cloud/rackspace/rax_files.py:
maintainers: angstwad
$modules/cloud/rackspace/rax_files_objects.py:
maintainers: angstwad
$modules/cloud/rackspace/rax_identity.py: $modules/cloud/rackspace/rax_identity.py:
maintainers: claco maintainers: claco
$modules/cloud/rackspace/rax_network.py: $modules/cloud/rackspace/rax_network.py:
maintainers: claco omgjlk maintainers: claco omgjlk
$modules/cloud/rackspace/rax_mon_alarm.py:
maintainers: smashwilson
$modules/cloud/rackspace/rax_mon_check.py:
maintainers: smashwilson
$modules/cloud/rackspace/rax_mon_entity.py:
maintainers: smashwilson
$modules/cloud/rackspace/rax_mon_notification.py:
maintainers: smashwilson
$modules/cloud/rackspace/rax_mon_notification_plan.py:
maintainers: smashwilson
$modules/cloud/rackspace/rax_queue.py: $modules/cloud/rackspace/rax_queue.py:
maintainers: claco maintainers: claco
$modules/cloud/scaleway/: $modules/cloud/scaleway/:
@@ -417,19 +281,13 @@ files:
$modules/cloud/scaleway/scaleway_ip_info.py: $modules/cloud/scaleway/scaleway_ip_info.py:
maintainers: Spredzy maintainers: Spredzy
$modules/cloud/scaleway/scaleway_organization_info.py: $modules/cloud/scaleway/scaleway_organization_info.py:
maintainers: Spredzy maintainers: sieben
$modules/cloud/scaleway/scaleway_private_network.py:
maintainers: pastral
$modules/cloud/scaleway/scaleway_security_group.py: $modules/cloud/scaleway/scaleway_security_group.py:
maintainers: DenBeke maintainers: DenBeke
$modules/cloud/scaleway/scaleway_security_group_info.py: $modules/cloud/scaleway/scaleway_security_group_info.py:
maintainers: Spredzy maintainers: sieben
$modules/cloud/scaleway/scaleway_security_group_rule.py: $modules/cloud/scaleway/scaleway_security_group_rule.py:
maintainers: DenBeke maintainers: DenBeke
$modules/cloud/scaleway/scaleway_server_info.py:
maintainers: Spredzy
$modules/cloud/scaleway/scaleway_snapshot_info.py:
maintainers: Spredzy
$modules/cloud/scaleway/scaleway_volume.py: $modules/cloud/scaleway/scaleway_volume.py:
labels: scaleway_volume labels: scaleway_volume
ignore: hekonsek ignore: hekonsek
@@ -481,24 +339,11 @@ files:
maintainers: john-westcott-iv maintainers: john-westcott-iv
$modules/database/misc/redis.py: $modules/database/misc/redis.py:
maintainers: slok maintainers: slok
$modules/database/misc/redis_info.py:
maintainers: levonet
$modules/database/misc/redis_data_info.py:
maintainers: paginabianca
$modules/database/misc/redis_data.py:
maintainers: paginabianca
$modules/database/misc/redis_data_incr.py:
maintainers: paginabianca
$modules/database/misc/riak.py: $modules/database/misc/riak.py:
maintainers: drewkerrigan jsmartin maintainers: drewkerrigan jsmartin
$modules/database/mssql/mssql_db.py: $modules/database/mssql/mssql_db.py:
maintainers: vedit Jmainguy kenichi-ogawa-1988 maintainers: vedit Jmainguy kenichi-ogawa-1988
labels: mssql_db labels: mssql_db
$modules/database/mssql/mssql_script.py:
maintainers: kbudde
labels: mssql_script
$modules/database/saphana/hana_query.py:
maintainers: rainerleber
$modules/database/vertica/: $modules/database/vertica/:
maintainers: dareko maintainers: dareko
$modules/files/archive.py: $modules/files/archive.py:
@@ -507,14 +352,10 @@ files:
maintainers: quidame maintainers: quidame
$modules/files/ini_file.py: $modules/files/ini_file.py:
maintainers: jpmens noseka1 maintainers: jpmens noseka1
$modules/files/iso_create.py:
maintainers: Tomorrow9
$modules/files/iso_extract.py: $modules/files/iso_extract.py:
maintainers: dagwieers jhoekx ribbons maintainers: dagwieers jhoekx ribbons
$modules/files/read_csv.py: $modules/files/read_csv.py:
maintainers: dagwieers maintainers: dagwieers
$modules/files/sapcar_extract.py:
maintainers: RainerLeber
$modules/files/xattr.py: $modules/files/xattr.py:
maintainers: bcoca maintainers: bcoca
labels: xattr labels: xattr
@@ -532,30 +373,15 @@ files:
maintainers: jparrill maintainers: jparrill
$modules/identity/keycloak/: $modules/identity/keycloak/:
maintainers: $team_keycloak maintainers: $team_keycloak
$modules/identity/keycloak/keycloak_authentication.py:
maintainers: elfelip Gaetan2907
$modules/identity/keycloak/keycloak_clientscope.py:
maintainers: Gaetan2907
$modules/identity/keycloak/keycloak_client_rolemapping.py:
maintainers: Gaetan2907
$modules/identity/keycloak/keycloak_group.py: $modules/identity/keycloak/keycloak_group.py:
maintainers: adamgoossens maintainers: adamgoossens
$modules/identity/keycloak/keycloak_identity_provider.py:
maintainers: laurpaum
$modules/identity/keycloak/keycloak_realm_info.py:
maintainers: fynncfchen
$modules/identity/keycloak/keycloak_realm.py: $modules/identity/keycloak/keycloak_realm.py:
maintainers: kris2kris maintainers: kris2kris
$modules/identity/keycloak/keycloak_role.py:
maintainers: laurpaum
$modules/identity/keycloak/keycloak_user_federation.py:
maintainers: laurpaum
$modules/identity/onepassword_info.py: $modules/identity/onepassword_info.py:
maintainers: Rylon maintainers: Rylon
$modules/identity/opendj/opendj_backendprop.py: $modules/identity/opendj/opendj_backendprop.py:
maintainers: dj-wasabi maintainers: dj-wasabi
$modules/monitoring/airbrake_deployment.py: $modules/monitoring/airbrake_deployment.py:
maintainers: phumpal
labels: airbrake_deployment labels: airbrake_deployment
ignore: bpennypacker ignore: bpennypacker
$modules/monitoring/bigpanda.py: $modules/monitoring/bigpanda.py:
@@ -566,8 +392,6 @@ files:
maintainers: n0ts maintainers: n0ts
labels: datadog_event labels: datadog_event
ignore: arturaz ignore: arturaz
$modules/monitoring/datadog/datadog_downtime.py:
maintainers: Datadog
$modules/monitoring/datadog/datadog_monitor.py: $modules/monitoring/datadog/datadog_monitor.py:
maintainers: skornehl maintainers: skornehl
$modules/monitoring/honeybadger_deployment.py: $modules/monitoring/honeybadger_deployment.py:
@@ -629,14 +453,12 @@ files:
labels: cloudflare_dns labels: cloudflare_dns
$modules/net_tools/dnsimple.py: $modules/net_tools/dnsimple.py:
maintainers: drcapulet maintainers: drcapulet
$modules/net_tools/dnsimple_info.py:
maintainers: edhilgendorf
$modules/net_tools/dnsmadeeasy.py: $modules/net_tools/dnsmadeeasy.py:
maintainers: briceburg maintainers: briceburg
$modules/net_tools/gandi_livedns.py:
maintainers: gthiemonge
$modules/net_tools/haproxy.py: $modules/net_tools/haproxy.py:
maintainers: ravibhure Normo maintainers: ravibhure Normo
$modules/net_tools/:
maintainers: nerzhul
$modules/net_tools/infinity/infinity.py: $modules/net_tools/infinity/infinity.py:
maintainers: MeganLiu maintainers: MeganLiu
$modules/net_tools/ip_netns.py: $modules/net_tools/ip_netns.py:
@@ -660,26 +482,37 @@ files:
ignore: andyhky ignore: andyhky
$modules/net_tools/netcup_dns.py: $modules/net_tools/netcup_dns.py:
maintainers: nbuchwitz maintainers: nbuchwitz
$modules/net_tools/nsupdate.py:
maintainers: nerzhul
$modules/net_tools/omapi_host.py: $modules/net_tools/omapi_host.py:
maintainers: amasolov nerzhul maintainers: amasolov
$modules/net_tools/pritunl/: $modules/net_tools/nios/:
maintainers: Lowess maintainers: $team_networking
labels: infoblox networking
$modules/net_tools/nios/nios_fixed_address.py:
maintainers: sjaiswal
$modules/net_tools/nios/nios_nsgroup.py:
maintainers: ebirn sjaiswal
$modules/net_tools/nios/nios_ptr_record.py:
maintainers: clementtrebuchet
$modules/net_tools/nios/nios_srv_record.py:
maintainers: brampling
$modules/net_tools/nios/nios_txt_record.py:
maintainers: coreywan
$modules/net_tools/nmcli.py: $modules/net_tools/nmcli.py:
maintainers: alcamie101 maintainers: alcamie101
$modules/net_tools/snmp_facts.py: $modules/net_tools/snmp_facts.py:
maintainers: ogenstad ujwalkomarla maintainers: ogenstad ujwalkomarla
$modules/notification/osx_say.py:
maintainers: ansible mpdehaan
labels: _osx_say
deprecated: true
$modules/notification/bearychat.py: $modules/notification/bearychat.py:
maintainers: tonyseek maintainers: tonyseek
$modules/notification/campfire.py: $modules/notification/campfire.py:
maintainers: fabulops maintainers: fabulops
$modules/notification/catapult.py: $modules/notification/catapult.py:
maintainers: Jmainguy maintainers: Jmainguy
$modules/notification/cisco_webex.py: $modules/notification/cisco_spark.py:
maintainers: drew-russell maintainers: drew-russell
$modules/notification/discord.py:
maintainers: cwollinger
$modules/notification/flowdock.py: $modules/notification/flowdock.py:
maintainers: mcodd maintainers: mcodd
$modules/notification/grove.py: $modules/notification/grove.py:
@@ -707,13 +540,13 @@ files:
$modules/notification/pushbullet.py: $modules/notification/pushbullet.py:
maintainers: willybarro maintainers: willybarro
$modules/notification/pushover.py: $modules/notification/pushover.py:
maintainers: weaselkeeper wopfel maintainers: weaselkeeper
$modules/notification/rocketchat.py: $modules/notification/rocketchat.py:
maintainers: Deepakkothandan maintainers: Deepakkothandan
labels: rocketchat labels: rocketchat
ignore: ramondelafuente ignore: ramondelafuente
$modules/notification/say.py: $modules/notification/say.py:
maintainers: $team_ansible_core mpdehaan maintainers: ansible mpdehaan
$modules/notification/sendgrid.py: $modules/notification/sendgrid.py:
maintainers: makaimc maintainers: makaimc
$modules/notification/slack.py: $modules/notification/slack.py:
@@ -721,19 +554,15 @@ files:
$modules/notification/syslogger.py: $modules/notification/syslogger.py:
maintainers: garbled1 maintainers: garbled1
$modules/notification/telegram.py: $modules/notification/telegram.py:
maintainers: tyouxa loms lomserman maintainers: tyouxa loms
$modules/notification/twilio.py: $modules/notification/twilio.py:
maintainers: makaimc maintainers: makaimc
$modules/notification/typetalk.py: $modules/notification/typetalk.py:
maintainers: tksmd maintainers: tksmd
$modules/packaging/language/ansible_galaxy_install.py:
maintainers: russoz
$modules/packaging/language/bower.py: $modules/packaging/language/bower.py:
maintainers: mwarkentin maintainers: mwarkentin
$modules/packaging/language/bundler.py: $modules/packaging/language/bundler.py:
maintainers: thoiberg maintainers: thoiberg
$modules/packaging/language/cargo.py:
maintainers: radek-sprta
$modules/packaging/language/composer.py: $modules/packaging/language/composer.py:
maintainers: dmtrs maintainers: dmtrs
ignore: resmo ignore: resmo
@@ -742,7 +571,7 @@ files:
$modules/packaging/language/easy_install.py: $modules/packaging/language/easy_install.py:
maintainers: mattupstate maintainers: mattupstate
$modules/packaging/language/gem.py: $modules/packaging/language/gem.py:
maintainers: $team_ansible_core johanwiren maintainers: ansible johanwiren
labels: gem labels: gem
$modules/packaging/language/maven_artifact.py: $modules/packaging/language/maven_artifact.py:
maintainers: tumbl3w33d turb maintainers: tumbl3w33d turb
@@ -757,22 +586,16 @@ files:
ignore: jle64 ignore: jle64
$modules/packaging/language/pip_package_info.py: $modules/packaging/language/pip_package_info.py:
maintainers: bcoca matburt maxamillion maintainers: bcoca matburt maxamillion
$modules/packaging/language/pipx.py:
maintainers: russoz
$modules/packaging/language/yarn.py: $modules/packaging/language/yarn.py:
maintainers: chrishoffman verkaufer maintainers: chrishoffman verkaufer
$modules/packaging/os/apk.py: $modules/packaging/os/apk.py:
maintainers: tdtrask maintainers: tdtrask
labels: apk labels: apk
ignore: kbrebanov ignore: kbrebanov
$modules/packaging/os/apt_repo.py:
maintainers: obirvalger
$modules/packaging/os/apt_rpm.py: $modules/packaging/os/apt_rpm.py:
maintainers: evgkrsk maintainers: evgkrsk
$modules/packaging/os/copr.py: $modules/packaging/os/copr.py:
maintainers: schlupov maintainers: schlupov
$modules/packaging/os/dnf_versionlock.py:
maintainers: moreda
$modules/packaging/os/flatpak.py: $modules/packaging/os/flatpak.py:
maintainers: $team_flatpak maintainers: $team_flatpak
$modules/packaging/os/flatpak_remote.py: $modules/packaging/os/flatpak_remote.py:
@@ -821,12 +644,9 @@ files:
$modules/packaging/os/opkg.py: $modules/packaging/os/opkg.py:
maintainers: skinp maintainers: skinp
$modules/packaging/os/pacman.py: $modules/packaging/os/pacman.py:
maintainers: elasticdog indrajitr tchernomax jraby maintainers: elasticdog indrajitr tchernomax
labels: pacman labels: pacman
ignore: elasticdog ignore: elasticdog
$modules/packaging/os/pacman_key.py:
maintainers: grawlinson
labels: pacman
$modules/packaging/os/pkgin.py: $modules/packaging/os/pkgin.py:
maintainers: $team_solaris L2G jasperla szinck martinm82 maintainers: $team_solaris L2G jasperla szinck martinm82
labels: pkgin solaris labels: pkgin solaris
@@ -869,9 +689,6 @@ files:
$modules/packaging/os/snap.py: $modules/packaging/os/snap.py:
maintainers: angristan vcarceler maintainers: angristan vcarceler
labels: snap labels: snap
$modules/packaging/os/snap_alias.py:
maintainers: russoz
labels: snap
$modules/packaging/os/sorcery.py: $modules/packaging/os/sorcery.py:
maintainers: vaygr maintainers: vaygr
$modules/packaging/os/svr4pkg.py: $modules/packaging/os/svr4pkg.py:
@@ -895,9 +712,8 @@ files:
labels: zypper labels: zypper
ignore: dirtyharrycallahan robinro ignore: dirtyharrycallahan robinro
$modules/packaging/os/zypper_repository.py: $modules/packaging/os/zypper_repository.py:
maintainers: $team_suse maintainers: $team_suse matze
labels: zypper labels: zypper
ignore: matze
$modules/remote_management/cobbler/: $modules/remote_management/cobbler/:
maintainers: dagwieers maintainers: dagwieers
$modules/remote_management/hpilo/: $modules/remote_management/hpilo/:
@@ -915,10 +731,6 @@ files:
$modules/remote_management/manageiq/: $modules/remote_management/manageiq/:
labels: manageiq labels: manageiq
maintainers: $team_manageiq maintainers: $team_manageiq
$modules/remote_management/manageiq/manageiq_alert_profiles.py:
maintainers: elad661
$modules/remote_management/manageiq/manageiq_alerts.py:
maintainers: elad661
$modules/remote_management/manageiq/manageiq_group.py: $modules/remote_management/manageiq/manageiq_group.py:
maintainers: evertmulder maintainers: evertmulder
$modules/remote_management/manageiq/manageiq_tenant.py: $modules/remote_management/manageiq/manageiq_tenant.py:
@@ -967,10 +779,6 @@ files:
maintainers: markuman maintainers: markuman
$modules/source_control/gitlab/gitlab_runner.py: $modules/source_control/gitlab/gitlab_runner.py:
maintainers: SamyCoenen maintainers: SamyCoenen
$modules/source_control/gitlab/gitlab_user.py:
maintainers: LennertMertens stgrace
$modules/source_control/gitlab/gitlab_branch.py:
maintainers: paytroff
$modules/source_control/hg.py: $modules/source_control/hg.py:
maintainers: yeukhon maintainers: yeukhon
$modules/storage/emc/emc_vnx_sg_member.py: $modules/storage/emc/emc_vnx_sg_member.py:
@@ -979,8 +787,13 @@ files:
maintainers: farhan7500 gautamphegde maintainers: farhan7500 gautamphegde
$modules/storage/ibm/: $modules/storage/ibm/:
maintainers: tzure maintainers: tzure
$modules/storage/pmem/pmem.py: $modules/storage/infinidat/:
maintainers: mizumm maintainers: vmalloc GR360RY
$modules/storage/netapp/:
maintainers: $team_netapp
$modules/storage/purestorage/:
maintainers: $team_purestorage
labels: pure_storage
$modules/storage/vexata/: $modules/storage/vexata/:
maintainers: vexata maintainers: vexata
$modules/storage/zfs/: $modules/storage/zfs/:
@@ -999,8 +812,6 @@ files:
maintainers: mulby maintainers: mulby
labels: alternatives labels: alternatives
ignore: DavidWittman ignore: DavidWittman
$modules/system/aix_lvol.py:
maintainers: adejoux
$modules/system/awall.py: $modules/system/awall.py:
maintainers: tdtrask maintainers: tdtrask
$modules/system/beadm.py: $modules/system/beadm.py:
@@ -1018,7 +829,7 @@ files:
$modules/system/dpkg_divert.py: $modules/system/dpkg_divert.py:
maintainers: quidame maintainers: quidame
$modules/system/facter.py: $modules/system/facter.py:
maintainers: $team_ansible_core gamethis maintainers: ansible gamethis
labels: facter labels: facter
$modules/system/filesystem.py: $modules/system/filesystem.py:
maintainers: pilou- abulimov quidame maintainers: pilou- abulimov quidame
@@ -1026,19 +837,15 @@ files:
$modules/system/gconftool2.py: $modules/system/gconftool2.py:
maintainers: Akasurde kevensen maintainers: Akasurde kevensen
labels: gconftool2 labels: gconftool2
$modules/system/homectl.py:
maintainers: jameslivulpi
$modules/system/interfaces_file.py: $modules/system/interfaces_file.py:
maintainers: obourdon hryamzik maintainers: obourdon hryamzik
labels: interfaces_file labels: interfaces_file
$modules/system/iptables_state.py: $modules/system/iptables_state.py:
maintainers: quidame maintainers: quidame
$modules/system/shutdown.py:
maintainers: nitzmahone samdoran aminvakil
$modules/system/java_cert.py: $modules/system/java_cert.py:
maintainers: haad absynth76 maintainers: haad absynth76
$modules/system/java_keystore.py: $modules/system/java_keystore.py:
maintainers: Mogztter quidame maintainers: Mogztter
$modules/system/kernel_blacklist.py: $modules/system/kernel_blacklist.py:
maintainers: matze maintainers: matze
$modules/system/launchd.py: $modules/system/launchd.py:
@@ -1052,7 +859,7 @@ files:
$modules/system/lvg.py: $modules/system/lvg.py:
maintainers: abulimov maintainers: abulimov
$modules/system/lvol.py: $modules/system/lvol.py:
maintainers: abulimov jhoekx zigaSRC unkaputtbar112 maintainers: abulimov jhoekx
$modules/system/make.py: $modules/system/make.py:
maintainers: LinusU maintainers: LinusU
$modules/system/mksysb.py: $modules/system/mksysb.py:
@@ -1065,7 +872,7 @@ files:
$modules/system/nosh.py: $modules/system/nosh.py:
maintainers: tacatac maintainers: tacatac
$modules/system/ohai.py: $modules/system/ohai.py:
maintainers: $team_ansible_core mpdehaan maintainers: ansible mpdehaan
labels: ohai labels: ohai
$modules/system/open_iscsi.py: $modules/system/open_iscsi.py:
maintainers: srvg maintainers: srvg
@@ -1094,8 +901,6 @@ files:
ignore: ryansb ignore: ryansb
$modules/system/runit.py: $modules/system/runit.py:
maintainers: jsumners maintainers: jsumners
$modules/system/sap_task_list_execute:
maintainers: rainerleber
$modules/system/sefcontext.py: $modules/system/sefcontext.py:
maintainers: dagwieers maintainers: dagwieers
$modules/system/selinux_permissive.py: $modules/system/selinux_permissive.py:
@@ -1108,10 +913,6 @@ files:
maintainers: $team_solaris pmarkham maintainers: $team_solaris pmarkham
labels: solaris labels: solaris
keywords: beadm dladm illumos ipadm nexenta omnios openindiana pfexec smartos solaris sunos zfs zpool keywords: beadm dladm illumos ipadm nexenta omnios openindiana pfexec smartos solaris sunos zfs zpool
$modules/system/ssh_config.py:
maintainers: gaqzi Akasurde
$modules/system/sudoers.py:
maintainers: JonEllis
$modules/system/svc.py: $modules/system/svc.py:
maintainers: bcoca maintainers: bcoca
$modules/system/syspatch.py: $modules/system/syspatch.py:
@@ -1127,38 +928,31 @@ files:
maintainers: ahtik ovcharenko pyykkis maintainers: ahtik ovcharenko pyykkis
labels: ufw labels: ufw
$modules/system/vdo.py: $modules/system/vdo.py:
maintainers: rhawalsh bgurney-rh maintainers: rhawalsh
$modules/system/xfconf.py: $modules/system/xfconf.py:
maintainers: russoz jbenden maintainers: russoz jbenden
labels: xfconf labels: xfconf
$modules/system/xfconf_info.py:
maintainers: russoz
labels: xfconf
$modules/system/xfs_quota.py: $modules/system/xfs_quota.py:
maintainers: bushvin maintainers: bushvin
$modules/web_infrastructure/apache2_mod_proxy.py: $modules/web_infrastructure/apache2_mod_proxy.py:
maintainers: oboukili maintainers: oboukili
$modules/web_infrastructure/apache2_module.py: $modules/web_infrastructure/apache2_module.py:
maintainers: berendt n0trax maintainers: berendt n0trax robinro
ignore: robinro
$modules/web_infrastructure/deploy_helper.py: $modules/web_infrastructure/deploy_helper.py:
maintainers: ramondelafuente maintainers: ramondelafuente
$modules/web_infrastructure/django_manage.py: $modules/web_infrastructure/django_manage.py:
maintainers: russoz maintainers: scottanderson42 russoz tastychutney
ignore: scottanderson42 tastychutney
labels: django_manage labels: django_manage
$modules/web_infrastructure/ejabberd_user.py: $modules/web_infrastructure/ejabberd_user.py:
maintainers: privateip maintainers: privateip
$modules/web_infrastructure/gunicorn.py: $modules/web_infrastructure/gunicorn.py:
maintainers: agmezr maintainers: agmezr
$modules/web_infrastructure/htpasswd.py: $modules/web_infrastructure/htpasswd.py:
maintainers: $team_ansible_core maintainers: ansible
labels: htpasswd labels: htpasswd
$modules/web_infrastructure/jboss.py: $modules/web_infrastructure/jboss.py:
maintainers: $team_jboss jhoekx maintainers: $team_jboss jhoekx
labels: jboss labels: jboss
$modules/web_infrastructure/jenkins_build.py:
maintainers: brettmilford unnecessary-username
$modules/web_infrastructure/jenkins_job.py: $modules/web_infrastructure/jenkins_job.py:
maintainers: sermilrod maintainers: sermilrod
$modules/web_infrastructure/jenkins_job_info.py: $modules/web_infrastructure/jenkins_job_info.py:
@@ -1168,19 +962,12 @@ files:
$modules/web_infrastructure/jenkins_script.py: $modules/web_infrastructure/jenkins_script.py:
maintainers: hogarthj maintainers: hogarthj
$modules/web_infrastructure/jira.py: $modules/web_infrastructure/jira.py:
maintainers: Slezhuk tarka pertoft maintainers: Slezhuk tarka
ignore: DWSR
labels: jira labels: jira
$modules/web_infrastructure/nginx_status_info.py: $modules/web_infrastructure/nginx_status_info.py:
maintainers: resmo maintainers: resmo
$modules/web_infrastructure/rundeck_acl_policy.py: $modules/web_infrastructure/:
maintainers: nerzhul maintainers: nerzhul
$modules/web_infrastructure/rundeck_project.py:
maintainers: nerzhul
$modules/web_infrastructure/rundeck_job_run.py:
maintainers: phsmith
$modules/web_infrastructure/rundeck_job_executions_info.py:
maintainers: phsmith
$modules/web_infrastructure/sophos_utm/: $modules/web_infrastructure/sophos_utm/:
maintainers: $team_e_spirit maintainers: $team_e_spirit
keywords: sophos utm keywords: sophos utm
@@ -1190,20 +977,10 @@ files:
$modules/web_infrastructure/sophos_utm/utm_proxy_exception.py: $modules/web_infrastructure/sophos_utm/utm_proxy_exception.py:
maintainers: $team_e_spirit RickS-C137 maintainers: $team_e_spirit RickS-C137
keywords: sophos utm keywords: sophos utm
$modules/web_infrastructure/sophos_utm/utm_ca_host_key_cert.py:
maintainers: stearz
$modules/web_infrastructure/sophos_utm/utm_ca_host_key_cert_info.py:
maintainers: stearz
$modules/web_infrastructure/sophos_utm/utm_network_interface_address.py:
maintainers: steamx
$modules/web_infrastructure/sophos_utm/utm_network_interface_address_info.py:
maintainers: steamx
$modules/web_infrastructure/supervisorctl.py: $modules/web_infrastructure/supervisorctl.py:
maintainers: inetfuture mattupstate maintainers: inetfuture mattupstate
$modules/web_infrastructure/taiga_issue.py: $modules/web_infrastructure/taiga_issue.py:
maintainers: lekum maintainers: lekum
$tests/a_module.py:
maintainers: felixfontein
######################### #########################
tests/: tests/:
labels: tests labels: tests
@@ -1219,26 +996,24 @@ files:
macros: macros:
actions: plugins/action actions: plugins/action
becomes: plugins/become becomes: plugins/become
caches: plugins/cache
callbacks: plugins/callback callbacks: plugins/callback
cliconfs: plugins/cliconf cliconfs: plugins/cliconf
connections: plugins/connection connections: plugins/connection
doc_fragments: plugins/doc_fragments doc_fragments: plugins/doc_fragments
filters: plugins/filter filters: plugins/filter
httpapis: plugins/httpapi
inventories: plugins/inventory inventories: plugins/inventory
lookups: plugins/lookup lookups: plugins/lookup
module_utils: plugins/module_utils module_utils: plugins/module_utils
modules: plugins/modules modules: plugins/modules
terminals: plugins/terminal terminals: plugins/terminal
tests: plugins/test
team_ansible_core:
team_aix: MorrisA bcoca d-little flynn1973 gforster kairoaraujo marvin-sinister mator molekuul ramooncamacho wtcross 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_bsd: JoergFiedler MacLemon bcoca dch jasperla mekanix opoplawski overhacked tuxillo
team_consul: sgargan team_consul: sgargan
team_cyberark_conjur: jvanderhoof ryanprior team_cyberark_conjur: jvanderhoof ryanprior
team_e_spirit: MatrixCrawler getjack team_e_spirit: MatrixCrawler getjack
team_flatpak: JayKayy oolongbrothers team_flatpak: JayKayy oolongbrothers
team_gitlab: Lunik Shaps dj-wasabi marwatk waheedi zanssa scodeman metanovii sh0shin nejch lgatellier suukit team_gitlab: Lunik Shaps dj-wasabi marwatk waheedi zanssa scodeman metanovii
team_hpux: bcoca davx8342 team_hpux: bcoca davx8342
team_huawei: QijunPan TommyLike edisonxiang freesky-edward hwDCN niuzhenguo xuxiaowei0512 yanzhangi zengchen1024 zhongjun2 team_huawei: QijunPan TommyLike edisonxiang freesky-edward hwDCN niuzhenguo xuxiaowei0512 yanzhangi zengchen1024 zhongjun2
team_ipa: Akasurde Nosmoht fxfitz justchris1 team_ipa: Akasurde Nosmoht fxfitz justchris1
@@ -1247,13 +1022,14 @@ macros:
team_linode: InTheCloudDan decentral1se displague rmcintosh Charliekenney23 LBGarber team_linode: InTheCloudDan decentral1se displague rmcintosh Charliekenney23 LBGarber
team_macos: Akasurde kyleabenson martinm82 danieljaouen indrajitr team_macos: Akasurde kyleabenson martinm82 danieljaouen indrajitr
team_manageiq: abellotti cben gtanzillo yaacov zgalor dkorn evertmulder team_manageiq: abellotti cben gtanzillo yaacov zgalor dkorn evertmulder
team_netapp: amit0701 carchi8py hulquest lmprice lonico ndswartz schmots1
team_networking: NilashishC Qalthos danielmellado ganeshrn justjais trishnaguha sganesh-infoblox privateip team_networking: NilashishC Qalthos danielmellado ganeshrn justjais trishnaguha sganesh-infoblox privateip
team_opennebula: ilicmilan meerkampdvv rsmontero xorel nilsding team_opennebula: ilicmilan meerkampdvv rsmontero xorel nilsding
team_oracle: manojmeda mross22 nalsaber team_oracle: manojmeda mross22 nalsaber
team_purestorage: bannaych dnix101 genegr lionmax opslounge raekins sdodsley sile16 team_purestorage: bannaych dnix101 genegr lionmax opslounge raekins sdodsley sile16
team_redfish: mraineri tomasg2012 xmadsen renxulei rajeevkallur bhavya06 team_redfish: mraineri tomasg2012 xmadsen renxulei
team_rhn: FlossWare alikins barnabycourt vritant team_rhn: FlossWare alikins barnabycourt vritant
team_scaleway: remyleone abarbare team_scaleway: QuentinBrosse abarbare jerome-quere kindermoumoute remyleone sieben
team_solaris: bcoca fishman jasperla jpdasma mator scathatheworm troy2914 xen0l team_solaris: bcoca fishman jasperla jpdasma mator scathatheworm troy2914 xen0l
team_suse: commel dcermak evrardjp lrupp toabctl AnderEnder alxgu andytom sealor team_suse: commel dcermak evrardjp lrupp toabctl AnderEnder alxgu andytom sealor
team_virt: joshainglis karmab tleguern Thulium-Drake Ajpantuso team_virt: joshainglis karmab tleguern Thulium-Drake Ajpantuso

View File

@@ -62,20 +62,6 @@ body:
validations: validations:
required: true required: true
- type: textarea
attributes:
label: Community.general Version
description: >-
Paste verbatim output from "ansible-galaxy collection list community.general"
between tripple backticks.
value: |
```console (paste below)
$ ansible-galaxy collection list community.general
```
validations:
required: true
- type: textarea - type: textarea
attributes: attributes:
label: Configuration label: Configuration

View File

@@ -62,20 +62,6 @@ body:
validations: validations:
required: false required: false
- type: textarea
attributes:
label: Community.general Version
description: >-
Paste verbatim output from "ansible-galaxy collection list community.general"
between tripple backticks.
value: |
```console (paste below)
$ ansible-galaxy collection list community.general
```
validations:
required: true
- type: textarea - type: textarea
attributes: attributes:
label: Configuration label: Configuration

View File

@@ -21,7 +21,7 @@ body:
placeholder: >- placeholder: >-
I am trying to do X with the collection from the main branch on GitHub and I am trying to do X with the collection from the main branch on GitHub and
I think that implementing a feature Y would be very helpful for me and I think that implementing a feature Y would be very helpful for me and
every other user of community.general because of Z. every other user of ansible-core because of Z.
validations: validations:
required: true required: true

View File

@@ -1,6 +0,0 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
interval:
schedule: "weekly"

81
.gitignore vendored
View File

@@ -1,6 +1,6 @@
# Created by https://www.toptal.com/developers/gitignore/api/git,linux,pydev,python,windows,pycharm+all,jupyternotebook,vim,webstorm,emacs,dotenv # Created by https://www.gitignore.io/api/git,linux,pydev,python,windows,pycharm+all,jupyternotebook,vim,webstorm,emacs,dotenv
# Edit at https://www.toptal.com/developers/gitignore?templates=git,linux,pydev,python,windows,pycharm+all,jupyternotebook,vim,webstorm,emacs,dotenv # Edit at https://www.gitignore.io/?templates=git,linux,pydev,python,windows,pycharm+all,jupyternotebook,vim,webstorm,emacs,dotenv
### dotenv ### ### dotenv ###
.env .env
@@ -88,7 +88,7 @@ flycheck_*.el
.nfs* .nfs*
### PyCharm+all ### ### PyCharm+all ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff # User-specific stuff
@@ -98,9 +98,6 @@ flycheck_*.el
.idea/**/dictionaries .idea/**/dictionaries
.idea/**/shelf .idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files # Generated files
.idea/**/contentModel.xml .idea/**/contentModel.xml
@@ -121,9 +118,6 @@ flycheck_*.el
# When using Gradle or Maven with auto-import, you should exclude module files, # When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using # since they will be recreated, and may cause churn. Uncomment if using
# auto-import. # auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml # .idea/modules.xml
# .idea/*.iml # .idea/*.iml
# .idea/modules # .idea/modules
@@ -204,6 +198,7 @@ parts/
sdist/ sdist/
var/ var/
wheels/ wheels/
pip-wheel-metadata/
share/python-wheels/ share/python-wheels/
*.egg-info/ *.egg-info/
.installed.cfg .installed.cfg
@@ -230,25 +225,13 @@ htmlcov/
nosetests.xml nosetests.xml
coverage.xml coverage.xml
*.cover *.cover
*.py,cover
.hypothesis/ .hypothesis/
.pytest_cache/ .pytest_cache/
cover/
# Translations # Translations
*.mo *.mo
*.pot *.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff: # Scrapy stuff:
.scrapy .scrapy
@@ -256,19 +239,9 @@ instance/
docs/_build/ docs/_build/
# PyBuilder # PyBuilder
.pybuilder/
target/ target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv # pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
.python-version .python-version
# pipenv # pipenv
@@ -278,24 +251,12 @@ ipython_config.py
# install all needed dependencies. # install all needed dependencies.
#Pipfile.lock #Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow # celery beat schedule file
__pypackages__/
# Celery stuff
celerybeat-schedule celerybeat-schedule
celerybeat.pid
# SageMath parsed files # SageMath parsed files
*.sage.py *.sage.py
# Environments
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings # Spyder project settings
.spyderproject .spyderproject
.spyproject .spyproject
@@ -303,6 +264,10 @@ venv.bak/
# Rope project settings # Rope project settings
.ropeproject .ropeproject
# Mr Developer
.mr.developer.cfg
.project
# mkdocs documentation # mkdocs documentation
/site /site
@@ -314,16 +279,9 @@ dmypy.json
# Pyre type checker # Pyre type checker
.pyre/ .pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
### Vim ### ### Vim ###
# Swap # Swap
[._]*.s[a-v][a-z] [._]*.s[a-v][a-z]
!*.svg # comment out if you don't need vector files
[._]*.sw[a-p] [._]*.sw[a-p]
[._]s[a-rt-v][a-z] [._]s[a-rt-v][a-z]
[._]ss[a-gi-z] [._]ss[a-gi-z]
@@ -341,13 +299,11 @@ tags
[._]*.un~ [._]*.un~
### WebStorm ### ### WebStorm ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff # User-specific stuff
# AWS User-specific
# Generated files # Generated files
# Sensitive or high-churn files # Sensitive or high-churn files
@@ -358,9 +314,6 @@ tags
# When using Gradle or Maven with auto-import, you should exclude module files, # When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using # since they will be recreated, and may cause churn. Uncomment if using
# auto-import. # auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml # .idea/modules.xml
# .idea/*.iml # .idea/*.iml
# .idea/modules # .idea/modules
@@ -396,27 +349,15 @@ tags
# *.ipr # *.ipr
# Sonarlint plugin # Sonarlint plugin
# https://plugins.jetbrains.com/plugin/7973-sonarlint
.idea/**/sonarlint/ .idea/**/sonarlint/
# SonarQube Plugin # SonarQube Plugin
# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
.idea/**/sonarIssues.xml .idea/**/sonarIssues.xml
# Markdown Navigator plugin # Markdown Navigator plugin
# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
.idea/**/markdown-navigator.xml .idea/**/markdown-navigator.xml
.idea/**/markdown-navigator-enh.xml
.idea/**/markdown-navigator/ .idea/**/markdown-navigator/
# Cache file creation bug
# See https://youtrack.jetbrains.com/issue/JBR-2257
.idea/$CACHE_FILE$
# CodeStream plugin
# https://plugins.jetbrains.com/plugin/12206-codestream
.idea/codestream.xml
### Windows ### ### Windows ###
# Windows thumbnail cache files # Windows thumbnail cache files
Thumbs.db Thumbs.db
@@ -443,4 +384,4 @@ $RECYCLE.BIN/
# Windows shortcuts # Windows shortcuts
*.lnk *.lnk
# End of https://www.toptal.com/developers/gitignore/api/git,linux,pydev,python,windows,pycharm+all,jupyternotebook,vim,webstorm,emacs,dotenv # End of https://www.gitignore.io/api/git,linux,pydev,python,windows,pycharm+all,jupyternotebook,vim,webstorm,emacs,dotenv

File diff suppressed because it is too large Load Diff

View File

@@ -1,121 +0,0 @@
# Contributing
We follow [Ansible Code of Conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html) in all our contributions and interactions within this repository.
If you are a committer, also refer to the [collection's committer guidelines](https://github.com/ansible-collections/community.general/blob/main/commit-rights.md).
## Issue tracker
Whether you are looking for an opportunity to contribute or you found a bug and already know how to solve it, please go to the [issue tracker](https://github.com/ansible-collections/community.general/issues).
There you can find feature ideas to implement, reports about bugs to solve, or submit an issue to discuss your idea before implementing it which can help choose a right direction at the beginning of your work and potentially save a lot of time and effort.
Also somebody may already have started discussing or working on implementing the same or a similar idea,
so you can cooperate to create a better solution together.
* If you are interested in starting with an easy issue, look for [issues with an `easyfix` label](https://github.com/ansible-collections/community.general/labels/easyfix).
* Often issues that are waiting for contributors to pick up have [the `waiting_on_contributor` label](https://github.com/ansible-collections/community.general/labels/waiting_on_contributor).
## Open pull requests
Look through currently [open pull requests](https://github.com/ansible-collections/community.general/pulls).
You can help by reviewing them. Reviews help move pull requests to merge state. Some good pull requests cannot be merged only due to a lack of reviews. And it is always worth saying that good reviews are often more valuable than pull requests themselves.
Note that reviewing does not only mean code review, but also offering comments on new interfaces added to existing plugins/modules, interfaces of new plugins/modules, improving language (not everyone is a native english speaker), or testing bugfixes and new features!
Also, consider taking up a valuable, reviewed, but abandoned pull request which you could politely ask the original authors to complete yourself.
* Try committing your changes with an informative but short commit message.
* Do not squash your commits and force-push to your branch if not needed. Reviews of your pull request are much easier with individual commits to comprehend the pull request history. All commits of your pull request branch will be squashed into one commit by GitHub upon merge.
* Do not add merge commits to your PR. The bot will complain and you will have to rebase ([instructions for rebasing](https://docs.ansible.com/ansible/latest/dev_guide/developing_rebasing.html)) to remove them before your PR can be merged. To avoid that git automatically does merges during pulls, you can configure it to do rebases instead by running `git config pull.rebase true` inside the repository checkout.
* Make sure your PR includes a [changelog fragment](https://docs.ansible.com/ansible/devel/community/development_process.html#changelogs-how-to). (You must not include a fragment for new modules or new plugins, except for test and filter plugins. Also you shouldn't include one for docs-only changes. If you're not sure, simply don't include one, we'll tell you whether one is needed or not :) )
* Avoid reformatting unrelated parts of the codebase in your PR. These types of changes will likely be requested for reversion, create additional work for reviewers, and may cause approval to be delayed.
You can also read [our Quick-start development guide](https://github.com/ansible/community-docs/blob/main/create_pr_quick_start_guide.rst).
## Test pull requests
If you want to test a PR locally, refer to [our testing guide](https://github.com/ansible/community-docs/blob/main/test_pr_locally_guide.rst) for instructions on how do it quickly.
If you find any inconsistencies or places in this document which can be improved, feel free to raise an issue or pull request to fix it.
## Run sanity, unit or integration tests locally
You have to check out the repository into a specific path structure to be able to run `ansible-test`. The path to the git checkout must end with `.../ansible_collections/community/general`. Please see [our testing guide](https://github.com/ansible/community-docs/blob/main/test_pr_locally_guide.rst) for instructions on how to check out the repository into a correct path structure. The short version of these instructions is:
```.bash
mkdir -p ~/dev/ansible_collections/community
git clone https://github.com/ansible-collections/community.general.git ~/dev/ansible_collections/community/general
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+.
The following commands show how to run sanity tests:
```.bash
# Run sanity tests for all files in the collection:
ansible-test sanity --docker -v
# Run sanity tests for the given files and directories:
ansible-test sanity --docker -v plugins/modules/system/pids.py tests/integration/targets/pids/
```
The following commands show how to run unit tests:
```.bash
# Run all unit tests:
ansible-test units --docker -v
# Run all unit tests for one Python version (a lot faster):
ansible-test units --docker -v --python 3.8
# Run a specific unit test (for the nmcli module) for one Python version:
ansible-test units --docker -v --python 3.8 tests/unit/plugins/modules/net_tools/test_nmcli.py
```
The following commands show how to run integration tests:
```.bash
# 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
# Run integration tests for the flattened lookup **without any isolation**:
ansible-test integration -v lookup_flattened
```
If you are unsure about the integration test target name for a module or plugin, you can take a look in `tests/integration/targets/`. Tests for plugins have the plugin type prepended.
## Creating new modules or plugins
Creating new modules and plugins requires a bit more work than other Pull Requests.
1. Please make sure that your new module or plugin is of interest to a larger audience. Very specialized modules or plugins that
can only be used by very few people should better be added to more specialized collections.
2. Please do not add more than one plugin/module in one PR, especially if it is the first plugin/module you are contributing.
That makes it easier for reviewers, and increases the chance that your PR will get merged. If you plan to contribute a group
of plugins/modules (say, more than a module and a corresponding ``_info`` module), please mention that in the first PR. In
such cases, you also have to think whether it is better to publish the group of plugins/modules in a new collection.
3. When creating a new module or plugin, please make sure that you follow various guidelines:
- Follow [development conventions](https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_best_practices.html);
- Follow [documentation standards](https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_documenting.html) and
the [Ansible style guide](https://docs.ansible.com/ansible/devel/dev_guide/style_guide/index.html#style-guide);
- Make sure your modules and plugins are [GPL-3.0-or-later](https://www.gnu.org/licenses/gpl-3.0-standalone.html) licensed
(new module_utils can also be [BSD-2-clause](https://opensource.org/licenses/BSD-2-Clause) licensed);
- Make sure that new plugins and modules have tests (unit tests, integration tests, or both); it is preferable to have some tests
which run in CI.
4. For modules and action plugins, make sure to create your module/plugin in the correct subdirectory, and create a symbolic link
from `plugins/modules/` respectively `plugins/action/` to the actual module/plugin code. (Other plugin types should not use
subdirectories.)
- Action plugins need to be accompanied by a module, even if the module file only contains documentation
(`DOCUMENTATION`, `EXAMPLES` and `RETURN`). The module must have the same name and directory path in `plugins/modules/`
than the action plugin has in `plugins/action/`.
5. Make sure to add a BOTMETA entry for your new module/plugin in `.github/BOTMETA.yml`. Search for other plugins/modules in the
same directory to see how entries could look. You should list all authors either as `maintainers` or under `ignore`. People
listed as `maintainers` will be pinged for new issues and PRs that modify the module/plugin or its tests.
When you add a new plugin/module, we expect that you perform maintainer duty for at least some time after contributing it.

View File

@@ -1,23 +1,17 @@
# Community General Collection # Community General Collection
[![Build Status](https://dev.azure.com/ansible/community.general/_apis/build/status/CI?branchName=stable-4)](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-3)](https://dev.azure.com/ansible/community.general/_build?definitionId=31)
[![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/community.general)](https://codecov.io/gh/ansible-collections/community.general) [![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/community.general)](https://codecov.io/gh/ansible-collections/community.general)
This repository contains the `community.general` Ansible Collection. The collection is a part of the Ansible package and includes many modules and plugins supported by Ansible community which are not part of more specialized community collections. This repo contains the `community.general` Ansible Collection. The collection includes many modules and plugins supported by Ansible community which are not part of more specialized community collections.
You can find [documentation for this collection on the Ansible docs site](https://docs.ansible.com/ansible/latest/collections/community/general/). You can find [documentation for this collection on the Ansible docs site](https://docs.ansible.com/ansible/latest/collections/community/general/).
Please note that this collection does **not** support Windows targets. Only connection plugins included in this collection might support Windows targets, and will explicitly mention that in their documentation if they do so. Please note that this collection does **not** support Windows targets. Only connection plugins included in this collection might support Windows targets, and will explicitly mention that in their documentation if they do so.
## Code of Conduct
We follow [Ansible Code of Conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html) in all our interactions within this project.
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.
## Tested with Ansible ## Tested with Ansible
Tested with the current Ansible 2.9, ansible-base 2.10, ansible-core 2.11, ansible-core 2.12, ansible-core 2.13 releases and the current development version of ansible-core. Ansible versions before 2.9.10 are not supported. Tested with the current Ansible 2.9, ansible-base 2.10 and ansible-core 2.11 releases and the current development version of ansible-core. Ansible versions before 2.9.10 are not supported.
## External requirements ## External requirements
@@ -29,9 +23,7 @@ Please check the included content on the [Ansible Galaxy page for this collectio
## Using this collection ## Using this collection
This collection is shipped with the Ansible package. So if you have it installed, no more action is required. Before using the General community collection, you need to install the collection with the `ansible-galaxy` CLI:
If you have a minimal installation (only Ansible Core installed) or you want to use the latest version of the collection along with the whole Ansible package, you need to install the collection from [Ansible Galaxy](https://galaxy.ansible.com/community/general) manually with the `ansible-galaxy` command-line tool:
ansible-galaxy collection install community.general ansible-galaxy collection install community.general
@@ -42,79 +34,57 @@ collections:
- name: community.general - name: community.general
``` ```
Note that if you install the collection manually, it will not be upgraded automatically when you upgrade the Ansible package. To upgrade the collection to the latest available version, run the following command:
```bash
ansible-galaxy collection install community.general --upgrade
```
You can also install a specific version of the collection, for example, if you need to downgrade when something is broken in the latest version (please report an issue in this repository). Use the following syntax where `X.Y.Z` can be any [available version](https://galaxy.ansible.com/community/general):
```bash
ansible-galaxy collection install community.general:==X.Y.Z
```
See [Ansible Using collections](https://docs.ansible.com/ansible/latest/user_guide/collections_using.html) for more details. See [Ansible Using collections](https://docs.ansible.com/ansible/latest/user_guide/collections_using.html) for more details.
## Contributing to this collection ## Contributing to this collection
The content of this collection is made by good people just like you, a community of individuals collaborating on making the world better through developing automation software. If you want to develop new content for this collection or improve what is already here, the easiest way to work on the collection is to clone it into one of the configured [`COLLECTIONS_PATH`](https://docs.ansible.com/ansible/latest/reference_appendices/config.html#collections-paths), and work on it there.
We are actively accepting new contributors. For example, if you are working in the `~/dev` directory:
All types of contributions are very welcome. ```
cd ~/dev
You don't know how to start? Refer to our [contribution guide](https://github.com/ansible-collections/community.general/blob/stable-4/CONTRIBUTING.md)! git clone git@github.com:ansible-collections/community.general.git collections/ansible_collections/community/general
export COLLECTIONS_PATH=$(pwd)/collections:$COLLECTIONS_PATH
The current maintainers are listed in the [commit-rights.md](https://github.com/ansible-collections/community.general/blob/stable-4/commit-rights.md#people) file. If you have questions or need help, feel free to mention them in the proposals. ```
You can find more information in the [developer guide for collections](https://docs.ansible.com/ansible/devel/dev_guide/developing_collections.html#contributing-to-collections), and in the [Ansible Community Guide](https://docs.ansible.com/ansible/latest/community/index.html). You can find more information in the [developer guide for collections](https://docs.ansible.com/ansible/devel/dev_guide/developing_collections.html#contributing-to-collections), and in the [Ansible Community Guide](https://docs.ansible.com/ansible/latest/community/index.html).
Also for some notes specific to this collection see [our CONTRIBUTING documentation](https://github.com/ansible-collections/community.general/blob/stable-4/CONTRIBUTING.md).
### Running tests ### Running tests
See [here](https://docs.ansible.com/ansible/devel/dev_guide/developing_collections.html#testing-collections). See [here](https://docs.ansible.com/ansible/devel/dev_guide/developing_collections.html#testing-collections).
## Collection maintenance ### Communication
To learn how to maintain / become a maintainer of this collection, refer to: We have a dedicated Working Group for Ansible development.
* [Committer guidelines](https://github.com/ansible-collections/community.general/blob/stable-4/commit-rights.md). You can find other people interested on the following Freenode IRC channels -
* [Maintainer guidelines](https://github.com/ansible/community-docs/blob/main/maintaining.rst). - `#ansible` - For general use questions and support.
- `#ansible-devel` - For discussions on developer topics and code related to features or bugs.
It is necessary for maintainers of this collection to be subscribed to: - `#ansible-community` - For discussions on community topics and community meetings.
* The collection itself (the `Watch` button → `All Activity` in the upper right corner of the repository's homepage).
* The "Changes Impacting Collection Contributors and Maintainers" [issue](https://github.com/ansible-collections/overview/issues/45).
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 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). For more information about [communication](https://docs.ansible.com/ansible/latest/community/communication.html)
## Publishing New Version ### 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. Basic instructions without release branches:
1. Create `changelogs/fragments/<version>.yml` with `release_summary:` section (which must be a string, not a list).
2. Run `antsibull-changelog release --collection-flatmap yes`
3. Make sure `CHANGELOG.rst` and `changelogs/changelog.yaml` are added to git, and the deleted fragments have been removed.
4. Tag the commit with `<version>`. Push changes and tag to the main repository.
## Release notes ## Release notes
See the [changelog](https://github.com/ansible-collections/community.general/blob/stable-4/CHANGELOG.rst). See the [changelog](https://github.com/ansible-collections/community.general/blob/stable-3/CHANGELOG.rst).
## Roadmap ## Roadmap
In general, we plan to release a major version every six months, and minor versions every two months. Major versions can contain breaking changes, while minor versions only contain new features and bugfixes. See [this issue](https://github.com/ansible-collections/community.general/issues/582) for information on releasing, versioning and deprecation.
See [this issue](https://github.com/ansible-collections/community.general/issues/582) for information on releasing, versioning, and deprecation. In general, we plan to release a major version every six months, and minor versions every two months. Major versions can contain breaking changes, while minor versions only contain new features and bugfixes.
## More information ## More information

File diff suppressed because it is too large Load Diff

View File

@@ -67,8 +67,6 @@ Individuals who have been asked to become a part of this group have generally be
| Name | GitHub ID | IRC Nick | Other | | Name | GitHub ID | IRC Nick | Other |
| ------------------- | -------------------- | ------------------ | -------------------- | | ------------------- | -------------------- | ------------------ | -------------------- |
| Alexei Znamensky | russoz | russoz | |
| Andrew Klychkov | andersson007 | andersson007_ | | | Andrew Klychkov | andersson007 | andersson007_ | |
| Andrew Pantuso | Ajpantuso | ajpantuso | |
| Felix Fontein | felixfontein | felixfontein | | | Felix Fontein | felixfontein | felixfontein | |
| John R Barker | gundalow | gundalow | | | John R Barker | gundalow | gundalow | |

View File

@@ -1,6 +0,0 @@
---
sections:
- title: Guides
toctree:
- filter_guide
- test_guide

View File

@@ -1,13 +0,0 @@
list1:
- name: foo
extra: true
- name: bar
extra: false
- name: meh
extra: true
list2:
- name: foo
path: /foo
- name: baz
path: /baz

View File

@@ -1,19 +0,0 @@
list1:
- name: myname01
param01:
x: default_value
y: default_value
list:
- default_value
- name: myname02
param01: [1, 1, 2, 3]
list2:
- name: myname01
param01:
y: patch_value
z: patch_value
list:
- patch_value
- name: myname02
param01: [3, 4, 4, {key: value}]

View File

@@ -1,10 +0,0 @@
---
- name: 1. Merge two lists by common attribute 'name'
include_vars:
dir: example-001_vars
- debug:
var: list3
when: debug|d(false)|bool
- template:
src: list3.out.j2
dest: example-001.out

View File

@@ -1 +0,0 @@
../default-common.yml

View File

@@ -1,2 +0,0 @@
list3: "{{ list1|
community.general.lists_mergeby(list2, 'name') }}"

View File

@@ -1,10 +0,0 @@
---
- name: 2. Merge two lists by common attribute 'name'
include_vars:
dir: example-002_vars
- debug:
var: list3
when: debug|d(false)|bool
- template:
src: list3.out.j2
dest: example-002.out

View File

@@ -1 +0,0 @@
../default-common.yml

View File

@@ -1,2 +0,0 @@
list3: "{{ [list1, list2]|
community.general.lists_mergeby('name') }}"

View File

@@ -1,10 +0,0 @@
---
- name: 3. Merge recursive by 'name', replace lists (default)
include_vars:
dir: example-003_vars
- debug:
var: list3
when: debug|d(false)|bool
- template:
src: list3.out.j2
dest: example-003.out

View File

@@ -1 +0,0 @@
../default-recursive-true.yml

View File

@@ -1,3 +0,0 @@
list3: "{{ [list1, list2]|
community.general.lists_mergeby('name',
recursive=true) }}"

View File

@@ -1,10 +0,0 @@
---
- name: 4. Merge recursive by 'name', keep lists
include_vars:
dir: example-004_vars
- debug:
var: list3
when: debug|d(false)|bool
- template:
src: list3.out.j2
dest: example-004.out

View File

@@ -1 +0,0 @@
../default-recursive-true.yml

View File

@@ -1,4 +0,0 @@
list3: "{{ [list1, list2]|
community.general.lists_mergeby('name',
recursive=true,
list_merge='keep') }}"

View File

@@ -1,10 +0,0 @@
---
- name: 5. Merge recursive by 'name', append lists
include_vars:
dir: example-005_vars
- debug:
var: list3
when: debug|d(false)|bool
- template:
src: list3.out.j2
dest: example-005.out

View File

@@ -1 +0,0 @@
../default-recursive-true.yml

View File

@@ -1,4 +0,0 @@
list3: "{{ [list1, list2]|
community.general.lists_mergeby('name',
recursive=true,
list_merge='append') }}"

View File

@@ -1,10 +0,0 @@
---
- name: 6. Merge recursive by 'name', prepend lists
include_vars:
dir: example-006_vars
- debug:
var: list3
when: debug|d(false)|bool
- template:
src: list3.out.j2
dest: example-006.out

View File

@@ -1 +0,0 @@
../default-recursive-true.yml

View File

@@ -1,4 +0,0 @@
list3: "{{ [list1, list2]|
community.general.lists_mergeby('name',
recursive=true,
list_merge='prepend') }}"

View File

@@ -1,10 +0,0 @@
---
- name: 7. Merge recursive by 'name', append lists 'remove present'
include_vars:
dir: example-007_vars
- debug:
var: list3
when: debug|d(false)|bool
- template:
src: list3.out.j2
dest: example-007.out

View File

@@ -1 +0,0 @@
../default-recursive-true.yml

View File

@@ -1,4 +0,0 @@
list3: "{{ [list1, list2]|
community.general.lists_mergeby('name',
recursive=true,
list_merge='append_rp') }}"

View File

@@ -1,10 +0,0 @@
---
- name: 8. Merge recursive by 'name', prepend lists 'remove present'
include_vars:
dir: example-008_vars
- debug:
var: list3
when: debug|d(false)|bool
- template:
src: list3.out.j2
dest: example-008.out

View File

@@ -1 +0,0 @@
../default-recursive-true.yml

View File

@@ -1,4 +0,0 @@
list3: "{{ [list1, list2]|
community.general.lists_mergeby('name',
recursive=true,
list_merge='prepend_rp') }}"

View File

@@ -1,50 +0,0 @@
---
examples:
- label: 'In the example below the lists are merged by the attribute ``name``:'
file: example-001_vars/list3.yml
lang: 'yaml+jinja'
- label: 'This produces:'
file: example-001.out
lang: 'yaml'
- label: 'It is possible to use a list of lists as an input of the filter:'
file: example-002_vars/list3.yml
lang: 'yaml+jinja'
- label: 'This produces the same result as in the previous example:'
file: example-002.out
lang: 'yaml'
- label: 'Example ``list_merge=replace`` (default):'
file: example-003_vars/list3.yml
lang: 'yaml+jinja'
- label: 'This produces:'
file: example-003.out
lang: 'yaml'
- label: 'Example ``list_merge=keep``:'
file: example-004_vars/list3.yml
lang: 'yaml+jinja'
- label: 'This produces:'
file: example-004.out
lang: 'yaml'
- label: 'Example ``list_merge=append``:'
file: example-005_vars/list3.yml
lang: 'yaml+jinja'
- label: 'This produces:'
file: example-005.out
lang: 'yaml'
- label: 'Example ``list_merge=prepend``:'
file: example-006_vars/list3.yml
lang: 'yaml+jinja'
- label: 'This produces:'
file: example-006.out
lang: 'yaml'
- label: 'Example ``list_merge=append_rp``:'
file: example-007_vars/list3.yml
lang: 'yaml+jinja'
- label: 'This produces:'
file: example-007.out
lang: 'yaml'
- label: 'Example ``list_merge=prepend_rp``:'
file: example-008_vars/list3.yml
lang: 'yaml+jinja'
- label: 'This produces:'
file: example-008.out
lang: 'yaml'

View File

@@ -1,8 +0,0 @@
{% for i in examples %}
{{ i.label }}
.. code-block:: {{ i.lang }}
{{ lookup('file', i.file)|indent(2) }}
{% endfor %}

View File

@@ -1,57 +0,0 @@
Merging lists of dictionaries
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you have two or more lists of dictionaries and want to combine them into a list of merged dictionaries, where the dictionaries are merged by an attribute, you can use the ``lists_mergeby`` filter.
.. 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 :ref:`the documentation for the community.general.yaml callback plugin <ansible_collections.community.general.yaml_callback>`.
Let us use the lists below in the following examples:
.. code-block:: yaml
{{ lookup('file', 'default-common.yml')|indent(2) }}
{% for i in examples[0:2] %}
{{ i.label }}
.. code-block:: {{ i.lang }}
{{ lookup('file', i.file)|indent(2) }}
{% endfor %}
.. versionadded:: 2.0.0
{% for i in examples[2:4] %}
{{ i.label }}
.. code-block:: {{ i.lang }}
{{ lookup('file', i.file)|indent(2) }}
{% endfor %}
The filter also accepts two optional parameters: ``recursive`` and ``list_merge``. These parameters are only supported when used with ansible-base 2.10 or ansible-core, but not with Ansible 2.9. This is available since community.general 4.4.0.
**recursive**
Is a boolean, default to ``False``. Should the ``community.general.lists_mergeby`` recursively merge nested hashes. Note: It does not depend on the value of the ``hash_behaviour`` setting in ``ansible.cfg``.
**list_merge**
Is a string, its possible values are ``replace`` (default), ``keep``, ``append``, ``prepend``, ``append_rp`` or ``prepend_rp``. It modifies the behaviour of ``community.general.lists_mergeby`` when the hashes to merge contain arrays/lists.
The examples below set ``recursive=true`` and display the differences among all six options of ``list_merge``. Functionality of the parameters is exactly the same as in the filter ``combine``. See :ref:`Combining hashes/dictionaries <combine_filter>` to learn details about these options.
Let us use the lists below in the following examples
.. code-block:: yaml
{{ lookup('file', 'default-recursive-true.yml')|indent(2) }}
{% for i in examples[4:16] %}
{{ i.label }}
.. code-block:: {{ i.lang }}
{{ lookup('file', i.file)|indent(2) }}
{% endfor %}

View File

@@ -1,2 +0,0 @@
list3:
{{ list3|to_nice_yaml(indent=0) }}

View File

@@ -1,59 +0,0 @@
---
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# 1) Run all examples and create example-XXX.out
# shell> ansible-playbook playbook.yml -e examples=true
#
# 2) Optionally, for testing, create examples_all.rst
# shell> ansible-playbook playbook.yml -e examples_all=true
#
# 3) Create docs REST files
# shell> ansible-playbook playbook.yml -e merging_lists_of_dictionaries=true
#
# Notes:
# * Use YAML callback, e.g. set ANSIBLE_STDOUT_CALLBACK=community.general.yaml
# * Use sphinx-view to render and review the REST files
# shell> sphinx-view <path_to_helper>/examples_all.rst
# * Proofread and copy completed docs *.rst files into the directory rst.
# * Then delete the *.rst and *.out files from this directory. Do not
# add *.rst and *.out in this directory to the version control.
#
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# community.general/docs/docsite/helper/lists_mergeby/playbook.yml
- hosts: localhost
gather_facts: false
tasks:
- block:
- import_tasks: example-001.yml
tags: t001
- import_tasks: example-002.yml
tags: t002
- import_tasks: example-003.yml
tags: t003
- import_tasks: example-004.yml
tags: t004
- import_tasks: example-005.yml
tags: t005
- import_tasks: example-006.yml
tags: t006
- import_tasks: example-007.yml
tags: t007
- import_tasks: example-008.yml
tags: t008
when: examples|d(false)|bool
- block:
- include_vars: examples.yml
- template:
src: examples_all.rst.j2
dest: examples_all.rst
when: examples_all|d(false)|bool
- block:
- include_vars: examples.yml
- template:
src: filter_guide_abstract_informations_merging_lists_of_dictionaries.rst.j2
dest: filter_guide_abstract_informations_merging_lists_of_dictionaries.rst
when: merging_lists_of_dictionaries|d(false)|bool

View File

@@ -1,23 +0,0 @@
---
edit_on_github:
repository: ansible-collections/community.general
branch: main
path_prefix: ''
extra_links:
- 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
url: https://github.com/ansible-collections/community.general/issues/new?assignees=&labels=&template=feature_request.yml
communication:
matrix_rooms:
- topic: General usage and support questions
room: '#users:ansible.im'
irc_channels:
- topic: General usage and support questions
network: Libera
channel: '#ansible'
mailing_lists:
- topic: Ansible Project List
url: https://groups.google.com/g/ansible-project

View File

@@ -1,19 +0,0 @@
.. _ansible_collections.community.general.docsite.filter_guide:
community.general Filter Guide
==============================
The :ref:`community.general collection <plugins_in_community.general>` offers several useful filter plugins.
.. toctree::
:maxdepth: 2
filter_guide_paths
filter_guide_abstract_informations
filter_guide_working_with_times
filter_guide_working_with_versions
filter_guide_creating_identifiers
filter_guide_conversions
filter_guide_selecting_json_data
filter_guide_working_with_unicode

View File

@@ -1,10 +0,0 @@
Abstract transformations
------------------------
.. toctree::
:maxdepth: 1
filter_guide_abstract_informations_dictionaries
filter_guide_abstract_informations_grouping
filter_guide_abstract_informations_merging_lists_of_dictionaries
filter_guide_abstract_informations_counting_elements_in_sequence

View File

@@ -1,77 +0,0 @@
Counting elements in a sequence
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The ``community.general.counter`` filter plugin allows you to count (hashable) elements in a sequence. Elements are returned as dictionary keys and their counts are stored as dictionary values.
.. code-block:: yaml+jinja
- name: Count character occurrences in a string
debug:
msg: "{{ 'abccbaabca' | community.general.counter }}"
- name: Count items in a list
debug:
msg: "{{ ['car', 'car', 'bike', 'plane', 'bike'] | community.general.counter }}"
This produces:
.. code-block:: ansible-output
TASK [Count character occurrences in a string] ********************************************
ok: [localhost] => {
"msg": {
"a": 4,
"b": 3,
"c": 3
}
}
TASK [Count items in a list] **************************************************************
ok: [localhost] => {
"msg": {
"bike": 2,
"car": 2,
"plane": 1
}
}
This plugin is useful for selecting resources based on current allocation:
.. code-block:: yaml+jinja
- name: Get ID of SCSI controller(s) with less than 4 disks attached and choose the one with the least disks
debug:
msg: >-
{{
( disks | dict2items | map(attribute='value.adapter') | list
| community.general.counter | dict2items
| rejectattr('value', '>=', 4) | sort(attribute='value') | first
).key
}}
vars:
disks:
sda:
adapter: scsi_1
sdb:
adapter: scsi_1
sdc:
adapter: scsi_1
sdd:
adapter: scsi_1
sde:
adapter: scsi_2
sdf:
adapter: scsi_3
sdg:
adapter: scsi_3
This produces:
.. code-block:: ansible-output
TASK [Get ID of SCSI controller(s) with less than 4 disks attached and choose the one with the least disks]
ok: [localhost] => {
"msg": "scsi_2"
}
.. versionadded:: 4.3.0

View File

@@ -1,119 +0,0 @@
Dictionaries
^^^^^^^^^^^^
You can use the ``dict_kv`` filter to create a single-entry dictionary with ``value | community.general.dict_kv(key)``:
.. code-block:: yaml+jinja
- name: Create a single-entry dictionary
debug:
msg: "{{ myvar | community.general.dict_kv('thatsmyvar') }}"
vars:
myvar: myvalue
- name: Create a list of dictionaries where the 'server' field is taken from a list
debug:
msg: >-
{{ myservers | map('community.general.dict_kv', 'server')
| map('combine', common_config) }}
vars:
common_config:
type: host
database: all
myservers:
- server1
- server2
This produces:
.. code-block:: ansible-output
TASK [Create a single-entry dictionary] **************************************************
ok: [localhost] => {
"msg": {
"thatsmyvar": "myvalue"
}
}
TASK [Create a list of dictionaries where the 'server' field is taken from a list] *******
ok: [localhost] => {
"msg": [
{
"database": "all",
"server": "server1",
"type": "host"
},
{
"database": "all",
"server": "server2",
"type": "host"
}
]
}
.. versionadded:: 2.0.0
If you need to convert a list of key-value pairs to a dictionary, you can use the ``dict`` function. Unfortunately, this function cannot be used with ``map``. For this, the ``community.general.dict`` filter can be used:
.. code-block:: yaml+jinja
- name: Create a dictionary with the dict function
debug:
msg: "{{ dict([[1, 2], ['a', 'b']]) }}"
- name: Create a dictionary with the community.general.dict filter
debug:
msg: "{{ [[1, 2], ['a', 'b']] | community.general.dict }}"
- name: Create a list of dictionaries with map and the community.general.dict filter
debug:
msg: >-
{{ values | map('zip', ['k1', 'k2', 'k3'])
| map('map', 'reverse')
| map('community.general.dict') }}
vars:
values:
- - foo
- 23
- a
- - bar
- 42
- b
This produces:
.. code-block:: ansible-output
TASK [Create a dictionary with the dict function] ****************************************
ok: [localhost] => {
"msg": {
"1": 2,
"a": "b"
}
}
TASK [Create a dictionary with the community.general.dict filter] ************************
ok: [localhost] => {
"msg": {
"1": 2,
"a": "b"
}
}
TASK [Create a list of dictionaries with map and the community.general.dict filter] ******
ok: [localhost] => {
"msg": [
{
"k1": "foo",
"k2": 23,
"k3": "a"
},
{
"k1": "bar",
"k2": 42,
"k3": "b"
}
]
}
.. versionadded:: 3.0.0

View File

@@ -1,98 +0,0 @@
Grouping
^^^^^^^^
If you have a list of dictionaries, the Jinja2 ``groupby`` filter allows to group the list by an attribute. This results in a list of ``(grouper, list)`` namedtuples, where ``list`` contains all dictionaries where the selected attribute equals ``grouper``. If you know that for every ``grouper``, there will be a most one entry in that list, you can use the ``community.general.groupby_as_dict`` filter to convert the original list into a dictionary which maps ``grouper`` to the corresponding dictionary.
One example is ``ansible_facts.mounts``, which is a list of dictionaries where each has one ``device`` element to indicate the device which is mounted. Therefore, ``ansible_facts.mounts | community.general.groupby_as_dict('device')`` is a dictionary mapping a device to the mount information:
.. code-block:: yaml+jinja
- name: Output mount facts grouped by device name
debug:
var: ansible_facts.mounts | community.general.groupby_as_dict('device')
- name: Output mount facts grouped by mount point
debug:
var: ansible_facts.mounts | community.general.groupby_as_dict('mount')
This produces:
.. code-block:: ansible-output
TASK [Output mount facts grouped by device name] ******************************************
ok: [localhost] => {
"ansible_facts.mounts | community.general.groupby_as_dict('device')": {
"/dev/sda1": {
"block_available": 2000,
"block_size": 4096,
"block_total": 2345,
"block_used": 345,
"device": "/dev/sda1",
"fstype": "ext4",
"inode_available": 500,
"inode_total": 512,
"inode_used": 12,
"mount": "/boot",
"options": "rw,relatime,data=ordered",
"size_available": 56821,
"size_total": 543210,
"uuid": "ab31cade-d9c1-484d-8482-8a4cbee5241a"
},
"/dev/sda2": {
"block_available": 1234,
"block_size": 4096,
"block_total": 12345,
"block_used": 11111,
"device": "/dev/sda2",
"fstype": "ext4",
"inode_available": 1111,
"inode_total": 1234,
"inode_used": 123,
"mount": "/",
"options": "rw,relatime",
"size_available": 42143,
"size_total": 543210,
"uuid": "abcdef01-2345-6789-0abc-def012345678"
}
}
}
TASK [Output mount facts grouped by mount point] ******************************************
ok: [localhost] => {
"ansible_facts.mounts | community.general.groupby_as_dict('mount')": {
"/": {
"block_available": 1234,
"block_size": 4096,
"block_total": 12345,
"block_used": 11111,
"device": "/dev/sda2",
"fstype": "ext4",
"inode_available": 1111,
"inode_total": 1234,
"inode_used": 123,
"mount": "/",
"options": "rw,relatime",
"size_available": 42143,
"size_total": 543210,
"uuid": "bdf50b7d-4859-40af-8665-c637ee7a7808"
},
"/boot": {
"block_available": 2000,
"block_size": 4096,
"block_total": 2345,
"block_used": 345,
"device": "/dev/sda1",
"fstype": "ext4",
"inode_available": 500,
"inode_total": 512,
"inode_used": 12,
"mount": "/boot",
"options": "rw,relatime,data=ordered",
"size_available": 56821,
"size_total": 543210,
"uuid": "ab31cade-d9c1-484d-8482-8a4cbee5241a"
}
}
}
.. versionadded: 3.0.0

View File

@@ -1,292 +0,0 @@
Merging lists of dictionaries
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you have two or more lists of dictionaries and want to combine them into a list of merged dictionaries, where the dictionaries are merged by an attribute, you can use the ``lists_mergeby`` filter.
.. 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 :ref:`the documentation for the community.general.yaml callback plugin <ansible_collections.community.general.yaml_callback>`.
Let us use the lists below in the following examples:
.. code-block:: yaml
list1:
- name: foo
extra: true
- name: bar
extra: false
- name: meh
extra: true
list2:
- name: foo
path: /foo
- name: baz
path: /baz
In the example below the lists are merged by the attribute ``name``:
.. code-block:: yaml+jinja
list3: "{{ list1|
community.general.lists_mergeby(list2, 'name') }}"
This produces:
.. code-block:: yaml
list3:
- extra: false
name: bar
- name: baz
path: /baz
- extra: true
name: foo
path: /foo
- extra: true
name: meh
.. versionadded:: 2.0.0
It is possible to use a list of lists as an input of the filter:
.. code-block:: yaml+jinja
list3: "{{ [list1, list2]|
community.general.lists_mergeby('name') }}"
This produces the same result as in the previous example:
.. code-block:: yaml
list3:
- extra: false
name: bar
- name: baz
path: /baz
- extra: true
name: foo
path: /foo
- extra: true
name: meh
The filter also accepts two optional parameters: ``recursive`` and ``list_merge``. These parameters are only supported when used with ansible-base 2.10 or ansible-core, but not with Ansible 2.9. This is available since community.general 4.4.0.
**recursive**
Is a boolean, default to ``False``. Should the ``community.general.lists_mergeby`` recursively merge nested hashes. Note: It does not depend on the value of the ``hash_behaviour`` setting in ``ansible.cfg``.
**list_merge**
Is a string, its possible values are ``replace`` (default), ``keep``, ``append``, ``prepend``, ``append_rp`` or ``prepend_rp``. It modifies the behaviour of ``community.general.lists_mergeby`` when the hashes to merge contain arrays/lists.
The examples below set ``recursive=true`` and display the differences among all six options of ``list_merge``. Functionality of the parameters is exactly the same as in the filter ``combine``. See :ref:`Combining hashes/dictionaries <combine_filter>` to learn details about these options.
Let us use the lists below in the following examples
.. code-block:: yaml
list1:
- name: myname01
param01:
x: default_value
y: default_value
list:
- default_value
- name: myname02
param01: [1, 1, 2, 3]
list2:
- name: myname01
param01:
y: patch_value
z: patch_value
list:
- patch_value
- name: myname02
param01: [3, 4, 4, {key: value}]
Example ``list_merge=replace`` (default):
.. code-block:: yaml+jinja
list3: "{{ [list1, list2]|
community.general.lists_mergeby('name',
recursive=true) }}"
This produces:
.. code-block:: yaml
list3:
- name: myname01
param01:
list:
- patch_value
x: default_value
y: patch_value
z: patch_value
- name: myname02
param01:
- 3
- 4
- 4
- key: value
Example ``list_merge=keep``:
.. code-block:: yaml+jinja
list3: "{{ [list1, list2]|
community.general.lists_mergeby('name',
recursive=true,
list_merge='keep') }}"
This produces:
.. code-block:: yaml
list3:
- name: myname01
param01:
list:
- default_value
x: default_value
y: patch_value
z: patch_value
- name: myname02
param01:
- 1
- 1
- 2
- 3
Example ``list_merge=append``:
.. code-block:: yaml+jinja
list3: "{{ [list1, list2]|
community.general.lists_mergeby('name',
recursive=true,
list_merge='append') }}"
This produces:
.. code-block:: yaml
list3:
- name: myname01
param01:
list:
- default_value
- patch_value
x: default_value
y: patch_value
z: patch_value
- name: myname02
param01:
- 1
- 1
- 2
- 3
- 3
- 4
- 4
- key: value
Example ``list_merge=prepend``:
.. code-block:: yaml+jinja
list3: "{{ [list1, list2]|
community.general.lists_mergeby('name',
recursive=true,
list_merge='prepend') }}"
This produces:
.. code-block:: yaml
list3:
- name: myname01
param01:
list:
- patch_value
- default_value
x: default_value
y: patch_value
z: patch_value
- name: myname02
param01:
- 3
- 4
- 4
- key: value
- 1
- 1
- 2
- 3
Example ``list_merge=append_rp``:
.. code-block:: yaml+jinja
list3: "{{ [list1, list2]|
community.general.lists_mergeby('name',
recursive=true,
list_merge='append_rp') }}"
This produces:
.. code-block:: yaml
list3:
- name: myname01
param01:
list:
- default_value
- patch_value
x: default_value
y: patch_value
z: patch_value
- name: myname02
param01:
- 1
- 1
- 2
- 3
- 4
- 4
- key: value
Example ``list_merge=prepend_rp``:
.. code-block:: yaml+jinja
list3: "{{ [list1, list2]|
community.general.lists_mergeby('name',
recursive=true,
list_merge='prepend_rp') }}"
This produces:
.. code-block:: yaml
list3:
- name: myname01
param01:
list:
- patch_value
- default_value
x: default_value
y: patch_value
z: patch_value
- name: myname02
param01:
- 3
- 4
- 4
- key: value
- 1
- 1
- 2

View File

@@ -1,108 +0,0 @@
Conversions
-----------
Parsing CSV files
^^^^^^^^^^^^^^^^^
Ansible offers the :ref:`community.general.read_csv module <ansible_collections.community.general.read_csv_module>` to read CSV files. Sometimes you need to convert strings to CSV files instead. For this, the ``from_csv`` filter exists.
.. code-block:: yaml+jinja
- name: "Parse CSV from string"
debug:
msg: "{{ csv_string | community.general.from_csv }}"
vars:
csv_string: |
foo,bar,baz
1,2,3
you,this,then
This produces:
.. code-block:: ansible-output
TASK [Parse CSV from string] **************************************************************
ok: [localhost] => {
"msg": [
{
"bar": "2",
"baz": "3",
"foo": "1"
},
{
"bar": "this",
"baz": "then",
"foo": "you"
}
]
}
The ``from_csv`` filter has several keyword arguments to control its behavior:
:dialect: Dialect of the CSV file. Default is ``excel``. Other possible choices are ``excel-tab`` and ``unix``. If one of ``delimiter``, ``skipinitialspace`` or ``strict`` is specified, ``dialect`` is ignored.
:fieldnames: A set of column names to use. If not provided, the first line of the CSV is assumed to contain the column names.
:delimiter: Sets the delimiter to use. Default depends on the dialect used.
:skipinitialspace: Set to ``true`` to ignore space directly after the delimiter. Default depends on the dialect used (usually ``false``).
:strict: Set to ``true`` to error out on invalid CSV input.
.. versionadded: 3.0.0
Converting to JSON
^^^^^^^^^^^^^^^^^^
`JC <https://pypi.org/project/jc/>`_ is a CLI tool and Python library which allows to interpret output of various CLI programs as JSON. It is also available as a filter in community.general. This filter needs the `jc Python library <https://pypi.org/project/jc/>`_ installed on the controller.
.. code-block:: yaml+jinja
- name: Run 'ls' to list files in /
command: ls /
register: result
- name: Parse the ls output
debug:
msg: "{{ result.stdout | community.general.jc('ls') }}"
This produces:
.. code-block:: ansible-output
TASK [Run 'ls' to list files in /] ********************************************************
changed: [localhost]
TASK [Parse the ls output] ****************************************************************
ok: [localhost] => {
"msg": [
{
"filename": "bin"
},
{
"filename": "boot"
},
{
"filename": "dev"
},
{
"filename": "etc"
},
{
"filename": "home"
},
{
"filename": "lib"
},
{
"filename": "proc"
},
{
"filename": "root"
},
{
"filename": "run"
},
{
"filename": "tmp"
}
]
}
.. versionadded: 2.0.0

View File

@@ -1,80 +0,0 @@
Creating identifiers
--------------------
The following filters allow to create identifiers.
Hashids
^^^^^^^
`Hashids <https://hashids.org/>`_ allow to convert sequences of integers to short unique string identifiers. This filter needs the `hashids Python library <https://pypi.org/project/hashids/>`_ installed on the controller.
.. code-block:: yaml+jinja
- name: "Create hashid"
debug:
msg: "{{ [1234, 5, 6] | community.general.hashids_encode }}"
- name: "Decode hashid"
debug:
msg: "{{ 'jm2Cytn' | community.general.hashids_decode }}"
This produces:
.. code-block:: ansible-output
TASK [Create hashid] **********************************************************************
ok: [localhost] => {
"msg": "jm2Cytn"
}
TASK [Decode hashid] **********************************************************************
ok: [localhost] => {
"msg": [
1234,
5,
6
]
}
The hashids filters accept keyword arguments to allow fine-tuning the hashids generated:
:salt: String to use as salt when hashing.
:alphabet: String of 16 or more unique characters to produce a hash.
:min_length: Minimum length of hash produced.
.. versionadded: 3.0.0
Random MACs
^^^^^^^^^^^
You can use the ``random_mac`` filter to complete a partial `MAC address <https://en.wikipedia.org/wiki/MAC_address>`_ to a random 6-byte MAC address.
.. code-block:: yaml+jinja
- name: "Create a random MAC starting with ff:"
debug:
msg: "{{ 'FF' | community.general.random_mac }}"
- name: "Create a random MAC starting with 00:11:22:"
debug:
msg: "{{ '00:11:22' | community.general.random_mac }}"
This produces:
.. code-block:: ansible-output
TASK [Create a random MAC starting with ff:] **********************************************
ok: [localhost] => {
"msg": "ff:69:d3:78:7f:b4"
}
TASK [Create a random MAC starting with 00:11:22:] ****************************************
ok: [localhost] => {
"msg": "00:11:22:71:5d:3b"
}
You can also initialize the random number generator from a seed to create random-but-idempotent MAC addresses:
.. code-block:: yaml+jinja
"{{ '52:54:00' | community.general.random_mac(seed=inventory_hostname) }}"

View File

@@ -1,14 +0,0 @@
Paths
-----
The ``path_join`` filter has been added in ansible-base 2.10. If you want to use this filter, but also need to support Ansible 2.9, you can use ``community.general``'s ``path_join`` shim, ``community.general.path_join``. This filter redirects to ``path_join`` for ansible-base 2.10 and ansible-core 2.11 or newer, and re-implements the filter for Ansible 2.9.
.. code-block:: yaml+jinja
# ansible-base 2.10 or newer:
path: {{ ('/etc', path, 'subdir', file) | path_join }}
# Also works with Ansible 2.9:
path: {{ ('/etc', path, 'subdir', file) | community.general.path_join }}
.. versionadded:: 3.0.0

View File

@@ -1,144 +0,0 @@
.. _ansible_collections.community.general.docsite.json_query_filter:
Selecting JSON data: JSON queries
---------------------------------
To select a single element or a data subset from a complex data structure in JSON format (for example, Ansible facts), use the ``json_query`` filter. The ``json_query`` filter lets you query a complex JSON structure and iterate over it using a loop structure.
.. note:: You must manually install the **jmespath** dependency on the Ansible controller before using this filter. This filter is built upon **jmespath**, and you can use the same syntax. For examples, see `jmespath examples <http://jmespath.org/examples.html>`_.
Consider this data structure:
.. code-block:: yaml+jinja
{
"domain_definition": {
"domain": {
"cluster": [
{
"name": "cluster1"
},
{
"name": "cluster2"
}
],
"server": [
{
"name": "server11",
"cluster": "cluster1",
"port": "8080"
},
{
"name": "server12",
"cluster": "cluster1",
"port": "8090"
},
{
"name": "server21",
"cluster": "cluster2",
"port": "9080"
},
{
"name": "server22",
"cluster": "cluster2",
"port": "9090"
}
],
"library": [
{
"name": "lib1",
"target": "cluster1"
},
{
"name": "lib2",
"target": "cluster2"
}
]
}
}
}
To extract all clusters from this structure, you can use the following query:
.. code-block:: yaml+jinja
- name: Display all cluster names
ansible.builtin.debug:
var: item
loop: "{{ domain_definition | community.general.json_query('domain.cluster[*].name') }}"
To extract all server names:
.. code-block:: yaml+jinja
- name: Display all server names
ansible.builtin.debug:
var: item
loop: "{{ domain_definition | community.general.json_query('domain.server[*].name') }}"
To extract ports from cluster1:
.. code-block:: yaml+jinja
- name: Display all ports from cluster1
ansible.builtin.debug:
var: item
loop: "{{ domain_definition | community.general.json_query(server_name_cluster1_query) }}"
vars:
server_name_cluster1_query: "domain.server[?cluster=='cluster1'].port"
.. note:: You can use a variable to make the query more readable.
To print out the ports from cluster1 in a comma separated string:
.. code-block:: yaml+jinja
- name: Display all ports from cluster1 as a string
ansible.builtin.debug:
msg: "{{ domain_definition | community.general.json_query('domain.server[?cluster==`cluster1`].port') | join(', ') }}"
.. note:: In the example above, quoting literals using backticks avoids escaping quotes and maintains readability.
You can use YAML `single quote escaping <https://yaml.org/spec/current.html#id2534365>`_:
.. code-block:: yaml+jinja
- name: Display all ports from cluster1
ansible.builtin.debug:
var: item
loop: "{{ domain_definition | community.general.json_query('domain.server[?cluster==''cluster1''].port') }}"
.. note:: Escaping single quotes within single quotes in YAML is done by doubling the single quote.
To get a hash map with all ports and names of a cluster:
.. code-block:: yaml+jinja
- name: Display all server ports and names from cluster1
ansible.builtin.debug:
var: item
loop: "{{ domain_definition | community.general.json_query(server_name_cluster1_query) }}"
vars:
server_name_cluster1_query: "domain.server[?cluster=='cluster2'].{name: name, port: port}"
To extract ports from all clusters with name starting with 'server1':
.. code-block:: yaml+jinja
- name: Display all ports from cluster1
ansible.builtin.debug:
msg: "{{ domain_definition | to_json | from_json | community.general.json_query(server_name_query) }}"
vars:
server_name_query: "domain.server[?starts_with(name,'server1')].port"
To extract ports from all clusters with name containing 'server1':
.. code-block:: yaml+jinja
- name: Display all ports from cluster1
ansible.builtin.debug:
msg: "{{ domain_definition | to_json | from_json | community.general.json_query(server_name_query) }}"
vars:
server_name_query: "domain.server[?contains(name,'server1')].port"
.. note:: while using ``starts_with`` and ``contains``, you have to use `` to_json | from_json `` filter for correct parsing of data structure.

View File

@@ -1,84 +0,0 @@
Working with times
------------------
The ``to_time_unit`` filter allows to convert times from a human-readable string to a unit. For example, ``'4h 30min 12second' | community.general.to_time_unit('hour')`` gives the number of hours that correspond to 4 hours, 30 minutes and 12 seconds.
There are shorthands to directly convert to various units, like ``to_hours``, ``to_minutes``, ``to_seconds``, and so on. The following table lists all units that can be used:
.. list-table:: Units
:widths: 25 25 25 25
:header-rows: 1
* - Unit name
- Unit value in seconds
- Unit strings for filter
- Shorthand filter
* - Millisecond
- 1/1000 second
- ``ms``, ``millisecond``, ``milliseconds``, ``msec``, ``msecs``, ``msecond``, ``mseconds``
- ``to_milliseconds``
* - Second
- 1 second
- ``s``, ``sec``, ``secs``, ``second``, ``seconds``
- ``to_seconds``
* - Minute
- 60 seconds
- ``m``, ``min``, ``mins``, ``minute``, ``minutes``
- ``to_minutes``
* - Hour
- 60*60 seconds
- ``h``, ``hour``, ``hours``
- ``to_hours``
* - Day
- 24*60*60 seconds
- ``d``, ``day``, ``days``
- ``to_days``
* - Week
- 7*24*60*60 seconds
- ``w``, ``week``, ``weeks``
- ``to_weeks``
* - Month
- 30*24*60*60 seconds
- ``mo``, ``month``, ``months``
- ``to_months``
* - Year
- 365*24*60*60 seconds
- ``y``, ``year``, ``years``
- ``to_years``
Note that months and years are using a simplified representation: a month is 30 days, and a year is 365 days. If you need different definitions of months or years, you can pass them as keyword arguments. For example, if you want a year to be 365.25 days, and a month to be 30.5 days, you can write ``'11months 4' | community.general.to_years(year=365.25, month=30.5)``. These keyword arguments can be specified to ``to_time_unit`` and to all shorthand filters.
.. code-block:: yaml+jinja
- name: Convert string to seconds
debug:
msg: "{{ '30h 20m 10s 123ms' | community.general.to_time_unit('seconds') }}"
- name: Convert string to hours
debug:
msg: "{{ '30h 20m 10s 123ms' | community.general.to_hours }}"
- name: Convert string to years (using 365.25 days == 1 year)
debug:
msg: "{{ '400d 15h' | community.general.to_years(year=365.25) }}"
This produces:
.. code-block:: ansible-output
TASK [Convert string to seconds] **********************************************************
ok: [localhost] => {
"msg": "109210.123"
}
TASK [Convert string to hours] ************************************************************
ok: [localhost] => {
"msg": "30.336145277778"
}
TASK [Convert string to years (using 365.25 days == 1 year)] ******************************
ok: [localhost] => {
"msg": "1.096851471595"
}
.. versionadded: 0.2.0

View File

@@ -1,30 +0,0 @@
Working with Unicode
---------------------
`Unicode <https://unicode.org/main.html>`_ makes it possible to produce two strings which may be visually equivalent, but are comprised of distinctly different characters/character sequences. To address this ``Unicode`` defines `normalization forms <https://unicode.org/reports/tr15/>`_ which avoid these distinctions by choosing a unique character sequence for a given visual representation.
You can use the ``community.general.unicode_normalize`` filter to normalize ``Unicode`` strings within your playbooks.
.. code-block:: yaml+jinja
- name: Compare Unicode representations
debug:
msg: "{{ with_combining_character | community.general.unicode_normalize == without_combining_character }}"
vars:
with_combining_character: "{{ 'Mayagu\u0308ez' }}"
without_combining_character: Mayagüez
This produces:
.. code-block:: ansible-output
TASK [Compare Unicode representations] ********************************************************
ok: [localhost] => {
"msg": true
}
The ``community.general.unicode_normalize`` filter accepts a keyword argument to select the ``Unicode`` form used to normalize the input string.
:form: One of ``'NFC'`` (default), ``'NFD'``, ``'NFKC'``, or ``'NFKD'``. See the `Unicode reference <https://unicode.org/reports/tr15/>`_ for more information.
.. versionadded:: 3.7.0

View File

@@ -1,34 +0,0 @@
Working with versions
---------------------
If you need to sort a list of version numbers, the Jinja ``sort`` filter is problematic. Since it sorts lexicographically, ``2.10`` will come before ``2.9``. To treat version numbers correctly, you can use the ``version_sort`` filter:
.. code-block:: yaml+jinja
- name: Sort list by version number
debug:
var: ansible_versions | community.general.version_sort
vars:
ansible_versions:
- '2.8.0'
- '2.11.0'
- '2.7.0'
- '2.10.0'
- '2.9.0'
This produces:
.. code-block:: ansible-output
TASK [Sort list by version number] ********************************************************
ok: [localhost] => {
"ansible_versions | community.general.version_sort": [
"2.7.0",
"2.8.0",
"2.9.0",
"2.10.0",
"2.11.0"
]
}
.. versionadded: 2.2.0

View File

@@ -1,28 +0,0 @@
.. _ansible_collections.community.general.docsite.test_guide:
community.general Test (Plugin) Guide
=====================================
The :ref:`community.general collection <plugins_in_community.general>` offers currently one test plugin.
.. contents:: Topics
Feature Tests
-------------
The ``a_module`` test allows to check whether a given string refers to an existing module or action plugin. This can be useful in roles, which can use this to ensure that required modules are present ahead of time.
.. code-block:: yaml+jinja
- name: Make sure that community.aws.route53 is available
assert:
that:
- >
'community.aws.route53' is community.general.a_module
- name: Make sure that community.general.does_not_exist is not a module or action plugin
assert:
that:
- "'community.general.does_not_exist' is not community.general.a_module"
.. versionadded:: 4.0.0

View File

@@ -1,6 +1,6 @@
namespace: community namespace: community
name: general name: general
version: 4.7.0 version: 3.0.2
readme: README.md readme: README.md
authors: authors:
- Ansible (https://github.com/ansible) - Ansible (https://github.com/ansible)

View File

@@ -1,5 +1,31 @@
--- ---
requires_ansible: '>=2.9.10' requires_ansible: '>=2.9.10'
action_groups:
ovirt:
- ovirt_affinity_label_facts
- ovirt_api_facts
- ovirt_cluster_facts
- ovirt_datacenter_facts
- ovirt_disk_facts
- ovirt_event_facts
- ovirt_external_provider_facts
- ovirt_group_facts
- ovirt_host_facts
- ovirt_host_storage_facts
- ovirt_network_facts
- ovirt_nic_facts
- ovirt_permission_facts
- ovirt_quota_facts
- ovirt_scheduling_policy_facts
- ovirt_snapshot_facts
- ovirt_storage_domain_facts
- ovirt_storage_template_facts
- ovirt_storage_vm_facts
- ovirt_tag_facts
- ovirt_template_facts
- ovirt_user_facts
- ovirt_vm_facts
- ovirt_vmpool_facts
plugin_routing: plugin_routing:
connection: connection:
docker: docker:
@@ -11,12 +37,6 @@ plugin_routing:
redirect: community.google.gcp_storage_file redirect: community.google.gcp_storage_file
hashi_vault: hashi_vault:
redirect: community.hashi_vault.hashi_vault redirect: community.hashi_vault.hashi_vault
nios:
redirect: infoblox.nios_modules.nios_lookup
nios_next_ip:
redirect: infoblox.nios_modules.nios_next_ip
nios_next_network:
redirect: infoblox.nios_modules.nios_next_network
modules: modules:
ali_instance_facts: ali_instance_facts:
tombstone: tombstone:
@@ -121,13 +141,11 @@ plugin_routing:
gcp_forwarding_rule: gcp_forwarding_rule:
tombstone: tombstone:
removal_version: 2.0.0 removal_version: 2.0.0
warning_text: Use google.cloud.gcp_compute_forwarding_rule or google.cloud.gcp_compute_global_forwarding_rule warning_text: Use google.cloud.gcp_compute_forwarding_rule or google.cloud.gcp_compute_global_forwarding_rule instead.
instead.
gcp_healthcheck: gcp_healthcheck:
tombstone: tombstone:
removal_version: 2.0.0 removal_version: 2.0.0
warning_text: Use google.cloud.gcp_compute_health_check, google.cloud.gcp_compute_http_health_check warning_text: Use google.cloud.gcp_compute_health_check, google.cloud.gcp_compute_http_health_check or google.cloud.gcp_compute_https_health_check instead.
or google.cloud.gcp_compute_https_health_check instead.
gcp_target_proxy: gcp_target_proxy:
tombstone: tombstone:
removal_version: 2.0.0 removal_version: 2.0.0
@@ -138,22 +156,37 @@ plugin_routing:
warning_text: Use google.cloud.gcp_compute_url_map instead. warning_text: Use google.cloud.gcp_compute_url_map instead.
gcpubsub: gcpubsub:
redirect: community.google.gcpubsub redirect: community.google.gcpubsub
gcpubsub_info:
redirect: community.google.gcpubsub_info
gcpubsub_facts: gcpubsub_facts:
tombstone: tombstone:
removal_version: 3.0.0 removal_version: 3.0.0
warning_text: Use community.google.gcpubsub_info instead. warning_text: Use community.google.gcpubsub_info instead.
gcpubsub_info:
redirect: community.google.gcpubsub_info
gcspanner: gcspanner:
tombstone: tombstone:
removal_version: 2.0.0 removal_version: 2.0.0
warning_text: Use google.cloud.gcp_spanner_database and/or google.cloud.gcp_spanner_instance warning_text: Use google.cloud.gcp_spanner_database and/or google.cloud.gcp_spanner_instance instead.
instead.
github_hooks: github_hooks:
tombstone: tombstone:
removal_version: 2.0.0 removal_version: 2.0.0
warning_text: Use community.general.github_webhook and community.general.github_webhook_info warning_text: Use community.general.github_webhook and community.general.github_webhook_info instead.
instead. # Adding tombstones burns the old name, so we simply remove the entries:
# gluster_heal_info:
# tombstone:
# removal_version: 3.0.0
# warning_text: The gluster modules have migrated to the gluster.gluster collection. Use gluster.gluster.gluster_heal_info instead.
# gluster_peer:
# tombstone:
# removal_version: 3.0.0
# warning_text: The gluster modules have migrated to the gluster.gluster collection. Use gluster.gluster.gluster_peer instead.
# gluster_volume:
# tombstone:
# removal_version: 3.0.0
# warning_text: The gluster modules have migrated to the gluster.gluster collection. Use gluster.gluster.gluster_volume instead.
# helm:
# tombstone:
# removal_version: 3.0.0
# warning_text: Use community.kubernetes.helm instead.
hetzner_failover_ip: hetzner_failover_ip:
redirect: community.hrobot.failover_ip redirect: community.hrobot.failover_ip
hetzner_failover_ip_info: hetzner_failover_ip_info:
@@ -201,13 +234,11 @@ plugin_routing:
logicmonitor: logicmonitor:
tombstone: tombstone:
removal_version: 1.0.0 removal_version: 1.0.0
warning_text: The logicmonitor_facts module is no longer maintained and the warning_text: The logicmonitor_facts module is no longer maintained and the API used has been disabled in 2017.
API used has been disabled in 2017.
logicmonitor_facts: logicmonitor_facts:
tombstone: tombstone:
removal_version: 1.0.0 removal_version: 1.0.0
warning_text: The logicmonitor_facts module is no longer maintained and the warning_text: The logicmonitor_facts module is no longer maintained and the API used has been disabled in 2017.
API used has been disabled in 2017.
memset_memstore_facts: memset_memstore_facts:
tombstone: tombstone:
removal_version: 3.0.0 removal_version: 3.0.0
@@ -256,38 +287,6 @@ plugin_routing:
tombstone: tombstone:
removal_version: 3.0.0 removal_version: 3.0.0
warning_text: Use community.general.nginx_status_info instead. warning_text: Use community.general.nginx_status_info instead.
nios_a_record:
redirect: infoblox.nios_modules.nios_a_record
nios_aaaa_record:
redirect: infoblox.nios_modules.nios_aaaa_record
nios_cname_record:
redirect: infoblox.nios_modules.nios_cname_record
nios_dns_view:
redirect: infoblox.nios_modules.nios_dns_view
nios_fixed_address:
redirect: infoblox.nios_modules.nios_fixed_address
nios_host_record:
redirect: infoblox.nios_modules.nios_host_record
nios_member:
redirect: infoblox.nios_modules.nios_member
nios_mx_record:
redirect: infoblox.nios_modules.nios_mx_record
nios_naptr_record:
redirect: infoblox.nios_modules.nios_naptr_record
nios_network:
redirect: infoblox.nios_modules.nios_network
nios_network_view:
redirect: infoblox.nios_modules.nios_network_view
nios_nsgroup:
redirect: infoblox.nios_modules.nios_nsgroup
nios_ptr_record:
redirect: infoblox.nios_modules.nios_ptr_record
nios_srv_record:
redirect: infoblox.nios_modules.nios_srv_record
nios_txt_record:
redirect: infoblox.nios_modules.nios_txt_record
nios_zone:
redirect: infoblox.nios_modules.nios_zone
ome_device_info: ome_device_info:
redirect: dellemc.openmanage.ome_device_info redirect: dellemc.openmanage.ome_device_info
one_image_facts: one_image_facts:
@@ -321,8 +320,7 @@ plugin_routing:
oneview_logical_interconnect_group_facts: oneview_logical_interconnect_group_facts:
tombstone: tombstone:
removal_version: 3.0.0 removal_version: 3.0.0
warning_text: Use community.general.oneview_logical_interconnect_group_info warning_text: Use community.general.oneview_logical_interconnect_group_info instead.
instead.
oneview_network_set_facts: oneview_network_set_facts:
tombstone: tombstone:
removal_version: 3.0.0 removal_version: 3.0.0
@@ -479,10 +477,10 @@ plugin_routing:
redirect: community.postgresql.postgresql_table redirect: community.postgresql.postgresql_table
postgresql_tablespace: postgresql_tablespace:
redirect: community.postgresql.postgresql_tablespace redirect: community.postgresql.postgresql_tablespace
postgresql_user:
redirect: community.postgresql.postgresql_user
postgresql_user_obj_stat_info: postgresql_user_obj_stat_info:
redirect: community.postgresql.postgresql_user_obj_stat_info redirect: community.postgresql.postgresql_user_obj_stat_info
postgresql_user:
redirect: community.postgresql.postgresql_user
purefa_facts: purefa_facts:
tombstone: tombstone:
removal_version: 3.0.0 removal_version: 3.0.0
@@ -570,11 +568,11 @@ plugin_routing:
redirect: community.kubevirt.kubevirt_common_options redirect: community.kubevirt.kubevirt_common_options
kubevirt_vm_options: kubevirt_vm_options:
redirect: community.kubevirt.kubevirt_vm_options redirect: community.kubevirt.kubevirt_vm_options
nios:
redirect: infoblox.nios_modules.nios
postgresql: postgresql:
redirect: community.postgresql.postgresql redirect: community.postgresql.postgresql
module_utils: module_utils:
remote_management.dellemc.dellemc_idrac:
redirect: dellemc.openmanage.dellemc_idrac
docker.common: docker.common:
redirect: community.docker.common redirect: community.docker.common
docker.swarm: docker.swarm:
@@ -589,30 +587,23 @@ plugin_routing:
redirect: community.hrobot.robot redirect: community.hrobot.robot
kubevirt: kubevirt:
redirect: community.kubevirt.kubevirt redirect: community.kubevirt.kubevirt
net_tools.nios.api:
redirect: infoblox.nios_modules.api
postgresql:
redirect: community.postgresql.postgresql
remote_management.dellemc.dellemc_idrac:
redirect: dellemc.openmanage.dellemc_idrac
remote_management.dellemc.ome: remote_management.dellemc.ome:
redirect: dellemc.openmanage.ome redirect: dellemc.openmanage.ome
postgresql:
redirect: community.postgresql.postgresql
callback: callback:
actionable: actionable:
tombstone: tombstone:
removal_version: 2.0.0 removal_version: 2.0.0
warning_text: Use the 'default' callback plugin with 'display_skipped_hosts warning_text: Use the 'default' callback plugin with 'display_skipped_hosts = no' and 'display_ok_hosts = no' options.
= no' and 'display_ok_hosts = no' options.
full_skip: full_skip:
tombstone: tombstone:
removal_version: 2.0.0 removal_version: 2.0.0
warning_text: Use the 'default' callback plugin with 'display_skipped_hosts warning_text: Use the 'default' callback plugin with 'display_skipped_hosts = no' option.
= no' option.
stderr: stderr:
tombstone: tombstone:
removal_version: 2.0.0 removal_version: 2.0.0
warning_text: Use the 'default' callback plugin with 'display_failed_stderr warning_text: Use the 'default' callback plugin with 'display_failed_stderr = yes' option.
= yes' option.
inventory: inventory:
docker_machine: docker_machine:
redirect: community.docker.docker_machine redirect: community.docker.docker_machine

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2020, quidame <quidame@poivron.org> # Copyright: (c) 2020, quidame <quidame@poivron.org>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
@@ -8,7 +7,7 @@ __metaclass__ = type
import time import time
from ansible.plugins.action import ActionBase from ansible.plugins.action import ActionBase
from ansible.errors import AnsibleActionFail, AnsibleConnectionFailure from ansible.errors import AnsibleError, AnsibleActionFail, AnsibleConnectionFailure
from ansible.utils.vars import merge_hash from ansible.utils.vars import merge_hash
from ansible.utils.display import Display from ansible.utils.display import Display
@@ -41,27 +40,19 @@ class ActionModule(ActionBase):
"(=%s) to 0, and 'async' (=%s) to a value >2 and not greater than " "(=%s) to 0, and 'async' (=%s) to a value >2 and not greater than "
"'ansible_timeout' (=%s) (recommended).") "'ansible_timeout' (=%s) (recommended).")
def _async_result(self, async_status_args, task_vars, timeout): def _async_result(self, module_args, task_vars, timeout):
''' '''
Retrieve results of the asynchonous task, and display them in place of Retrieve results of the asynchonous task, and display them in place of
the async wrapper results (those with the ansible_job_id key). the async wrapper results (those with the ansible_job_id key).
''' '''
async_status = self._task.copy()
async_status.args = async_status_args
async_status.action = 'ansible.builtin.async_status'
async_status.async_val = 0
async_action = self._shared_loader_obj.action_loader.get(
async_status.action, task=async_status, connection=self._connection,
play_context=self._play_context, loader=self._loader, templar=self._templar,
shared_loader_obj=self._shared_loader_obj)
if async_status.args['mode'] == 'cleanup':
return async_action.run(task_vars=task_vars)
# At least one iteration is required, even if timeout is 0. # At least one iteration is required, even if timeout is 0.
for dummy in range(max(1, timeout)): for i in range(max(1, timeout)):
async_result = async_action.run(task_vars=task_vars) async_result = self._execute_module(
if async_result.get('finished', 0) == 1: module_name='ansible.builtin.async_status',
module_args=module_args,
task_vars=task_vars,
wrap_async=False)
if async_result['finished'] == 1:
break break
time.sleep(min(1, timeout)) time.sleep(min(1, timeout))
@@ -85,6 +76,7 @@ class ActionModule(ActionBase):
task_async = self._task.async_val task_async = self._task.async_val
check_mode = self._play_context.check_mode check_mode = self._play_context.check_mode
max_timeout = self._connection._play_context.timeout max_timeout = self._connection._play_context.timeout
module_name = self._task.action
module_args = self._task.args module_args = self._task.args
if module_args.get('state', None) == 'restored': if module_args.get('state', None) == 'restored':
@@ -115,7 +107,7 @@ class ActionModule(ActionBase):
# longer on the controller); and set a backup file path. # longer on the controller); and set a backup file path.
module_args['_timeout'] = task_async module_args['_timeout'] = task_async
module_args['_back'] = '%s/iptables.state' % async_dir module_args['_back'] = '%s/iptables.state' % async_dir
async_status_args = dict(mode='status') async_status_args = dict(_async_dir=async_dir)
confirm_cmd = 'rm -f %s' % module_args['_back'] confirm_cmd = 'rm -f %s' % module_args['_back']
starter_cmd = 'touch %s.starter' % module_args['_back'] starter_cmd = 'touch %s.starter' % module_args['_back']
remaining_time = max(task_async, max_timeout) remaining_time = max(task_async, max_timeout)
@@ -141,7 +133,7 @@ class ActionModule(ActionBase):
# The module is aware to not process the main iptables-restore # The module is aware to not process the main iptables-restore
# command before finding (and deleting) the 'starter' cookie on # command before finding (and deleting) the 'starter' cookie on
# the host, so the previous query will not reach ssh timeout. # the host, so the previous query will not reach ssh timeout.
dummy = self._low_level_execute_command(starter_cmd, sudoable=self.DEFAULT_SUDOABLE) garbage = self._low_level_execute_command(starter_cmd, sudoable=self.DEFAULT_SUDOABLE)
# As the main command is not yet executed on the target, here # As the main command is not yet executed on the target, here
# 'finished' means 'failed before main command be executed'. # 'finished' means 'failed before main command be executed'.
@@ -151,7 +143,7 @@ class ActionModule(ActionBase):
except AttributeError: except AttributeError:
pass pass
for dummy in range(max_timeout): for x in range(max_timeout):
time.sleep(1) time.sleep(1)
remaining_time -= 1 remaining_time -= 1
# - AnsibleConnectionFailure covers rejected requests (i.e. # - AnsibleConnectionFailure covers rejected requests (i.e.
@@ -159,7 +151,7 @@ class ActionModule(ActionBase):
# - ansible_timeout is able to cover dropped requests (due # - ansible_timeout is able to cover dropped requests (due
# to a rule or policy DROP) if not lower than async_val. # to a rule or policy DROP) if not lower than async_val.
try: try:
dummy = self._low_level_execute_command(confirm_cmd, sudoable=self.DEFAULT_SUDOABLE) garbage = self._low_level_execute_command(confirm_cmd, sudoable=self.DEFAULT_SUDOABLE)
break break
except AnsibleConnectionFailure: except AnsibleConnectionFailure:
continue continue
@@ -172,12 +164,16 @@ class ActionModule(ActionBase):
del result[key] del result[key]
if result.get('invocation', {}).get('module_args'): if result.get('invocation', {}).get('module_args'):
for key in ('_back', '_timeout', '_async_dir', 'jid'): if '_timeout' in result['invocation']['module_args']:
if result['invocation']['module_args'].get(key): del result['invocation']['module_args']['_back']
del result['invocation']['module_args'][key] del result['invocation']['module_args']['_timeout']
async_status_args['mode'] = 'cleanup' async_status_args['mode'] = 'cleanup'
dummy = self._async_result(async_status_args, task_vars, 0) garbage = self._execute_module(
module_name='ansible.builtin.async_status',
module_args=async_status_args,
task_vars=task_vars,
wrap_async=False)
if not wrap_async: if not wrap_async:
# remove a temporary path we created # remove a temporary path we created

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2020, Amin Vakil <info@aminvakil.com> # Copyright: (c) 2020, Amin Vakil <info@aminvakil.com>
# Copyright: (c) 2016-2018, Matt Davis <mdavis@ansible.com> # Copyright: (c) 2016-2018, Matt Davis <mdavis@ansible.com>
# Copyright: (c) 2018, Sam Doran <sdoran@redhat.com> # Copyright: (c) 2018, Sam Doran <sdoran@redhat.com>
@@ -8,7 +7,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type __metaclass__ = type
from ansible.errors import AnsibleError, AnsibleConnectionFailure from ansible.errors import AnsibleError, AnsibleConnectionFailure
from ansible.module_utils.common.text.converters import to_native, to_text from ansible.module_utils._text import to_native, to_text
from ansible.module_utils.common.collections import is_string from ansible.module_utils.common.collections import is_string
from ansible.plugins.action import ActionBase from ansible.plugins.action import ActionBase
from ansible.utils.display import Display from ansible.utils.display import Display

View File

@@ -9,7 +9,7 @@ DOCUMENTATION = '''
short_description: Do As user short_description: Do As user
description: description:
- This become plugins allows your remote/login user to execute commands as another user via the doas utility. - This become plugins allows your remote/login user to execute commands as another user via the doas utility.
author: Ansible Core Team author: ansible (@core)
options: options:
become_user: become_user:
description: User you 'become' to execute the task description: User you 'become' to execute the task
@@ -81,7 +81,7 @@ DOCUMENTATION = '''
import re import re
from ansible.module_utils.common.text.converters import to_bytes from ansible.module_utils._text import to_bytes
from ansible.plugins.become import BecomeBase from ansible.plugins.become import BecomeBase

View File

@@ -8,7 +8,7 @@ DOCUMENTATION = '''
short_description: Centrify's Direct Authorize short_description: Centrify's Direct Authorize
description: description:
- This become plugins allows your remote/login user to execute commands as another user via the dzdo utility. - This become plugins allows your remote/login user to execute commands as another user via the dzdo utility.
author: Ansible Core Team author: ansible (@core)
options: options:
become_user: become_user:
description: User you 'become' to execute the task description: User you 'become' to execute the task

View File

@@ -9,7 +9,7 @@ DOCUMENTATION = '''
short_description: Kerberos substitute user short_description: Kerberos substitute user
description: description:
- This become plugins allows your remote/login user to execute commands as another user via the ksu utility. - This become plugins allows your remote/login user to execute commands as another user via the ksu utility.
author: Ansible Core Team author: ansible (@core)
options: options:
become_user: become_user:
description: User you 'become' to execute the task description: User you 'become' to execute the task
@@ -82,7 +82,7 @@ DOCUMENTATION = '''
import re import re
from ansible.module_utils.common.text.converters import to_bytes from ansible.module_utils._text import to_bytes
from ansible.plugins.become import BecomeBase from ansible.plugins.become import BecomeBase

View File

@@ -9,7 +9,7 @@ DOCUMENTATION = '''
short_description: Systemd's machinectl privilege escalation short_description: Systemd's machinectl privilege escalation
description: description:
- This become plugins allows your remote/login user to execute commands as another user via the machinectl utility. - This become plugins allows your remote/login user to execute commands as another user via the machinectl utility.
author: Ansible Core Team author: ansible (@core)
options: options:
become_user: become_user:
description: User you 'become' to execute the task description: User you 'become' to execute the task

View File

@@ -9,7 +9,7 @@ DOCUMENTATION = '''
short_description: PowerBroker run short_description: PowerBroker run
description: description:
- This become plugins allows your remote/login user to execute commands as another user via the pbrun utility. - This become plugins allows your remote/login user to execute commands as another user via the pbrun utility.
author: Ansible Core Team author: ansible (@core)
options: options:
become_user: become_user:
description: User you 'become' to execute the task description: User you 'become' to execute the task

View File

@@ -9,7 +9,7 @@ DOCUMENTATION = '''
short_description: profile based execution short_description: profile based execution
description: description:
- This become plugins allows your remote/login user to execute commands as another user via the pfexec utility. - This become plugins allows your remote/login user to execute commands as another user via the pfexec utility.
author: Ansible Core Team author: ansible (@core)
options: options:
become_user: become_user:
description: description:

View File

@@ -9,7 +9,7 @@ DOCUMENTATION = '''
short_description: Privilege Manager run short_description: Privilege Manager run
description: description:
- This become plugins allows your remote/login user to execute commands as another user via the pmrun utility. - This become plugins allows your remote/login user to execute commands as another user via the pmrun utility.
author: Ansible Core Team author: ansible (@core)
options: options:
become_exe: become_exe:
description: Sudo executable description: Sudo executable

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# (c) 2014, Brian Coca, Josh Drake, et al # (c) 2014, Brian Coca, Josh Drake, et al
# (c) 2017 Ansible Project # (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
@@ -20,7 +19,6 @@ DOCUMENTATION = '''
- List of connection information for the memcached DBs - List of connection information for the memcached DBs
default: ['127.0.0.1:11211'] default: ['127.0.0.1:11211']
type: list type: list
elements: string
env: env:
- name: ANSIBLE_CACHE_PLUGIN_CONNECTION - name: ANSIBLE_CACHE_PLUGIN_CONNECTION
ini: ini:
@@ -155,12 +153,12 @@ class CacheModuleKeys(MutableSet):
def __len__(self): def __len__(self):
return len(self._keyset) return len(self._keyset)
def add(self, value): def add(self, key):
self._keyset[value] = time.time() self._keyset[key] = time.time()
self._cache.set(self.PREFIX, self._keyset) self._cache.set(self.PREFIX, self._keyset)
def discard(self, value): def discard(self, key):
del self._keyset[value] del self._keyset[key]
self._cache.set(self.PREFIX, self._keyset) self._cache.set(self.PREFIX, self._keyset)
def remove_by_timerange(self, s_min, s_max): def remove_by_timerange(self, s_min, s_max):

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# (c) 2017, Brian Coca # (c) 2017, Brian Coca
# (c) 2017 Ansible Project # (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# (c) 2014, Brian Coca, Josh Drake, et al # (c) 2014, Brian Coca, Josh Drake, et al
# (c) 2017 Ansible Project # (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
@@ -62,13 +61,12 @@ DOCUMENTATION = '''
type: integer type: integer
''' '''
import re
import time import time
import json import json
from ansible import constants as C from ansible import constants as C
from ansible.errors import AnsibleError from ansible.errors import AnsibleError
from ansible.module_utils.common.text.converters import to_native from ansible.module_utils._text import to_native
from ansible.parsing.ajson import AnsibleJSONEncoder, AnsibleJSONDecoder from ansible.parsing.ajson import AnsibleJSONEncoder, AnsibleJSONDecoder
from ansible.plugins.cache import BaseCacheModule from ansible.plugins.cache import BaseCacheModule
from ansible.release import __version__ as ansible_base_version from ansible.release import __version__ as ansible_base_version
@@ -93,8 +91,6 @@ class CacheModule(BaseCacheModule):
performance. performance.
""" """
_sentinel_service_name = None _sentinel_service_name = None
re_url_conn = re.compile(r'^([^:]+|\[[^]]+\]):(\d+):(\d+)(?::(.*))?$')
re_sent_conn = re.compile(r'^(.*):(\d+)$')
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
uri = '' uri = ''
@@ -134,18 +130,11 @@ class CacheModule(BaseCacheModule):
self._db = self._get_sentinel_connection(uri, kw) self._db = self._get_sentinel_connection(uri, kw)
# normal connection # normal connection
else: else:
connection = self._parse_connection(self.re_url_conn, uri) connection = uri.split(':')
self._db = StrictRedis(*connection, **kw) self._db = StrictRedis(*connection, **kw)
display.vv('Redis connection: %s' % self._db) display.vv('Redis connection: %s' % self._db)
@staticmethod
def _parse_connection(re_patt, uri):
match = re_patt.match(uri)
if not match:
raise AnsibleError("Unable to parse connection string")
return match.groups()
def _get_sentinel_connection(self, uri, kw): def _get_sentinel_connection(self, uri, kw):
""" """
get sentinel connection details from _uri get sentinel connection details from _uri
@@ -169,7 +158,7 @@ class CacheModule(BaseCacheModule):
except IndexError: except IndexError:
pass # password is optional pass # password is optional
sentinels = [self._parse_connection(self.re_sent_conn, shost) for shost in connections] sentinels = [tuple(shost.split(':')) for shost in connections]
display.vv('\nUsing redis sentinels: %s' % sentinels) display.vv('\nUsing redis sentinels: %s' % sentinels)
scon = Sentinel(sentinels, **kw) scon = Sentinel(sentinels, **kw)
try: try:

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# (c) 2017, Brian Coca # (c) 2017, Brian Coca
# (c) 2017 Ansible Project # (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# (C) 2012, Michael DeHaan, <michael.dehaan@gmail.com> # (C) 2012, Michael DeHaan, <michael.dehaan@gmail.com>
# (c) 2017 Ansible Project # (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# (c) 2018, Ivan Aragones Muniesa <ivan.aragones.muniesa@gmail.com> # (c) 2018, Ivan Aragones Muniesa <ivan.aragones.muniesa@gmail.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
''' '''
@@ -45,8 +44,6 @@ class CallbackModule(CallbackBase):
_task_total = 0 _task_total = 0
_host_counter = 1 _host_counter = 1
_host_total = 0 _host_total = 0
_current_batch_total = 0
_previous_batch_total = 0
def __init__(self): def __init__(self):
super(CallbackModule, self).__init__() super(CallbackModule, self).__init__()
@@ -78,11 +75,8 @@ class CallbackModule(CallbackBase):
self._display.banner(msg) self._display.banner(msg)
self._play = play self._play = play
self._previous_batch_total = self._current_batch_total
self._current_batch_total = self._previous_batch_total + len(self._all_vars()['vars']['ansible_play_batch'])
self._host_total = len(self._all_vars()['vars']['ansible_play_hosts_all']) self._host_total = len(self._all_vars()['vars']['ansible_play_hosts_all'])
self._task_total = len(self._play.get_tasks()[0]) self._task_total = len(self._play.get_tasks()[0])
self._task_counter = 1
def v2_playbook_on_stats(self, stats): def v2_playbook_on_stats(self, stats):
self._display.banner("PLAY RECAP") self._display.banner("PLAY RECAP")
@@ -150,7 +144,7 @@ class CallbackModule(CallbackBase):
path = task.get_path() path = task.get_path()
if path: if path:
self._display.display("task path: %s" % path, color=C.COLOR_DEBUG) self._display.display("task path: %s" % path, color=C.COLOR_DEBUG)
self._host_counter = self._previous_batch_total self._host_counter = 0
self._task_counter += 1 self._task_counter += 1
def v2_runner_on_ok(self, result): def v2_runner_on_ok(self, result):

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# (c) 2016, Dag Wieers <dag@wieers.com> # (c) 2016, Dag Wieers <dag@wieers.com>
# (c) 2017 Ansible Project # (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

View File

@@ -792,7 +792,7 @@ from ansible.utils.color import colorize, hostcolor
from ansible.template import Templar from ansible.template import Templar
from ansible.vars.manager import VariableManager from ansible.vars.manager import VariableManager
from ansible.plugins.callback.default import CallbackModule as Default from ansible.plugins.callback.default import CallbackModule as Default
from ansible.module_utils.common.text.converters import to_text from ansible.module_utils._text import to_text
class DummyStdout(object): class DummyStdout(object):

View File

@@ -1,423 +0,0 @@
# (C) 2021, Victor Martinez <VictorMartinezRubio@gmail.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
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:
- 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 = '''
examples: |
Enable the plugin in ansible.cfg:
[defaults]
callbacks_enabled = community.general.elastic
Set the environment variable:
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
import time
import uuid
from collections import OrderedDict
from os.path import basename
from ansible.errors import AnsibleError, AnsibleRuntimeError
from ansible.module_utils.six import raise_from
from ansible.plugins.callback import CallbackBase
try:
from elasticapm import Client, capture_span, trace_parent_from_string, instrument, label
except ImportError as imp_exc:
ELASTIC_LIBRARY_IMPORT_ERROR = imp_exc
else:
ELASTIC_LIBRARY_IMPORT_ERROR = None
class TaskData:
"""
Data about an individual task.
"""
def __init__(self, uuid, name, path, play, action, args):
self.uuid = uuid
self.name = name
self.path = path
self.play = play
self.host_data = OrderedDict()
self.start = time.time()
self.action = action
self.args = args
def add_host(self, host):
if host.uuid in self.host_data:
if host.status == 'included':
# concatenate task include output from multiple items
host.result = '%s\n%s' % (self.host_data[host.uuid].result, host.result)
else:
return
self.host_data[host.uuid] = host
class HostData:
"""
Data about an individual host.
"""
def __init__(self, uuid, name, status, result):
self.uuid = uuid
self.name = name
self.status = status
self.result = result
self.finish = time.time()
class ElasticSource(object):
def __init__(self, display):
self.ansible_playbook = ""
self.ansible_version = None
self.session = str(uuid.uuid4())
self.host = socket.gethostname()
try:
self.ip_address = socket.gethostbyname(socket.gethostname())
except Exception as e:
self.ip_address = None
self.user = getpass.getuser()
self._display = display
def start_task(self, tasks_data, hide_task_arguments, play_name, task):
""" record the start of a task for one or more hosts """
uuid = task._uuid
if uuid in tasks_data:
return
name = task.get_name().strip()
path = task.get_path()
action = task.action
args = None
if not task.no_log and not hide_task_arguments:
args = ', '.join(('%s=%s' % a for a in task.args.items()))
tasks_data[uuid] = TaskData(uuid, name, path, play_name, action, args)
def finish_task(self, tasks_data, status, result):
""" record the results of a task for a single host """
task_uuid = result._task._uuid
if hasattr(result, '_host') and result._host is not None:
host_uuid = result._host._uuid
host_name = result._host.name
else:
host_uuid = 'include'
host_name = 'include'
task = tasks_data[task_uuid]
if self.ansible_version is None and result._task_fields['args'].get('_ansible_version'):
self.ansible_version = result._task_fields['args'].get('_ansible_version')
task.add_host(HostData(host_uuid, host_name, status, result))
def generate_distributed_traces(self, tasks_data, status, end_time, traceparent, apm_service_name,
apm_server_url, apm_verify_server_cert, apm_secret_token, apm_api_key):
""" generate distributed traces from the collected TaskData and HostData """
tasks = []
parent_start_time = None
for task_uuid, task in tasks_data.items():
if parent_start_time is None:
parent_start_time = task.start
tasks.append(task)
apm_cli = self.init_apm_client(apm_server_url, apm_service_name, apm_verify_server_cert, apm_secret_token, apm_api_key)
if apm_cli:
instrument() # Only call this once, as early as possible.
if traceparent:
parent = trace_parent_from_string(traceparent)
apm_cli.begin_transaction("Session", trace_parent=parent, start=parent_start_time)
else:
apm_cli.begin_transaction("Session", start=parent_start_time)
# Populate trace metadata attributes
if self.ansible_version is not None:
label(ansible_version=self.ansible_version)
label(ansible_session=self.session, ansible_host_name=self.host, ansible_host_user=self.user)
if self.ip_address is not None:
label(ansible_host_ip=self.ip_address)
for task_data in tasks:
for host_uuid, host_data in task_data.host_data.items():
self.create_span_data(apm_cli, task_data, host_data)
apm_cli.end_transaction(name=__name__, result=status, duration=end_time - parent_start_time)
def create_span_data(self, apm_cli, task_data, host_data):
""" create the span with the given TaskData and HostData """
name = '[%s] %s: %s' % (host_data.name, task_data.play, task_data.name)
message = "success"
status = "success"
enriched_error_message = None
if host_data.status == 'included':
rc = 0
else:
res = host_data.result._result
rc = res.get('rc', 0)
if host_data.status == 'failed':
message = self.get_error_message(res)
enriched_error_message = self.enrich_error_message(res)
status = "failure"
elif host_data.status == 'skipped':
if 'skip_reason' in res:
message = res['skip_reason']
else:
message = 'skipped'
status = "unknown"
with capture_span(task_data.name,
start=task_data.start,
span_type="ansible.task.run",
duration=host_data.finish - task_data.start,
labels={"ansible.task.args": task_data.args,
"ansible.task.message": message,
"ansible.task.module": task_data.action,
"ansible.task.name": name,
"ansible.task.result": rc,
"ansible.task.host.name": host_data.name,
"ansible.task.host.status": host_data.status}) as span:
span.outcome = status
if 'failure' in status:
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):
if apm_server_url:
return Client(service_name=apm_service_name,
server_url=apm_server_url,
verify_server_cert=False,
secret_token=apm_secret_token,
api_key=apm_api_key,
use_elastic_traceparent_header=True,
debug=True)
@staticmethod
def get_error_message(result):
if result.get('exception') is not None:
return ElasticSource._last_line(result['exception'])
return result.get('msg', 'failed')
@staticmethod
def _last_line(text):
lines = text.strip().split('\n')
return lines[-1]
@staticmethod
def enrich_error_message(result):
message = result.get('msg', 'failed')
exception = result.get('exception')
stderr = result.get('stderr')
return ('message: "{0}"\nexception: "{1}"\nstderr: "{2}"').format(message, exception, stderr)
class CallbackModule(CallbackBase):
"""
This callback creates distributed traces with Elastic APM.
"""
CALLBACK_VERSION = 2.0
CALLBACK_TYPE = 'notification'
CALLBACK_NAME = 'community.general.elastic'
CALLBACK_NEEDS_ENABLED = True
def __init__(self, display=None):
super(CallbackModule, self).__init__(display=display)
self.hide_task_arguments = None
self.apm_service_name = None
self.ansible_playbook = None
self.traceparent = False
self.play_name = None
self.tasks_data = None
self.errors = 0
self.disabled = False
if ELASTIC_LIBRARY_IMPORT_ERROR:
raise_from(
AnsibleError('The `elastic-apm` must be installed to use this plugin'),
ELASTIC_LIBRARY_IMPORT_ERROR)
self.tasks_data = OrderedDict()
self.elastic = ElasticSource(display=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)
self.hide_task_arguments = self.get_option('hide_task_arguments')
self.apm_service_name = self.get_option('apm_service_name')
if not self.apm_service_name:
self.apm_service_name = 'ansible'
self.apm_server_url = self.get_option('apm_server_url')
self.apm_secret_token = self.get_option('apm_secret_token')
self.apm_api_key = self.get_option('apm_api_key')
self.apm_verify_server_cert = self.get_option('apm_verify_server_cert')
self.traceparent = self.get_option('traceparent')
def v2_playbook_on_start(self, playbook):
self.ansible_playbook = basename(playbook._file_name)
def v2_playbook_on_play_start(self, play):
self.play_name = play.get_name()
def v2_runner_on_no_hosts(self, task):
self.elastic.start_task(
self.tasks_data,
self.hide_task_arguments,
self.play_name,
task
)
def v2_playbook_on_task_start(self, task, is_conditional):
self.elastic.start_task(
self.tasks_data,
self.hide_task_arguments,
self.play_name,
task
)
def v2_playbook_on_cleanup_task_start(self, task):
self.elastic.start_task(
self.tasks_data,
self.hide_task_arguments,
self.play_name,
task
)
def v2_playbook_on_handler_task_start(self, task):
self.elastic.start_task(
self.tasks_data,
self.hide_task_arguments,
self.play_name,
task
)
def v2_runner_on_failed(self, result, ignore_errors=False):
self.errors += 1
self.elastic.finish_task(
self.tasks_data,
'failed',
result
)
def v2_runner_on_ok(self, result):
self.elastic.finish_task(
self.tasks_data,
'ok',
result
)
def v2_runner_on_skipped(self, result):
self.elastic.finish_task(
self.tasks_data,
'skipped',
result
)
def v2_playbook_on_include(self, included_file):
self.elastic.finish_task(
self.tasks_data,
'included',
included_file
)
def v2_playbook_on_stats(self, stats):
if self.errors == 0:
status = "success"
else:
status = "failure"
self.elastic.generate_distributed_traces(
self.tasks_data,
status,
time.time(),
self.traceparent,
self.apm_service_name,
self.apm_server_url,
self.apm_verify_server_cert,
self.apm_secret_token,
self.apm_api_key
)
def v2_runner_on_async_failed(self, result, **kwargs):
self.errors += 1

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# (C) 2014, Matt Martz <matt@sivel.net> # (C) 2014, Matt Martz <matt@sivel.net>
# (c) 2017 Ansible Project # (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2016 maxn nikolaev.makc@gmail.com # Copyright (C) 2016 maxn nikolaev.makc@gmail.com
# Copyright (c) 2017 Ansible Project # Copyright (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# (C) 2012, Michael DeHaan, <michael.dehaan@gmail.com> # (C) 2012, Michael DeHaan, <michael.dehaan@gmail.com>
# (c) 2017 Ansible Project # (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
@@ -32,7 +31,7 @@ import time
import json import json
from ansible.utils.path import makedirs_safe from ansible.utils.path import makedirs_safe
from ansible.module_utils.common.text.converters import to_bytes from ansible.module_utils._text import to_bytes
from ansible.module_utils.common._collections_compat import MutableMapping from ansible.module_utils.common._collections_compat import MutableMapping
from ansible.parsing.ajson import AnsibleJSONEncoder from ansible.parsing.ajson import AnsibleJSONEncoder
from ansible.plugins.callback import CallbackBase from ansible.plugins.callback import CallbackBase

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function) from __future__ import (absolute_import, division, print_function)

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# (c) 2018, Samir Musali <samir.musali@logdna.com> # (c) 2018, Samir Musali <samir.musali@logdna.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
@@ -78,7 +77,7 @@ def get_mac():
# Getting hostname of system: # Getting hostname of system:
def get_hostname(): def get_hostname():
return str(socket.gethostname()).split('.local', 1)[0] return str(socket.gethostname()).split('.local')[0]
# Getting IP of system: # Getting IP of system:

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# (c) 2015, Logentries.com, Jimmy Tang <jimmy.tang@logentries.com> # (c) 2015, Logentries.com, Jimmy Tang <jimmy.tang@logentries.com>
# (c) 2017 Ansible Project # (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
@@ -112,7 +111,7 @@ try:
except ImportError: except ImportError:
HAS_FLATDICT = False HAS_FLATDICT = False
from ansible.module_utils.common.text.converters import to_bytes, to_text from ansible.module_utils._text import to_bytes, to_text
from ansible.plugins.callback import CallbackBase from ansible.plugins.callback import CallbackBase
# Todo: # Todo:

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# (C) 2020, Yevhen Khmelenko <ujenmr@gmail.com> # (C) 2020, Yevhen Khmelenko <ujenmr@gmail.com>
# (C) 2017 Ansible Project # (C) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
@@ -94,7 +93,6 @@ ansible.cfg: |
import os import os
import json import json
from ansible import context
import socket import socket
import uuid import uuid
import logging import logging
@@ -153,11 +151,11 @@ class CallbackModule(CallbackBase):
self.base_data['ansible_pre_command_output'] = os.popen( self.base_data['ansible_pre_command_output'] = os.popen(
self.ls_pre_command).read() self.ls_pre_command).read()
if context.CLIARGS is not None: if self._options is not None:
self.base_data['ansible_checkmode'] = context.CLIARGS.get('check') self.base_data['ansible_checkmode'] = self._options.check
self.base_data['ansible_tags'] = context.CLIARGS.get('tags') self.base_data['ansible_tags'] = self._options.tags
self.base_data['ansible_skip_tags'] = context.CLIARGS.get('skip_tags') self.base_data['ansible_skip_tags'] = self._options.skip_tags
self.base_data['inventory'] = context.CLIARGS.get('inventory') self.base_data['inventory'] = self._options.inventory
def set_options(self, task_keys=None, var_options=None, direct=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) super(CallbackModule, self).set_options(task_keys=task_keys, var_options=var_options, direct=direct)

View File

@@ -11,16 +11,14 @@ name: mail
type: notification type: notification
short_description: Sends failure events via email short_description: Sends failure events via email
description: description:
- This callback will report failures via email. - This callback will report failures via email
author: author:
- Dag Wieers (@dagwieers) - Dag Wieers (@dagwieers)
requirements: requirements:
- whitelisting in configuration - whitelisting in configuration
options: options:
mta: mta:
description: description: Mail Transfer Agent, server that accepts SMTP
- Mail Transfer Agent, server that accepts SMTP.
type: str
env: env:
- name: SMTPHOST - name: SMTPHOST
ini: ini:
@@ -28,57 +26,43 @@ options:
key: smtphost key: smtphost
default: localhost default: localhost
mtaport: mtaport:
description: description: Mail Transfer Agent Port, port at which server SMTP
- Mail Transfer Agent Port.
- Port at which server SMTP.
type: int
ini: ini:
- section: callback_mail - section: callback_mail
key: smtpport key: smtpport
default: 25 default: 25
to: to:
description: description: Mail recipient
- Mail recipient.
type: list
elements: str
ini: ini:
- section: callback_mail - section: callback_mail
key: to key: to
default: [root] default: root
sender: sender:
description: description: Mail sender
- Mail sender.
- Note that this will be required from community.general 6.0.0 on.
type: str
ini: ini:
- section: callback_mail - section: callback_mail
key: sender key: sender
cc: cc:
description: description: CC'd recipient
- CC'd recipients.
type: list
elements: str
ini: ini:
- section: callback_mail - section: callback_mail
key: cc key: cc
bcc: bcc:
description: description: BCC'd recipient
- BCC'd recipients.
type: list
elements: str
ini: ini:
- section: callback_mail - section: callback_mail
key: bcc key: bcc
notes:
- "TODO: expand configuration options now that plugins can leverage Ansible's configuration"
''' '''
import json import json
import os import os
import re import re
import email.utils
import smtplib import smtplib
from ansible.module_utils.six import string_types from ansible.module_utils.six import string_types
from ansible.module_utils.common.text.converters import to_bytes from ansible.module_utils._text import to_bytes
from ansible.parsing.ajson import AnsibleJSONEncoder from ansible.parsing.ajson import AnsibleJSONEncoder
from ansible.plugins.callback import CallbackBase from ansible.plugins.callback import CallbackBase
@@ -104,13 +88,9 @@ class CallbackModule(CallbackBase):
super(CallbackModule, self).set_options(task_keys=task_keys, var_options=var_options, direct=direct) super(CallbackModule, self).set_options(task_keys=task_keys, var_options=var_options, direct=direct)
self.sender = self.get_option('sender') self.sender = self.get_option('sender')
if self.sender is None:
self._display.deprecated(
'The sender for the mail callback has not been specified. This will be an error in the future',
version='6.0.0', collection_name='community.general')
self.to = self.get_option('to') self.to = self.get_option('to')
self.smtphost = self.get_option('mta') self.smtphost = self.get_option('mta')
self.smtpport = self.get_option('mtaport') self.smtpport = int(self.get_option('mtaport'))
self.cc = self.get_option('cc') self.cc = self.get_option('cc')
self.bcc = self.get_option('bcc') self.bcc = self.get_option('bcc')
@@ -120,34 +100,28 @@ class CallbackModule(CallbackBase):
smtp = smtplib.SMTP(self.smtphost, port=self.smtpport) smtp = smtplib.SMTP(self.smtphost, port=self.smtpport)
sender_address = email.utils.parseaddr(self.sender) b_sender = to_bytes(self.sender)
if self.to: b_to = to_bytes(self.to)
to_addresses = email.utils.getaddresses(self.to) b_cc = to_bytes(self.cc)
b_bcc = to_bytes(self.bcc)
b_subject = to_bytes(subject)
b_body = to_bytes(body)
b_content = b'From: %s\n' % b_sender
b_content += b'To: %s\n' % b_to
if self.cc: if self.cc:
cc_addresses = email.utils.getaddresses(self.cc) b_content += b'Cc: %s\n' % b_cc
b_content += b'Subject: %s\n\n' % b_subject
b_content += b_body
b_addresses = b_to.split(b',')
if self.cc:
b_addresses += b_cc.split(b',')
if self.bcc: if self.bcc:
bcc_addresses = email.utils.getaddresses(self.bcc) b_addresses += b_bcc.split(b',')
content = 'Date: %s\n' % email.utils.formatdate() for b_address in b_addresses:
content += 'From: %s\n' % email.utils.formataddr(sender_address) smtp.sendmail(b_sender, b_address, b_content)
if self.to:
content += 'To: %s\n' % ', '.join([email.utils.formataddr(pair) for pair in to_addresses])
if self.cc:
content += 'Cc: %s\n' % ', '.join([email.utils.formataddr(pair) for pair in cc_addresses])
content += 'Message-ID: %s\n' % email.utils.make_msgid()
content += 'Subject: %s\n\n' % subject.strip()
content += body
addresses = to_addresses
if self.cc:
addresses += cc_addresses
if self.bcc:
addresses += bcc_addresses
if not addresses:
self._display.warning('No receiver has been specified for the mail callback plugin.')
smtp.sendmail(self.sender, [address for name, address in addresses], to_bytes(content))
smtp.quit() smtp.quit()

View File

@@ -10,23 +10,22 @@ DOCUMENTATION = '''
name: nrdp name: nrdp
type: notification type: notification
author: "Remi VERCHERE (@rverchere)" author: "Remi VERCHERE (@rverchere)"
short_description: Post task results to a Nagios server through nrdp short_description: post task result to a nagios server through nrdp
description: description:
- This callback send playbook result to Nagios. - this callback send playbook result to nagios
- Nagios shall use NRDP to recive passive events. - nagios shall use NRDP to recive passive events
- The passive check is sent to a dedicated host/service for Ansible. - the passive check is sent to a dedicated host/service for ansible
options: options:
url: url:
description: URL of the nrdp server. description: url of the nrdp server
required: true required: True
env: env:
- name : NRDP_URL - name : NRDP_URL
ini: ini:
- section: callback_nrdp - section: callback_nrdp
key: url key: url
type: string
validate_certs: validate_certs:
description: Validate the SSL certificate of the nrdp server. (Used for HTTPS URLs.) description: (bool) validate the SSL certificate of the nrdp server. (For HTTPS url)
env: env:
- name: NRDP_VALIDATE_CERTS - name: NRDP_VALIDATE_CERTS
ini: ini:
@@ -34,43 +33,38 @@ DOCUMENTATION = '''
key: validate_nrdp_certs key: validate_nrdp_certs
- section: callback_nrdp - section: callback_nrdp
key: validate_certs key: validate_certs
type: boolean default: False
default: false
aliases: [ validate_nrdp_certs ] aliases: [ validate_nrdp_certs ]
token: token:
description: Token to be allowed to push nrdp events. description: token to be allowed to push nrdp events
required: true required: True
env: env:
- name: NRDP_TOKEN - name: NRDP_TOKEN
ini: ini:
- section: callback_nrdp - section: callback_nrdp
key: token key: token
type: string
hostname: hostname:
description: Hostname where the passive check is linked to. description: hostname where the passive check is linked to
required: true required: True
env: env:
- name : NRDP_HOSTNAME - name : NRDP_HOSTNAME
ini: ini:
- section: callback_nrdp - section: callback_nrdp
key: hostname key: hostname
type: string
servicename: servicename:
description: Service where the passive check is linked to. description: service where the passive check is linked to
required: true required: True
env: env:
- name : NRDP_SERVICENAME - name : NRDP_SERVICENAME
ini: ini:
- section: callback_nrdp - section: callback_nrdp
key: servicename key: servicename
type: string
''' '''
import os import os
import json import json
from ansible.module_utils.six.moves.urllib.parse import urlencode from ansible.module_utils.six.moves.urllib.parse import urlencode
from ansible.module_utils.common.text.converters import to_bytes
from ansible.module_utils.urls import open_url from ansible.module_utils.urls import open_url
from ansible.plugins.callback import CallbackBase from ansible.plugins.callback import CallbackBase
@@ -144,7 +138,7 @@ class CallbackModule(CallbackBase):
body = { body = {
'cmd': 'submitcheck', 'cmd': 'submitcheck',
'token': self.token, 'token': self.token,
'XMLDATA': to_bytes(xmldata) 'XMLDATA': bytes(xmldata)
} }
try: try:

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# (c) 2017 Ansible Project # (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

View File

@@ -1,515 +0,0 @@
# -*- coding: utf-8 -*-
# (C) 2021, Victor Martinez <VictorMartinezRubio@gmail.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
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:
- 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
enable_from_environment:
type: str
description:
- Whether to enable this callback only if the given environment variable exists and it is set to C(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 I(enable_from_environment) value as environment variable
and if set to true this plugin will be enabled.
env:
- name: ANSIBLE_OPENTELEMETRY_ENABLE_FROM_ENVIRONMENT
version_added: 3.8.0
otel_service_name:
default: ansible
type: str
description:
- The service name resource attribute.
env:
- name: OTEL_SERVICE_NAME
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
requirements:
- opentelemetry-api (Python library)
- opentelemetry-exporter-otlp (Python library)
- opentelemetry-sdk (Python library)
'''
EXAMPLES = '''
examples: |
Enable the plugin in ansible.cfg:
[defaults]
callbacks_enabled = community.general.opentelemetry
Set the environment variable:
export OTEL_EXPORTER_OTLP_ENDPOINT=<your endpoint (OTLP/HTTP)>
export OTEL_EXPORTER_OTLP_HEADERS="authorization=Bearer your_otel_token"
export OTEL_SERVICE_NAME=your_service_name
'''
import getpass
import os
import socket
import sys
import time
import uuid
from collections import OrderedDict
from os.path import basename
from ansible.errors import AnsibleError
from ansible.module_utils.six import raise_from
from ansible.module_utils.six.moves.urllib.parse import urlparse
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
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
)
from opentelemetry.util._time import _time_ns
except ImportError as imp_exc:
OTEL_LIBRARY_IMPORT_ERROR = imp_exc
else:
OTEL_LIBRARY_IMPORT_ERROR = None
class TaskData:
"""
Data about an individual task.
"""
def __init__(self, uuid, name, path, play, action, args):
self.uuid = uuid
self.name = name
self.path = path
self.play = play
self.host_data = OrderedDict()
if sys.version_info >= (3, 7):
self.start = time.time_ns()
else:
self.start = _time_ns()
self.action = action
self.args = args
def add_host(self, host):
if host.uuid in self.host_data:
if host.status == 'included':
# concatenate task include output from multiple items
host.result = '%s\n%s' % (self.host_data[host.uuid].result, host.result)
else:
return
self.host_data[host.uuid] = host
class HostData:
"""
Data about an individual host.
"""
def __init__(self, uuid, name, status, result):
self.uuid = uuid
self.name = name
self.status = status
self.result = result
if sys.version_info >= (3, 7):
self.finish = time.time_ns()
else:
self.finish = _time_ns()
class OpenTelemetrySource(object):
def __init__(self, display):
self.ansible_playbook = ""
self.ansible_version = None
self.session = str(uuid.uuid4())
self.host = socket.gethostname()
try:
self.ip_address = socket.gethostbyname(socket.gethostname())
except Exception as e:
self.ip_address = None
self.user = getpass.getuser()
self._display = display
def traceparent_context(self, traceparent):
carrier = dict()
carrier['traceparent'] = traceparent
return TraceContextTextMapPropagator().extract(carrier=carrier)
def start_task(self, tasks_data, hide_task_arguments, play_name, task):
""" record the start of a task for one or more hosts """
uuid = task._uuid
if uuid in tasks_data:
return
name = task.get_name().strip()
path = task.get_path()
action = task.action
args = None
if not task.no_log and not hide_task_arguments:
args = task.args
tasks_data[uuid] = TaskData(uuid, name, path, play_name, action, args)
def finish_task(self, tasks_data, status, result):
""" record the results of a task for a single host """
task_uuid = result._task._uuid
if hasattr(result, '_host') and result._host is not None:
host_uuid = result._host._uuid
host_name = result._host.name
else:
host_uuid = 'include'
host_name = 'include'
task = tasks_data[task_uuid]
if self.ansible_version is None and result._task_fields['args'].get('_ansible_version'):
self.ansible_version = result._task_fields['args'].get('_ansible_version')
task.add_host(HostData(host_uuid, host_name, status, result))
def generate_distributed_traces(self, otel_service_name, ansible_playbook, tasks_data, status, traceparent):
""" generate distributed traces from the collected TaskData and HostData """
tasks = []
parent_start_time = None
for task_uuid, task in tasks_data.items():
if parent_start_time is None:
parent_start_time = task.start
tasks.append(task)
trace.set_tracer_provider(
TracerProvider(
resource=Resource.create({SERVICE_NAME: otel_service_name})
)
)
processor = BatchSpanProcessor(OTLPSpanExporter())
trace.get_tracer_provider().add_span_processor(processor)
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span(ansible_playbook, context=self.traceparent_context(traceparent),
start_time=parent_start_time, kind=SpanKind.SERVER) as parent:
parent.set_status(status)
# Populate trace metadata attributes
if self.ansible_version is not None:
parent.set_attribute("ansible.version", self.ansible_version)
parent.set_attribute("ansible.session", self.session)
parent.set_attribute("ansible.host.name", self.host)
if self.ip_address is not None:
parent.set_attribute("ansible.host.ip", self.ip_address)
parent.set_attribute("ansible.host.user", self.user)
for task in tasks:
for host_uuid, host_data in task.host_data.items():
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)
def update_span_data(self, task_data, host_data, span):
""" update the span with the given TaskData and HostData """
name = '[%s] %s: %s' % (host_data.name, task_data.play, task_data.name)
message = 'success'
res = {}
rc = 0
status = Status(status_code=StatusCode.OK)
if host_data.status != 'included':
# Support loops
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)
enriched_error_message = self.enrich_error_message_from_results(host_data.result._result['results'], task_data.action)
else:
res = host_data.result._result
rc = res.get('rc', 0)
message = self.get_error_message(res)
enriched_error_message = self.enrich_error_message(res)
if host_data.status == 'failed':
status = Status(status_code=StatusCode.ERROR, description=message)
# Record an exception with the task message
span.record_exception(BaseException(enriched_error_message))
elif host_data.status == 'skipped':
message = res['skip_reason'] if 'skip_reason' in res else 'skipped'
status = Status(status_code=StatusCode.UNSET)
elif host_data.status == 'ignored':
status = Status(status_code=StatusCode.UNSET)
span.set_status(status)
if isinstance(task_data.args, dict) and "gather_facts" not in task_data.action:
names = tuple(self.transform_ansible_unicode_to_str(k) for k in task_data.args.keys())
values = tuple(self.transform_ansible_unicode_to_str(k) for k in task_data.args.values())
self.set_span_attribute(span, ("ansible.task.args.name"), names)
self.set_span_attribute(span, ("ansible.task.args.value"), values)
self.set_span_attribute(span, "ansible.task.module", task_data.action)
self.set_span_attribute(span, "ansible.task.message", message)
self.set_span_attribute(span, "ansible.task.name", name)
self.set_span_attribute(span, "ansible.task.result", rc)
self.set_span_attribute(span, "ansible.task.host.name", host_data.name)
self.set_span_attribute(span, "ansible.task.host.status", host_data.status)
# This will allow to enrich the service map
self.add_attributes_for_service_map_if_possible(span, task_data)
span.end(end_time=host_data.finish)
def set_span_attribute(self, span, attributeName, attributeValue):
""" update the span attribute with the given attribute and value if not None """
if span is None and self._display is not None:
self._display.warning('span object is None. Please double check if that is expected.')
else:
if attributeValue is not None:
span.set_attribute(attributeName, attributeValue)
def add_attributes_for_service_map_if_possible(self, span, task_data):
"""Update the span attributes with the service that the task interacted with, if possible."""
redacted_url = self.parse_and_redact_url_if_possible(task_data.args)
if redacted_url:
self.set_span_attribute(span, "http.url", redacted_url.geturl())
@staticmethod
def parse_and_redact_url_if_possible(args):
"""Parse and redact the url, if possible."""
try:
parsed_url = urlparse(OpenTelemetrySource.url_from_args(args))
except ValueError:
return None
if OpenTelemetrySource.is_valid_url(parsed_url):
return OpenTelemetrySource.redact_user_password(parsed_url)
return None
@staticmethod
def url_from_args(args):
# the order matters
url_args = ("url", "api_url", "baseurl", "repo", "server_url", "chart_repo_url", "registry_url", "endpoint", "uri", "updates_url")
for arg in url_args:
if args is not None and args.get(arg):
return args.get(arg)
return ""
@staticmethod
def redact_user_password(url):
return url._replace(netloc=url.hostname) if url.password else url
@staticmethod
def is_valid_url(url):
if all([url.scheme, url.netloc, url.hostname]):
return "{{" not in url.hostname
return False
@staticmethod
def transform_ansible_unicode_to_str(value):
parsed_url = urlparse(str(value))
if OpenTelemetrySource.is_valid_url(parsed_url):
return OpenTelemetrySource.redact_user_password(parsed_url).geturl()
return str(value)
@staticmethod
def get_error_message(result):
if result.get('exception') is not None:
return OpenTelemetrySource._last_line(result['exception'])
return result.get('msg', 'failed')
@staticmethod
def get_error_message_from_results(results, action):
for result in results:
if result.get('failed', False):
return ('{0}({1}) - {2}').format(action, result.get('item', 'none'), OpenTelemetrySource.get_error_message(result))
@staticmethod
def _last_line(text):
lines = text.strip().split('\n')
return lines[-1]
@staticmethod
def enrich_error_message(result):
message = result.get('msg', 'failed')
exception = result.get('exception')
stderr = result.get('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 = ('{0}({1}) - {2}\n{3}').format(action, result.get('item', 'none'), OpenTelemetrySource.enrich_error_message(result), message)
return message
class CallbackModule(CallbackBase):
"""
This callback creates distributed traces.
"""
CALLBACK_VERSION = 2.0
CALLBACK_TYPE = 'notification'
CALLBACK_NAME = 'community.general.opentelemetry'
CALLBACK_NEEDS_ENABLED = True
def __init__(self, display=None):
super(CallbackModule, self).__init__(display=display)
self.hide_task_arguments = None
self.otel_service_name = None
self.ansible_playbook = None
self.play_name = None
self.tasks_data = None
self.errors = 0
self.disabled = False
self.traceparent = False
if OTEL_LIBRARY_IMPORT_ERROR:
raise_from(
AnsibleError('The `opentelemetry-api`, `opentelemetry-exporter-otlp` or `opentelemetry-sdk` must be installed to use this plugin'),
OTEL_LIBRARY_IMPORT_ERROR)
self.tasks_data = OrderedDict()
self.opentelemetry = OpenTelemetrySource(display=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)
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("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')
self.otel_service_name = self.get_option('otel_service_name')
if not self.otel_service_name:
self.otel_service_name = 'ansible'
# See https://github.com/open-telemetry/opentelemetry-specification/issues/740
self.traceparent = self.get_option('traceparent')
def v2_playbook_on_start(self, playbook):
self.ansible_playbook = basename(playbook._file_name)
def v2_playbook_on_play_start(self, play):
self.play_name = play.get_name()
def v2_runner_on_no_hosts(self, task):
self.opentelemetry.start_task(
self.tasks_data,
self.hide_task_arguments,
self.play_name,
task
)
def v2_playbook_on_task_start(self, task, is_conditional):
self.opentelemetry.start_task(
self.tasks_data,
self.hide_task_arguments,
self.play_name,
task
)
def v2_playbook_on_cleanup_task_start(self, task):
self.opentelemetry.start_task(
self.tasks_data,
self.hide_task_arguments,
self.play_name,
task
)
def v2_playbook_on_handler_task_start(self, task):
self.opentelemetry.start_task(
self.tasks_data,
self.hide_task_arguments,
self.play_name,
task
)
def v2_runner_on_failed(self, result, ignore_errors=False):
if ignore_errors:
status = 'ignored'
else:
status = 'failed'
self.errors += 1
self.opentelemetry.finish_task(
self.tasks_data,
status,
result
)
def v2_runner_on_ok(self, result):
self.opentelemetry.finish_task(
self.tasks_data,
'ok',
result
)
def v2_runner_on_skipped(self, result):
self.opentelemetry.finish_task(
self.tasks_data,
'skipped',
result
)
def v2_playbook_on_include(self, included_file):
self.opentelemetry.finish_task(
self.tasks_data,
'included',
included_file
)
def v2_playbook_on_stats(self, stats):
if self.errors == 0:
status = Status(status_code=StatusCode.OK)
else:
status = Status(status_code=StatusCode.ERROR)
self.opentelemetry.generate_distributed_traces(
self.otel_service_name,
self.ansible_playbook,
self.tasks_data,
status,
self.traceparent
)
def v2_runner_on_async_failed(self, result, **kwargs):
self.errors += 1

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# (c) 2012, Michael DeHaan, <michael.dehaan@gmail.com> # (c) 2012, Michael DeHaan, <michael.dehaan@gmail.com>
# (c) 2017 Ansible Project # (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
@@ -21,11 +20,11 @@ DOCUMENTATION = '''
- In 2.8, this callback has been renamed from C(osx_say) into M(community.general.say). - In 2.8, this callback has been renamed from C(osx_say) into M(community.general.say).
''' '''
import distutils.spawn
import platform import platform
import subprocess import subprocess
import os import os
from ansible.module_utils.common.process import get_bin_path
from ansible.plugins.callback import CallbackBase from ansible.plugins.callback import CallbackBase
@@ -47,24 +46,21 @@ class CallbackModule(CallbackBase):
self.HAPPY_VOICE = None self.HAPPY_VOICE = None
self.LASER_VOICE = None self.LASER_VOICE = None
try: self.synthesizer = distutils.spawn.find_executable('say')
self.synthesizer = get_bin_path('say') if not self.synthesizer:
if platform.system() != 'Darwin': self.synthesizer = distutils.spawn.find_executable('espeak')
# 'say' binary available, it might be GNUstep tool which doesn't support 'voice' parameter if self.synthesizer:
self._display.warning("'say' executable found but system is '%s': ignoring voice parameter" % platform.system())
else:
self.FAILED_VOICE = 'Zarvox'
self.REGULAR_VOICE = 'Trinoids'
self.HAPPY_VOICE = 'Cellos'
self.LASER_VOICE = 'Princess'
except ValueError:
try:
self.synthesizer = get_bin_path('espeak')
self.FAILED_VOICE = 'klatt' self.FAILED_VOICE = 'klatt'
self.HAPPY_VOICE = 'f5' self.HAPPY_VOICE = 'f5'
self.LASER_VOICE = 'whisper' self.LASER_VOICE = 'whisper'
except ValueError: elif platform.system() != 'Darwin':
self.synthesizer = None # 'say' binary available, it might be GNUstep tool which doesn't support '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'
self.HAPPY_VOICE = 'Cellos'
self.LASER_VOICE = 'Princess'
# plugin disable itself if say is not present # plugin disable itself if say is not present
# ansible will not call any callback if disabled is set to True # ansible will not call any callback if disabled is set to True

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