Compare commits

..

550 Commits
3.7.0 ... 4.3.0

Author SHA1 Message Date
Felix Fontein
c85bb8713e Release 4.3.0 2022-01-11 07:27:25 +01:00
patchback[bot]
5cdc8f4b07 New Module: Keycloak Realm Info (#3998) (#4022)
* feat(plugins/keycloak): add get_realm_info_by_id as util function

* feat(plugins/keycloak): add keycloak_realm_info module

* chore: add maintainer

* feat(plugins/keycloak): remove supports_check_mode

* feat(plugins/keycloak): add supports_check_mode back

* Update plugins/modules/identity/keycloak/keycloak_realm_info.py

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

* Update plugins/modules/identity/keycloak/keycloak_realm_info.py

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

* docs(plugins/keycloak): cleanup docs

* feat(plugins/keycloak): add unit test

* Update plugins/modules/identity/keycloak/keycloak_realm_info.py

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

* Update plugins/modules/identity/keycloak/keycloak_realm_info.py

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

* feat(plugins/keycloak): remove end_state

* docs(plugins/keycloak): complete sentences

* docs(plugins/keycloak): use dict for return type

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

Co-authored-by: Fynnnnn <fynn.cfchen@gmail.com>
2022-01-11 07:13:16 +01:00
Felix Fontein
50131f5dfa Prepare 4.3.0 release. 2022-01-10 23:06:56 +01:00
patchback[bot]
c734e7c2e5 fix alternatives parsing when they are part of a group (#3976) (#4021)
* fix alternatives parsing when they are part of a group

* add changelog fragment

Co-authored-by: Guillaume Rousse <guillaume.rousse@renater.fr>
(cherry picked from commit a675afcba9)

Co-authored-by: Guillaume Rousse <guillomovitch@gmail.com>
2022-01-10 07:27:31 +01:00
patchback[bot]
7e6e8f7749 puppet: Add documentation and remove deprecation for show_diff, keep deprecation for alias show-diff (#3980) (#4019)
* puppet: Add documentation and remove deprecation for show_diff

* Add changelog fragment

* Update changelogs/fragments/3980-puppet-show_diff.yml

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

* Update plugins/modules/system/puppet.py

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

* Update plugins/modules/system/puppet.py

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

* Fixing syntax error introduced in 29298da3

* More documentation for show_diff and fix some sanity errors

* Update changelogs/fragments/3980-puppet-show_diff.yml

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

* Update tests/sanity/ignore-2.10.txt

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

* Add validate-modules:parameter-invalid to ignores due to invalid and depricated alias

* Keep use-argspec-type-path in ignores

* Update plugins/modules/system/puppet.py

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

Co-authored-by: Benoit Vaudel <benoit@catalyst.net.nz>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit fe57cd5ac8)

Co-authored-by: Benoit Vaudel <vaudelbenoit@aol.com>
2022-01-10 07:27:22 +01:00
patchback[bot]
687acdc961 Fix example code for flattened lookup (#4013) (#4016)
Co-authored-by: Lee Garrett <lgarrett@rocketjump.eu>
(cherry picked from commit d19ab93faf)

Co-authored-by: Lee Garrett <leegarrett@users.noreply.github.com>
2022-01-09 12:29:22 +01:00
patchback[bot]
16092feaab ipmi_power: Add machine option to ensure the power state via the remote target address (#3968) (#4012)
* ipmi_power: Add machine option to ensure the power state via the remote target address

* Fix yamllint sanity check error

* Add changelog fragment entry

* Apply suggestions from the code review

* update to apply suggestions

* Add version_added.

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

Co-authored-by: mizumm <26898888+mizumm@users.noreply.github.com>
2022-01-08 16:17:56 +01:00
patchback[bot]
6676fb8fb4 New module for cargo command (#3712) (#4011)
* New module for cargo command

* Resolve CI errors

* Update plugins/modules/packaging/language/cargo.py

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

* Update plugins/modules/packaging/language/cargo.py

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

* Update plugins/modules/packaging/language/cargo.py

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

* Add maintainer

* Change installed_packages from property to function

* Allow cargo to install list of of packages

* Remove period at the end of task names

* Pass only the list of packages to take action on to cargo

* Add integration tests for cargo

* Update plugins/modules/packaging/language/cargo.py

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

* Apply suggestions from code review

* Update tests/integration/targets/cargo/tasks/setup.yml

* Update tests/integration/targets/cargo/tasks/setup.yml

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

Co-authored-by: radek-sprta <mail@radeksprta.eu>
2022-01-08 16:03:23 +01:00
patchback[bot]
a860f537dd Restrict PyNaCL to 1.4.x on RHEL8 when using Python 3.6 (#4006) (#4010)
* Restrict PyNaCL to 1.4.x on RHEL8 when using Python 3.6.

* Fix typo.

(cherry picked from commit 77a930cf6b)

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-01-08 14:19:25 +00:00
patchback[bot]
f1a9c2f00a nmcli: Add wireguard connection type support (#3985) (#4007)
* nmcli: add wireguard connection type

* nmcli: fix wireguard unit tests

* nmcli: set ipv4.method to disabled if ip4 not set

Method 'auto' is not supported for WireGuard

* nmcli: add wireguard documentation

* nmcli: clean up wireguard documentation

* nmcli: add wireguard changelog fragment

* nmcli: fix wireguard documentation

* Apply suggestions from code review

Co-authored-by: Andrew Pantuso <ajpantuso@gmail.com>

Co-authored-by: Andrew Pantuso <ajpantuso@gmail.com>
(cherry picked from commit 4ea58fba75)

Co-authored-by: Johan Wennerberg <j.wennerberg@gmail.com>
2022-01-08 14:33:02 +01:00
patchback[bot]
f8de068e32 Fix 2.9 unit tests (#4002) (#4005)
* Fix 2.9 unit tests.

* Another try.

(cherry picked from commit 26a91e811f)

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-01-08 13:34:11 +01:00
patchback[bot]
70b4bacf0f Fix comment. (#3993) (#3995)
(cherry picked from commit a6a8cd02b6)

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-01-06 15:10:49 +01:00
patchback[bot]
41f5d1741c proxmox: Add clone parameter (#3930) (#3992)
* proxmox: Add clone parameter

* Add changelog fragment

* Add version_added

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

* Add PR URL to changelog fragment

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

* Clarify what content_check does

* Split up try/except block to give a separate error message when creation pre-checks fail

* Create seperate case for cloning

* Prevent 'clone' argument from being removed

* Fix double argument, add todo's

* Check if to be cloned container actually exists

* Adjust module options dependencies

* Require 'storage' parameter when cloned container is not a template and ignore otherwise

* Don't only create linked clones of template containers

* Fix pylint errors

* Add extra example

* Minor language fix

* Add clone_type parameter to specify cloning behaviour

* I can't find if openvz nodes have this clone API, so just don't support it

* Remove unrelated changes

* Don't pass unused kwargs

* Revert more unrelated changes

* Remove required_together clone and clone_type because clone_type has a default choice

* Fix clone_type reference

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

* Fix missing period

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

* Fix redundant period

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

* Fix redundant period

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

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

Co-authored-by: Martijn <martijn@mrtijn.nl>
2022-01-06 08:06:55 +01:00
patchback[bot]
54ede7dd7f Fix BOTMETA and corresponding sanity test (#3989) (#3990)
* Fix BOTMETA and authors mistakes.

* Fix BOTMETA sanity test regex.

(cherry picked from commit 11205eefee)

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-01-06 06:56:27 +01:00
patchback[bot]
7f0702b786 Use vendored copy of distutils.version. (#3984) (#3987)
(cherry picked from commit cf7a33356c)

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-01-05 22:05:13 +01:00
patchback[bot]
89a3abe64a [Bug] Scaleway The volume is created systematically on par1 (#3964) (#3983)
* [Bug] The volume is created systematically on par1

* add change log

* added backward compatibility with organization

* add documentation

* change typo doc

* Update changelogs/fragments/3964-scaleway_volume_add_region.yml

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

* Update plugins/modules/cloud/scaleway/scaleway_volume.py

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

* Update plugins/modules/cloud/scaleway/scaleway_volume.py

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

* Update plugins/modules/cloud/scaleway/scaleway_volume.py

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

* Update plugins/modules/cloud/scaleway/scaleway_volume.py

Co-authored-by: Rémy Léone <remy.leone@gmail.com>

* optimization

Co-authored-by: Romain SCHARFF <rscharff@plussimple.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Rémy Léone <remy.leone@gmail.com>
(cherry picked from commit 125516b957)

Co-authored-by: xilmen <romain.scha@gmail.com>
2022-01-05 18:12:11 +01:00
patchback[bot]
59eff2e3e0 Re-enable snap tests (#3967) (#3981)
* Re-enable snap tests.

* Skip tests on RHEL 8.2 and 8.3.

* Refactor snap setup.

* Try to simplify setup.

(cherry picked from commit bb78d98f8f)

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-01-05 17:49:05 +01:00
patchback[bot]
1115b463fe Sudoers (take 2) (#3746) (#3977)
* Add module and pass the andebox validate-modules

* Fixes pep8 and sanity checks

* Add tests (intending that they'll fail)

* Fix pep8 complaint

* Remove stub test_sudoers file

* Add version_added to documentation

Co-authored-by: Andrew Pantuso <ajpantuso@gmail.com>

* Various improvements as suggested by reviewers

* Remove further required: false from documentation

* Make yaml indentation consistently indented

* Remove default for command argument

Co-authored-by: Andrew Pantuso <ajpantuso@gmail.com>

* Refactor check_mode checking as guards

* Update documentation formatting and use to_native

* Update plugins/modules/system/sudoers.py

* Update examples and formatting

* Fix merge conflict

* Update handle

* Add some integration tests

* Update tests to pass yamllint

* Fix assertions typo

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

* Remove wrapping quotes from assertions

* Use >- for long example names

* Add aliases file to sudoers integration tests

* Fix integration test name

* Create new alternative sudoers directory in case /tmp doesn't exist

* Alternative assertion test for checking rule revocation

* Re-quote assertions

* Update version_added to 4.3.0

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

* Uppercase first character of short_description

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

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

Co-authored-by: Jon <ellis.jp@gmail.com>
2022-01-04 21:08:02 +01:00
patchback[bot]
77bf1fedf5 Get rid of distutils.spawn and distutils.util (#3934) (#3974)
* Replace distutils.spawn.find_executable.

* Replace distutils.util.strtobool.

(cherry picked from commit 77b7b4f75b)

Co-authored-by: Felix Fontein <felix@fontein.de>
2022-01-04 07:22:25 +01:00
patchback[bot]
89560ea2e7 Mattermost: Add sending of attachments (#3946) (#3972)
* Add sending of attachments

* Change required arguments and add changelog

- text was still default -> changed to required_one_of text or attachments
- Add version_added
- Add changelog fragment for mattermost attachments

Co-Authored-By: Felix Fontein <felix@fontein.de>

* Fix wrong indentation

* Add trailing comma

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

* Remove default=None

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

* Fix sentence

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

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

Co-authored-by: xobtoor <313188+xobtoor@users.noreply.github.com>
2022-01-03 19:44:06 +01:00
patchback[bot]
f9919d28d4 slack - use UTF-8 charset in content-type header (#3933) (#3971)
* Use UTF-8 charset in content-type header

* Add changelog fragment

(cherry picked from commit a4ab85fd68)

Co-authored-by: bluikko <14869000+bluikko@users.noreply.github.com>
2022-01-03 19:43:50 +01:00
patchback[bot]
7b4660d28a Add support of project id for scawelay_compute (#3951) (#3961)
* Add support of project id for scawelay_compute

* Create 3951-scaleway_compute_add_project_id

* rename changelog frament

* remove useless whitespace in scaleway_compute.py

* Update changelogs/fragments/3951-scaleway_compute_add_project_id.yml

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

* Update plugins/modules/cloud/scaleway/scaleway_compute.py

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

* correct documentation

* Update changelogs/fragments/3951-scaleway_compute_add_project_id.yml

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

* Update changelogs/fragments/3951-scaleway_compute_add_project_id.yml

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

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

Co-authored-by: pmangin <96626847+pmangin@users.noreply.github.com>
2021-12-28 16:44:10 +01:00
patchback[bot]
29496be80e Restrict redis to < 4.1.0 for ansible-base 2.10. (#3955) (#3959)
(cherry picked from commit 3f2364574d)

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-12-27 21:17:09 +01:00
patchback[bot]
991c96615c fix scaleway_user_data (#3940) (#3954)
* fix  scaleway_user_data

scaleway_user_data put cloud-init valuer with 2 unexpected " (begin and end of value)

If Content-Type is not change , it's jsonify ( file module_utils/scaleway.py ligne 131 )

fix the probleme  when "Content-Type" is used instead of "Content-type"

* Create 3940_fix_contenttype_scaleway_user_data.yml

* Update changelogs/fragments/3940_fix_contenttype_scaleway_user_data.yml

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

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

Co-authored-by: pmangin <96626847+pmangin@users.noreply.github.com>
2021-12-27 20:00:58 +01:00
patchback[bot]
fe5ad997c1 ipa_dnszone: add PTR synchronization support for dnszones (#3374) (#3950)
* Add PTR synchronization support for dnszones

* Add changelog fragment

* Update changelogs/fragments/3374-add-ipa-ptr-sync-support.yml

Update to reflect proper module name.

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

* Update plugins/modules/identity/ipa/ipa_dnszone.py

Add period.

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

* Update plugins/modules/identity/ipa/ipa_dnszone.py

Remove requires comment.

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

* Change type to boolean in following with API docs

* Tested with needed changes made.

* Fix documentation to max implementation

* Check for specific params; allow for modifications if needed

* Add PTR synchronization support for dnszones

* Add changelog fragment

* Update changelogs/fragments/3374-add-ipa-ptr-sync-support.yml

Update to reflect proper module name.

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

* Remove trailing whitespace

* Make use of full search and compare params

* Fix formatting errors

* Move the change flag outside of module check

* Fix itens typo to items

* Update dynamicupdate to a boolean

* Remove unnecessary flags and options

* Minor comment changes

* Update changelogs/fragments/3374-add-ipa-ptr-sync-support.yml

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

* Update plugins/modules/identity/ipa/ipa_dnszone.py

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

Co-authored-by: Anne-Marie Lee <alee@datainterfuse.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 84e45c2cc0)

Co-authored-by: Annie Lee <hambriak@gmail.com>
2021-12-27 16:22:55 +01:00
patchback[bot]
468b28bbb8 Add counter filter (#3921) (#3945)
* Add counter filter

* move counter filter doc to existing chapter

* Use existing typerror exception from Counter

* Match counter filter example task name and output

(cherry picked from commit 9642a15d34)

Co-authored-by: Rémy Keil <remy.keil@gmail.com>
2021-12-26 15:25:18 +01:00
patchback[bot]
9b57221d9a Prepare for distutils.version being removed in Python 3.12 (#3936) (#3941)
* Prepare for distutils.version being removed in Python 2.12.

* Fix copy'n'paste error.

* Re-add Loose prefix.

* Fix Python version typos.

* Improve formulation.

* Move message into own line.

* Fix casing, now that the object is no longer called Version.

(cherry picked from commit a2f72be6c8)

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-12-24 19:15:47 +01:00
patchback[bot]
cd1a92d417 Fix filesystem tests (so they run on their own) (#3937) (#3939)
* Don't use loops for installing packages.

* Install util-linux-systemd on OpenSuSE so that findmnt is around.

(cherry picked from commit f34c454412)

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-12-23 12:33:24 +01:00
Felix Fontein
7486e3a074 Next expected release is 4.3.0. 2021-12-21 12:24:08 +01:00
Felix Fontein
6661917370 Release 4.2.0. 2021-12-21 11:58:13 +01:00
patchback[bot]
ec0bd3143a Add additional auth support to Gitlab (#705) (#3918) (#3929)
* Add additional auth support to Gitlab (#705)

- removed unused imports from module_utils.gitlab
- fix bug in gitlab_project to check if avatar_path is provided

* add doc_fragment and argument_spec for gitlab auth

* doc fixes and remove avatar_path bug fix

* small doc changes, pass validate_certs to requests call

* update changelog

(cherry picked from commit 52ad0a5fbb)

Co-authored-by: Josh <josham@users.noreply.github.com>
2021-12-20 22:20:40 +01:00
patchback[bot]
cce68def8b fix gitlab_project avatar_path open when undefined bug (#3926) (#3927) (#3928)
* fix gitlab_project avatar_path open when undefined bug (#3926)

* remove changelog fragment

(cherry picked from commit 11fcf661bf)

Co-authored-by: Josh <josham@users.noreply.github.com>
2021-12-20 20:22:29 +01:00
patchback[bot]
6f5ad22d28 Disable snap tests. (#3922) (#3923)
(cherry picked from commit 51838adf8c)

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-12-20 10:58:42 +01:00
patchback[bot]
6c53a09eef xfconf - using aggregated base class (#3919) (#3920)
* xfconf - using aggregated base class

* added changelog fragment

* fixed typo

(cherry picked from commit daabb53a2b)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-12-20 10:15:24 +01:00
patchback[bot]
9b6e75f7f4 Icinga2 Inventory Plugin - Error handling and inventory name changer (#3906) (#3915)
* Added inventory_attr and filter error handling

* Added inventory_attr and filter error handling

* Added inventory_attr and filter error handling

* Added inventory_attr and filter error handling

* Added changelog

* Added inventory_attr and filter error handling

* Added inventory_attr and filter error handling

* Applying requested changes

* FIxes for tests

* Added inventory_attr and filter error handling

* Error handling

* Error handling

* Error handling

* Modifications to unit tests

* Remove pitfall

(cherry picked from commit 8da2c630d8)

Co-authored-by: Cliff Hults <BongoEADGC6@users.noreply.github.com>
2021-12-19 14:18:57 +01:00
patchback[bot]
e09650140d Fix nrdp string arguments without an encoding (#3909) (#3912)
* Fix nrdp string arguments without an encoding

* added changelog fragment

Signed-off-by: Jesse Harris <zigford@gmail.com>

* Update changelogs/fragments/3909-nrdp_fix_string_args_without_encoding.yaml

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

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

Co-authored-by: Jesse Harris <zigford@gmail.com>
2021-12-17 22:40:29 +01:00
patchback[bot]
67388be1a9 jira - fixed 'body' dict key error (#3867) (#3914)
* fixed

* added changelog fragment

* improved fail output when placing JIRA API requests

* Update plugins/modules/web_infrastructure/jira.py

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

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

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-12-17 22:13:43 +01:00
patchback[bot]
130d07948a proxmox - fixing onboot parameter causing module failure when not defined (#3874) (#3902)
* fixing onboot parameter when not supplied

* adding changelog fragment

(cherry picked from commit 00a1152bb1)

Co-authored-by: Andrew Pantuso <ajpantuso@gmail.com>
2021-12-14 07:00:32 +01:00
patchback[bot]
5d6fcaef53 LXD inventory: Support virtual machines (#3519) (#3900)
* LXD 4.x compatibility (Containers and VMs)

* add changelog fragment

* update fixture

* update plugin options

* backwards compatible alias

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

* Update changelogs/fragments/3519-inventory-support-lxd-4.yml

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

* add lxd 4.0 requirement

* filter for type of virtualization added. due to duplication in the namespace, "type" is not used as the keyword but "nature".

* add type filter

Since the first version of this inventory plugin only supports containers,
a filter function was added to filter between containers and
virtual machines or both.
By default only containers are displayed, as in the first version of the plugin.
This behavior will change in the future.

* rename C(nature) to C(type)

The term "nature" does not fit into the lxd namespace.
Therefore i renamed nature to type.

* update changelog fragment

* Update plugins/inventory/lxd.py

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

* Apply suggestions from code review

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

* rename typefilter to type_filter

* fix tests with type_filter

* Update plugins/inventory/lxd.py

* Update plugins/inventory/lxd.py

Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Frank Dornheim <“dornheim@posteo.de@users.noreply.github.com”>
(cherry picked from commit 8825ef4711)

Co-authored-by: Élie <elie@deloumeau.fr>
2021-12-14 06:42:47 +01:00
patchback[bot]
f044a83c49 Pass missing vlan-related options (flags, ingress, egress) to nmcli (#3896) (#3899)
* Pass missing vlan-related options (flags, ingress, egress) to nmcli

Signed-off-by: Jean-Francois Panisset <panisset@gmail.com>

* Follow style: comma on last parameter

Signed-off-by: Jean-Francois Panisset <panisset@gmail.com>

* PEP8 code style fix

Signed-off-by: Jean-Francois Panisset <panisset@gmail.com>

* add missing changelog fragment

Signed-off-by: Jean-Francois Panisset <panisset@gmail.com>
(cherry picked from commit 6cec2e2f58)

Co-authored-by: Jean-Francois Panisset <32653482+jfpanisset@users.noreply.github.com>
2021-12-13 21:59:37 +01:00
patchback[bot]
e3f7e8dadf Docs improvements. (#3893) (#3894)
(cherry picked from commit 59bbaeed77)

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-12-12 11:46:31 +01:00
patchback[bot]
8d1a028dbd Modules for managing HPE iLO (#3740) (#3892)
* Adding HPE ilo modules

* lint fix

* symlink created

* Fan message enhancement

* Removed comments

* Added uniform constuct

* Update plugins/module_utils/redfish_utils.py

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

* Update plugins/module_utils/redfish_utils.py

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

* Update plugins/modules/remote_management/redfish/ilo_redfish_config.py

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

* Added info module and minor changes

* lint fixes

* lint fixes

* lint fixes

* lint fixes

* Added tests and modifed ilo_redfish_info

* Modified tests

* lint fix

* result overwrite fixed

* result overwrite fixed

* Added result

* Changed RESULT

* Modified contains

* Added License

* lint fix

* Changed RESULT

* lint fix

* Changed return

* Changed return

* Update plugins/modules/remote_management/redfish/ilo_redfish_info.py

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

* Update plugins/modules/remote_management/redfish/ilo_redfish_info.py

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

* Update plugins/modules/remote_management/redfish/ilo_redfish_info.py

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

* Update plugins/modules/remote_management/redfish/ilo_redfish_info.py

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

* Update plugins/modules/remote_management/redfish/ilo_redfish_config.py

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

* Update plugins/modules/remote_management/redfish/ilo_redfish_info.py

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

* Added - changed

* Modified changed attribute

* Changed modified

* lint fix

* Removed req

* Minor changes

* Update plugins/modules/remote_management/redfish/ilo_redfish_info.py

Co-authored-by: Rajeevalochana Kallur <rajeevalochana.kallur@hpe.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 8508e3fa6f)

Co-authored-by: Bhavya <44067558+Bhavya06@users.noreply.github.com>
2021-12-11 21:56:10 +01:00
patchback[bot]
8823e5c061 hponcfg - revamped the module using ModuleHelper (#3840) (#3891)
* hponcfg - revamped the module using ModuleHelper

* added changelog fragment

* fixed imports

* Update plugins/modules/remote_management/hpilo/hponcfg.py

* fixed

(cherry picked from commit 7cbe1bcf63)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-12-11 21:35:23 +01:00
patchback[bot]
102456d033 add dnsimple_info module, see issue #3569 (#3739) (#3890)
* add dnsimple_info module, see issue #3569

https://github.com/ansible-collections/community.general/issues/3569#issuecomment-945002861

* Update plugins/modules/net_tools/dnsimple_info.py

Update dnsimple_info.py

Update dnsimple_info.py

Update dnsimple_info.py

Update BOTMETA.yml

Update dnsimple_info.py

Create dnsimple_info.py

Create dnsimple_info.py

pep8

Update dnsimple_info.py

Update dnsimple_info.py

Update dnsimple_info.py

Update plugins/modules/net_tools/dnsimple_info.py

Update plugins/modules/net_tools/dnsimple_info.py

Update plugins/modules/net_tools/dnsimple_info.py

Update plugins/modules/net_tools/dnsimple_info.py

Update plugins/modules/net_tools/dnsimple_info.py

Update dnsimple_info.py

add returns

pep8 spacing

Update dnsimple_info.py

Update dnsimple_info.py

change return results to list

fix time stamps

Update dnsimple_info.py

remove extra comma

Update plugins/modules/net_tools/dnsimple_info.py

Update test_dnsimple_info.py

Update dnsimple_info.py

fix descriptions

Update dnsimple_info.py

Update dnsimple_info.py

Update dnsimple_info.py

Update dnsimple_info.py

Update dnsimple_info.py

Update dnsimple_info.py

Update dnsimple_info.py

Update dnsimple_info.py

missing punctuation throughout docs

Update dnsimple_info.py

add elements in descriptions

Update dnsimple_info.py

indentation error

Update dnsimple_info.py

Update dnsimple_info.py

Update dnsimple_info.py

Update dnsimple_info.py

Update dnsimple_info.py

refactor, remove unneeded arguments

refactor and error handling

formatting

add unit test

Update test_dnsimple_info.py

Update test_dnsimple_info.py

Update plugins/modules/net_tools/dnsimple_info.py

Update plugins/modules/net_tools/dnsimple_info.py

Update plugins/modules/net_tools/dnsimple_info.py

Update plugins/modules/net_tools/dnsimple_info.py

Update plugins/modules/net_tools/dnsimple_info.py

Update plugins/modules/net_tools/dnsimple_info.py

Update plugins/modules/net_tools/dnsimple_info.py

Update plugins/modules/net_tools/dnsimple_info.py

Update plugins/modules/net_tools/dnsimple_info.py

Update plugins/modules/net_tools/dnsimple_info.py

Update plugins/modules/net_tools/dnsimple_info.py

Update test_dnsimple_info.py

Update test_dnsimple_info.py

Update test_dnsimple_info.py

Update test_dnsimple_info.py

Update test_dnsimple_info.py

Update test_dnsimple_info.py

assert fail/exit

Update test_dnsimple_info.py

pep8 fixes

Update test_dnsimple_info.py

Update test_dnsimple_info.py

Update test_dnsimple_info.py

Update test_dnsimple_info.py

Co-Authored-By: Felix Fontein <felix@fontein.de>

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

Co-authored-by: Edward Hilgendorf <edward@hilgendorf.me>
2021-12-11 21:29:27 +01:00
patchback[bot]
aad4c55d3d lxc_container - invoke run_command passing list (#3851) (#3886)
* lxc_container - invoke run_command passing list

* added changelog fragment

* Update plugins/modules/cloud/lxc/lxc_container.py

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

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

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-12-10 06:43:19 +01:00
patchback[bot]
e31c98f17f jira - Add support for Bearer token auth (#3838) (#3884)
* jira - Add support for Bearer token auth

* jira - Add support for Bearer token auth

* added changelog fragment

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

* fix indent issue

* fix overindent

* jira - Add support for Bearer token auth

* jira - Add support for Bearer token auth

* added changelog fragment

* minor doc fix to be clearer.

Be clear about the exclusivity between username and token
as well as password and token.

* Update changelogs/fragments/3838-jira-token.yaml

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

* Update plugins/modules/web_infrastructure/jira.py

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

* Update plugins/modules/web_infrastructure/jira.py

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

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

Co-authored-by: Kambiz Aghaiepour <kambiz@aghaiepour.com>
2021-12-09 22:05:02 +01:00
patchback[bot]
6a5dfc5579 aix_lvg - invoke run_command passing list (#3834) (#3883)
* aix_lvg - invoke run_command passing list

* added changelog fragment

(cherry picked from commit 4bddf9e12c)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-12-09 22:01:28 +01:00
Felix Fontein
ab7efef9df nmcli: adding ipv6 address list support (#3776) (#3885)
* rebase

* Add changelog fragment

* add suggestions

* split PR into two

* Add multiple address support but with #3768 fiexed

* rebase

* clean some merge artifacts

* update the wording

(cherry picked from commit 90c0980e8d)

Co-authored-by: Alex Groshev <38885591+haddystuff@users.noreply.github.com>
2021-12-09 22:00:33 +01:00
patchback[bot]
ca9c763b57 aix_filesystems - invoke run_command passing list (#3833) (#3882)
* aix_filesystems - invoke run_command passing list

* added changelog fragment

(cherry picked from commit 70f73f42f8)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-12-09 22:00:12 +01:00
patchback[bot]
cfeb40ed23 Update lxd connection to use all documented vars for options (#3798) (#3881)
* Update lxd connection to use documented vars

* Add a changelog fragment

* Add clarification to changelog description

* Shorten changelog fragment description

(cherry picked from commit 8f6866dba6)

Co-authored-by: Conner Crosby <conner@cavcrosby.tech>
2021-12-09 21:58:06 +01:00
patchback[bot]
c495d136fa add module gitlab_branch (#3795) (#3879)
* add module gitlab_branch

* Update plugins/modules/source_control/gitlab/gitlab_branch.py

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

* Update plugins/modules/source_control/gitlab/gitlab_branch.py

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

* Update plugins/modules/source_control/gitlab/gitlab_branch.py

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

* Update gitlab_branch.py

* Update gitlab_branch.py

* Update gitlab_branch.py

* add integration tests

* Update BOTMETA.yml

* Update gitlab_branch.py

* Update tests/integration/targets/gitlab_branch/aliases

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

* Update main.yml

Co-authored-by: paitrault <aymeric.paitrault@inetum.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit c69e4f4ac9)

Co-authored-by: paytroff <paytroff@gmail.com>
2021-12-09 21:19:13 +01:00
patchback[bot]
d9e2d6682b small docs update for timezone module (#3876) (#3878)
* small docs update for timezone module
fixes #3242

* Update plugins/modules/system/timezone.py

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

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

Co-authored-by: Anatoly Pugachev <matorola@gmail.com>
2021-12-09 21:19:03 +01:00
Felix Fontein
d7fe288ffd Prepare 4.2.0 release. 2021-12-08 20:22:04 +01:00
patchback[bot]
7de89699f7 update scaleway maintainers (#3472) (#3873)
* update scaleway maintainers

* Fix

* Fix sieben -> remyleone

Co-authored-by: scaleway-bot <github@scaleway.com>
(cherry picked from commit 80d650f60a)

Co-authored-by: Rémy Léone <remy.leone@gmail.com>
2021-12-08 20:20:59 +01:00
patchback[bot]
b0a9cceeb5 interfaces_file: unit tests improved (#3863) (#3869)
* interfaces_file: fixed unit tests and added README, added test cases for #3862

* typo fix for interfaces_file unit tests README.md

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

* typo fix for interfaces_file unit tests README.md

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

* typo fix for interfaces_file unit tests README.md

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

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

Co-authored-by: Roman Belyakovsky <ihryamzik@gmail.com>
2021-12-08 12:51:25 +01:00
patchback[bot]
b08f0b2f82 interfaces_file - fixed dup options bug (#3862) (#3866)
* interfaces_file - fixed dup options bug

* added changelog fragment

(cherry picked from commit 3dd5b0d343)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-12-08 05:54:48 +00:00
patchback[bot]
f23f409bd6 MH additional tests (#3850) (#3859)
(cherry picked from commit d50f30c618)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-12-05 22:14:16 +01:00
patchback[bot]
cfea62793f MH decorators - added decorators for check_mode (#3849) (#3860)
* MH decorators - added decorators for check_mode

* added changelog fragment

(cherry picked from commit fb79c2998e)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-12-05 22:14:08 +01:00
patchback[bot]
62bda91466 Add stable-4 to nightly CI jobs; make stable-2 weekly. (#3852) (#3857)
(cherry picked from commit 727c9a4032)

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-12-05 17:41:15 +01:00
patchback[bot]
473d5fa2af Moved changelog fragment file to the right directory (#3853) (#3858)
* moved changelog fragment file to the right directory

* fixed filename

(cherry picked from commit 4f4150117d)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-12-05 17:40:43 +01:00
patchback[bot]
cc76d684d5 opentelemetry: honour ignore errors (#3837) (#3847)
* opentelemetry: honour the ignore_errors

* fix-encoding-pragma

* Add changelog fragment

* opentelemetry: ignore produces unset span status

(cherry picked from commit ce6d0a749e)

Co-authored-by: Victor Martinez <victormartinezrubio@gmail.com>
2021-12-04 19:55:17 +01:00
patchback[bot]
7a6770c731 nmcli - add support for addr-gen-mode and ip6-privacy options (#3802) (#3845)
* Add support for addr-gen-mode and ip6-privacy options

* Apply suggestions from code review

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

* try to solve conflict

* add suggested code + fix some of its issues

* Update plugins/modules/net_tools/nmcli.py

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

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

Co-authored-by: Alex Groshev <38885591+haddystuff@users.noreply.github.com>
2021-12-04 19:18:49 +01:00
patchback[bot]
d2214af6e8 java_cert - invoke run_command passing list (#3835) (#3842)
* java_cert - invoke run_command passing list

* added changelog fragment

(cherry picked from commit 6b91c56c4e)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-12-03 08:07:15 +01:00
patchback[bot]
fad1220869 monit - invoke run_command passing list (#3821) (#3832)
* monit - invoke run_command passing list

* added changelog fragment

* fixed unit test

* further adjustments

* fixed handling of command_args

* better handling of command_args

(cherry picked from commit 52d4907480)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-12-02 08:12:52 +01:00
patchback[bot]
fe09516235 svc - invoke run_command passing list (#3829) (#3830)
* svc - invoke run_command passing list

* added changelog fragment

(cherry picked from commit ccb74ffd7c)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-12-01 20:43:16 +01:00
patchback[bot]
78cd8886f4 ip_netns - invoke run_command passing list (#3822) (#3828)
* ip_netns - invoke run_command passing list

* added changelog fragment

(cherry picked from commit ba9578f12a)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-12-01 13:19:28 +01:00
patchback[bot]
6b99d48f06 logstash_plugin - invoke run_command passing list (#3808) (#3827)
* logstash_plugin - invoke run_command passing list

* added changelog fragment

* rogue chglog frag escaped its caged and was seen running around into a different PR

(cherry picked from commit c587d21ba0)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-12-01 07:09:49 +01:00
patchback[bot]
6e0e17a7e3 xattr - invoke run_command passing list (#3806) (#3820)
* xattr - invoke run_command passing list

* added changelog fragment

* Update plugins/modules/files/xattr.py

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

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

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-12-01 06:58:39 +01:00
patchback[bot]
90de95c7b2 pipx - fixed --include-apps bug (#3800) (#3818)
* pipx - fixed --include-apps bug

* added changelog fragment

* skipped freebsd for the last test

(cherry picked from commit bc619bcefc)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-11-30 08:33:31 +01:00
patchback[bot]
07c6b8b24e ModuleHelper - deprecate attribute VarDict (#3801) (#3819)
* ModuleHelper - deprecate attribute VarDict

* added changelog fragment

(cherry picked from commit 2896131ca7)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-11-30 08:32:56 +01:00
patchback[bot]
d106de6d51 python_requirements_info - improvements (#3797) (#3816)
* python_requirements_info - improvements

- returns python version broken down into its components
- minor refactoring

* adjusted indentation in the documentaiton blocks

* added changelog fragment

* fixes from PR review + assertion in test

(cherry picked from commit ff0c065ca2)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-11-30 08:32:42 +01:00
patchback[bot]
e96101fb3f Improve modules gitlab (#3792) (#3815)
* correction doc

* Update gitlab_group.py

* improve gitlab

* Update changelogs/3766-improve_gitlab_group_and_project.yml

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

* Update plugins/modules/source_control/gitlab/gitlab_group.py

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

* Update plugins/modules/source_control/gitlab/gitlab_group.py

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

* Update plugins/modules/source_control/gitlab/gitlab_group.py

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

* Update plugins/modules/source_control/gitlab/gitlab_group.py

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

* correction

* correction sanity project

* Update plugins/modules/source_control/gitlab/gitlab_project.py

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

* modif condition default_branch arg

* Update gitlab_project.py

change indent if defautl_branch inside if initialize_with_radme

Co-authored-by: paitrault <aymeric.paitrault@inetum.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit c6dcae5fda)

Co-authored-by: paytroff <paytroff@gmail.com>
2021-11-30 06:53:17 +01:00
patchback[bot]
a60d55f03c ansible_galaxy_install - minor documentation fix (#3804) (#3814)
* ansible_galaxy_install - minor documentation fix

* further adjustments

(cherry picked from commit 49bdc0f218)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-11-30 06:53:07 +01:00
patchback[bot]
d6a09ada98 iso_extract - invoke run_command passing list (#3805) (#3812)
* iso_extract - invoke run_command passing list

* added changelog fragment

(cherry picked from commit d60edc4ac1)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-11-30 06:53:00 +01:00
patchback[bot]
9ddb75a3a2 logentries - invoke run_command passing list (#3807) (#3811)
* logentries - invoke run_command passing list

* added changelog fragment

(cherry picked from commit cb0ade4323)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-11-30 06:52:49 +01:00
patchback[bot]
b85ff2a997 Fixing ip address without mask bug (#3784) (#3803)
* change ip6 type to list of str and fix problem with setting addresses without netmask

* change ip6 type to list of str and fix problem with setting addresses without netmask

* Add changelog fragment

* add suggestions

* fix no mask using bug

* Make change independed from feature branch

(cherry picked from commit aae3ae1a8e)

Co-authored-by: Alex Groshev <38885591+haddystuff@users.noreply.github.com>
2021-11-30 06:01:50 +01:00
patchback[bot]
3d1ca5638b python_requirements_info - fail when version operator used without version (#3785) (#3793)
* python_requirements_info - fail when version operator used without version

* added changelog fragment

* simplified way of achieving the same result

(cherry picked from commit 59c1859fb3)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-11-26 20:53:58 +01:00
patchback[bot]
35fd4700bf MH DeprecateAttrsMixin (#3727) (#3794)
* initial commit for deprecate_attrs

* completed tests

* added spaces

* test now works when tehre is more than one deprecation

* trying == instead of eq in jinja

* new approach to testing

* removed extraneous debug message

(cherry picked from commit 887b3882dc)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-11-26 20:53:49 +01:00
patchback[bot]
9add9df7d6 Keycloak: add sssd provider for user federation (#3780) (#3788)
* add sssd provider

* add changelog fragment

* fix message

* add version

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

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

Co-authored-by: Laurent Paumier <30328363+laurpaum@users.noreply.github.com>
2021-11-25 13:23:21 +01:00
Felix Fontein
cdb747b41d Next expected release is 4.2.0. 2021-11-23 06:44:41 +01:00
Felix Fontein
7a70fda784 Release 4.1.0. 2021-11-23 05:52:35 +01:00
patchback[bot]
13d1b9569e terraform: ensuring command options are applied during build_plan (#3726) (#3778)
* Fixes parameters missing in planned state

* Added new line at end of file

* Added changelog fragment for pr 3726

* Added changes mentioned by felixfontein

* Removed blank space for pep8 validation

* Update changelogs/fragments/3726-terraform-missing-parameters-planned-fix.yml

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

* Update plugins/modules/cloud/misc/terraform.py

extend needs to be a list

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

Co-authored-by: Thomas Arringe <thomas.arringe@fouredge.se>
Co-authored-by: Thomas Arringe <Thomas.Arringe@ica.se>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 946430e1fb)

Co-authored-by: egnirra <37709886+egnirra@users.noreply.github.com>
2021-11-23 05:49:18 +01:00
patchback[bot]
c8c5021773 pacman: add stdout and stderr as return parameters (#3758) (#3775)
* pacman: add stdout and stderr as return parameters

Following the model of ansible.builtin.apt

* Bugfix to PR: fix documentation formatting

* Add changelog fragment 3758-pacman-add-stdout-stderr.yml

* Apply suggestions from code review

* Update changelogs/fragments/3758-pacman-add-stdout-stderr.yml

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

Co-authored-by: Célestin Matte <tohwiq@gmail.com>
2021-11-22 20:01:50 +01:00
patchback[bot]
206ac72bd8 extend open_iscsi to allow rescanning a session to discover new mapped LUN's #3763 (#3765) (#3774)
* <!--- Describe the change below, including rationale and design decisions -->

<!--- HINT: Include "Fixes #nnn" if you are fixing an existing issue -->

According to issue 3767, adding a session rescan flag to add and utilize mapped_luns after login into a portal and target.

<!--- Pick one below and delete the rest -->
- Feature Pull Request

<!--- Write the short name of the module, plugin, task or feature below -->
open_iscsi rescan flag

<!--- Include additional information to help people understand the change here -->
<!--- A step-by-step reproduction of the problem is helpful if there is no related issue -->

<!--- Paste verbatim command output below, e.g. before and after your change -->
``` yaml
      - name: Rescan Targets
        open_iscsi:
          rescan: true
          target: "{{ item.0 }}"
        register: iscsi_rescan
        loop:
          - iqn.1994-05.com.redhat:8c4ea31d28e
        tags:
          - rescan
```
```bash
    TASK [Rescan Targets] ********************************************************************************************************************************************************************
    changed: [node1] => (item=['iqn.1994-05.com.redhat:8c4ea31d28e'])
    changed: [node2] => (item=['iqn.1994-05.com.redhat:8c4ea31d28e'])

    TASK [Output rescan output] **************************************************************************************************************************************************************
    ok: [node1] => {
        "iscsi_rescan": {
            "changed": true,
            "msg": "All items completed",
            "results": [
                {
                    "ansible_loop_var": "item",
                    "changed": true,
                    "failed": false,
                    "invocation": {
                        "module_args": {
                            "auto_node_startup": null,
                            "discover": false,
                            "login": null,
                            "node_auth": "CHAP",
                            "node_pass": null,
                            "node_user": null,
                            "port": "3260",
                            "portal": null,
                            "rescan": true,
                            "show_nodes": false,
                            "target": "iqn.1994-05.com.redhat:8c4ea31d28e'"
                        }
                    },
                    "item": [
                        "iqn.1994-05.com.redhat:8c4ea31d28e"
                    ],
                    "sessions": [
                        "Rescanning session [sid: 3, target: iqn.1994-05.com.redhat:8c4ea31d28e, portal: 127.0.0.1,3260]",
                        "Rescanning session [sid: 1, target: iqn.1994-05.com.redhat:8c4ea31d28e, portal: 127.0.0.2,3260]",
                        "Rescanning session [sid: 2, target: iqn.1994-05.com.redhat:8c4ea31d28e, portal: 127.0.0.3,3260]",
                        ""
                    ]
                }
            ]
        }
    }
    ok: [node2] => {
        "iscsi_rescan": {
            "changed": true,
            "msg": "All items completed",
            "results": [
                {
                    "ansible_loop_var": "item",
                    "changed": true,
                    "failed": false,
                    "invocation": {
                        "module_args": {
                            "auto_node_startup": null,
                            "discover": false,
                            "login": null,
                            "node_auth": "CHAP",
                            "node_pass": null,
                            "node_user": null,
                            "port": "3260",
                            "portal": null,
                            "rescan": true,
                            "show_nodes": false,
                            "target": "iqn.1994-05.com.redhat:8c4ea31d28e"
                        }
                    },
                    "item": [
                        "iqn.1994-05.com.redhat:8c4ea31d28e"
                    ],
                    "sessions": [
                        "Rescanning session [sid: 3, target: iqn.1994-05.com.redhat:8c4ea31d28e, portal: 127.0.0.1,3260]",
                        "Rescanning session [sid: 2, target: iqn.1994-05.com.redhat:8c4ea31d28e, portal: 127.0.0.2,3260]",
                        "Rescanning session [sid: 1, target: iqn.1994-05.com.redhat:8c4ea31d28e, portal: 127.0.0.3,3260]",
                        ""
                    ]
                }
            ]
        }
    }
```

* minor_changes:
  - open_iscsi - extended module to allow rescanning of established session for one or all targets. (https://github.com/ansible-collections/community.general/issues/3763)

* * fixed commend according to the recommendation.

* Update plugins/modules/system/open_iscsi.py

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

Co-authored-by: Michaela Lang <94735640+michaelalang@users.noreply.github.com>
2021-11-22 19:50:44 +01:00
patchback[bot]
1ee123bb1e Xen orchestra inventory: Added groups, keyed_groups and compose support (#3766) (#3772)
* Xen orchestra inventory: Added groups, keyed_groups and compose support

* Update plugins/inventory/xen_orchestra.py

Remove extra params declaration

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

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

Co-authored-by: Samori Gorse <samori@codeinstyle.io>
2021-11-22 19:27:00 +01:00
patchback[bot]
aa0bcad9df RevBits PAM Secret Server Plugin (#3405) (#3771)
* RevBits PAM Secret Server Plugin

* Update revbitspss.py

* Update plugins/lookup/revbitspss.py

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

* Update plugins/lookup/revbitspss.py

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

* Update plugins/lookup/revbitspss.py

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

* Update plugins/lookup/revbitspss.py

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

* Update plugins/lookup/revbitspss.py

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

* Update plugins/lookup/revbitspss.py

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

* Fixes based on feedback from Ansible

* Fixes for auto tests

* module updated

* f string changed

* maintainer added

* maintainer added

* maintainer added

* review updates

* test added

* test added

* test added

* revisions updtes

* revisions updtes

* revisions updtes

* file removed

* unit test added

* suggestions updated

* suggestions updated

* Update plugins/lookup/revbitspss.py

* Update plugins/lookup/revbitspss.py

* Update plugins/lookup/revbitspss.py

Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Zubair Hassan <zubair.hassan@invozone.com>
Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
(cherry picked from commit 25e80762aa)

Co-authored-by: RevBits, LLC <74629760+RevBits@users.noreply.github.com>
2021-11-22 19:26:48 +01:00
patchback[bot]
6e51690a95 Support IPMI encryption key parameter in ipmi_boot (#3702) (#3770)
* Support IPMI encryption key parameter in ipmi_boot

* Support py2 on hex parsing, error handling

Change parsing hex string to support python2 and add error handling to it based on feedback.

* Don't explicitly set required to false

* Add version_added to key arg

* Add changelog fragment

* Add IPMI encryption key arg to ipmi_power

* Fix the formatting of changelog fragment

(cherry picked from commit 4013d0c9ca)

Co-authored-by: bluikko <14869000+bluikko@users.noreply.github.com>
2021-11-22 13:49:54 +01:00
patchback[bot]
3eab4faf0b Bugfix: github_repo does not apply defaults on existing repos (#2386) (#3769)
* github_repo do not apply defaults on currently existing repos

* Fixed sanity

* Fixed doc defaults

* Added changelog

* Fix "or" statement and some formatting

* Improve description change check

* Added api_url parameter for unit tests and default values for private and description parameters

* Added force_defaults parameter

* Improved docs

* Fixed doc anchors for force_defaults parameter

* Update plugins/modules/source_control/github/github_repo.py

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

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

Co-authored-by: Álvaro Torres Cogollo <atorrescogollo@gmail.com>
2021-11-22 13:49:29 +01:00
Felix Fontein
c6589a772b Prepare 4.1.0 release. 2021-11-20 09:16:49 +01:00
patchback[bot]
cb06c4ff77 [PR #3344/fef02c0f backport][stable-4] Xen orchestra inventory plugin (#3760)
* Xen orchestra inventory plugin (#3344)

* wip

* Renamed xo env variable with ANSIBLE prefix

* Suppress 3.x import and boilerplate errors

* Added shinuza as maintainer

* Do not use automatic field numbering spec

* Removed f string

* Fixed sanity checks

* wip tests

* Added working tests

* Fixed a bug when login fails

* Update plugins/inventory/xen_orchestra.py

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

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

* Replace usage of packaging.version with distutils.version.LooseVersion. (#3762)

(cherry picked from commit 08067f08df)

Co-authored-by: Samori Gorse <samori@codeinstyle.io>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-11-20 09:14:01 +01:00
patchback[bot]
78316fbb75 lxd_container: support lxd instance types (#3661) (#3761)
* lxd_container: support lxd instance types

Update the lxd_container module to enable the new LXD API endpoint,
which supports different types of instances, such as containers and virtual machines.
The type attributes can be set explicitly to create containers or virtual machines.

* lxd_container: rename references from containers to instances

* lxd_container: add an example of creating vms

* lxd_container: update doc

* lxd_container: fix pylint

* resolve converstation

* remove type from config

* remove outdated validation related to the instance api

* correct diff

* changing last bits

* add missing dot

(cherry picked from commit 58eb94fff3)

Co-authored-by: rchicoli <rchicoli@users.noreply.github.com>
2021-11-20 08:36:04 +01:00
patchback[bot]
c7df82652f change ip4 type to list of str (#3738) (#3757)
* change ip4 type to list of str

* Add several tests and change documentation

* Update changelogs/fragments/1088-nmcli_add_multiple_addresses_support.yml

Co-authored-by: Andrew Pantuso <ajpantuso@gmail.com>

Co-authored-by: Andrew Pantuso <ajpantuso@gmail.com>
(cherry picked from commit 50c2f3a97d)

Co-authored-by: Alex Groshev <38885591+haddystuff@users.noreply.github.com>
2021-11-19 07:27:36 +01:00
patchback[bot]
342a1a7faa Fix collection dependency installation in CI. (#3753) (#3756)
(cherry picked from commit 17b4c6972f)

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-11-19 07:25:26 +01:00
patchback[bot]
17431bd42c CI: Replace RHEL 8.4 by RHEL 8.5 for devel (#3747) (#3749)
* Replace RHEL 8.4 by RHEL 8.5 for devel.

* Install virtualenv.

* Revert "Install virtualenv."

This reverts commit 22ba0d074e.

* Just do another skip...

(cherry picked from commit 26c7995c82)

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-11-17 22:22:46 +01:00
patchback[bot]
eacf663999 listen_ports_facts: Added support for ss (#3708) (#3744)
(cherry picked from commit 245cee0ece)

Co-authored-by: Jan Gaßner <40096303+moonrail@users.noreply.github.com>
2021-11-16 20:06:56 +01:00
patchback[bot]
84a806be08 Add GetHostInterfaces command to redfish_info (#3693) (#3743)
* Add GetHostInterfaces command to redfish_info

Adding a GetHostInterfaces command to redfish_info in order to report the
following:
- Properties about the HostInterface(s) like Status, InterfaceEnabled, etc
- ManagerEthernetInterface (info on BMC -> host NIC)
- HostEthernetInterfaces (list of NICs for host -> BMC connectivity)

fixes #3692

* add fragment

* fixup for linter

* redfish_utils.py cleanup

- Remove unneeded Properties list from get_nic_inventory()
- Remove bogus key variable from get_hostinterfaces()
- Add additional Properties to collect from HostInterface objects

* fixup for stray deletion

(cherry picked from commit 98cca3c19c)

Co-authored-by: Jacob <jyundt@gmail.com>
2021-11-16 20:06:28 +01:00
patchback[bot]
7db5c86dc8 gitlab: clean up modules and utils (#3694) (#3741)
* gitlab: remove dead code in module_utils

* gitlab: use snake_case consistently in methods and functions

* gitlab: use snake_case consistently in variables

* gitlab: fix pep8 indentation issues

* gitlab: add changelog fragment

* gitlab: apply suggestions from code review

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
Co-authored-by: Chris Frage <git@sh0shin.org>

* gitlab: use consistent indentation

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
Co-authored-by: Chris Frage <git@sh0shin.org>
(cherry picked from commit d29aecad26)

Co-authored-by: Nejc Habjan <hab.nejc@gmail.com>
2021-11-16 19:45:45 +01:00
patchback[bot]
1e82b5c580 redfish_config: Add support to configure Redfish Host Interface (#3632) (#3718)
* redfish_config: Add support to configure Redfish Host Interface

Adding another Manager command to redfish_config in order to set Redfish
Host Interface properties.

Fixes #3631

* add fragment

* fixup for fragment filename

* Update plugins/modules/remote_management/redfish/redfish_config.py

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

* Add support for specifying HostInterface resource ID

* Apply suggestions from code review

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

* Update plugins/modules/remote_management/redfish/redfish_config.py

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

* Update changelogs/fragments/3632-add-redfish-host-interface-config-support.yml

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

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

Co-authored-by: Jacob <jyundt@gmail.com>
2021-11-16 19:45:30 +01:00
Felix Fontein
7f6be665f9 Next expected release is 4.1.0. 2021-11-16 09:10:42 +01:00
Felix Fontein
174b00cd29 Release 4.0.2. 2021-11-16 08:07:27 +01:00
patchback[bot]
a7c92f491d Restrict redis version. (#3733) (#3736)
(cherry picked from commit bf7a954f00)

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-11-16 07:30:41 +01:00
Felix Fontein
592cd3747b [stable-4] Announce deprecation of support for Ansible 2.9 and ansible-base 2.10 (#3723)
* Announce deprecation of support for Ansible 2.9 and ansible-base 2.10.

* Update changelogs/fragments/deprecate-ansible-2.9-2.10.yml

Co-authored-by: Brian Scholer <1260690+briantist@users.noreply.github.com>

Co-authored-by: Brian Scholer <1260690+briantist@users.noreply.github.com>
2021-11-16 07:15:24 +01:00
patchback[bot]
4295ee0bb4 Enable counter_enabled.py to support batch mode (#3709) (#3732)
* Enable counter_enabled.py to support serial mode

Enable counter_enabled.py to support batch playbook executions using the serial tag in plays. Currently, the host counter gets reset at the beginning of every task. However, during batch executions we want it to keep track of the previous batch executions and print the host counter based on the previous runs. This proposal keeps track of how many servers have been updated in previous batches and starts the host counter at that tracked value.

```
- hosts: allthethings
  gather_facts: no
  serial:
    - 3
    - 15%
    - 20%
    - 35%
    - 55%
    - 90%
    - 100%
  tasks:
    - name: Ping Hello!
      ping:
        data: "Hello!!!!"
```

* Reset task counter on play start

Reset task counter on play start for batch mode playbook executions.

* Add changelog fragment

* change changelog fragment after feedback

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

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

Co-authored-by: Nabheet Sandhu <nabheet@users.noreply.github.com>
2021-11-15 22:26:19 +01:00
Felix Fontein
7e1ff300f8 Prepare 4.0.2 release. 2021-11-13 15:47:25 +01:00
patchback[bot]
b3ddec2b29 Allow LDAP search to run in check mode (#3667) (#3725)
* Allow ldap search to run in check mode always

* Fix indentions

* Remove Comments and Chg Fragment

* Update changelogs/fragments/3667-ldap_search.yml

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

Co-authored-by: Sebastian Trupiano <sebastian.trupiano@srpnet.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
(cherry picked from commit 115d435d2d)

Co-authored-by: sabman3 <sabman3@aol.com>
2021-11-13 15:27:50 +01:00
patchback[bot]
227f6e333e Rework safety check on size arguments for when LV doesn't exist (#3681) (#3720)
* Rework safety check on size arguments for when LV doesn't exist

* Update changelogs/fragments/3681-lvol-fix-create.yml

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

Co-authored-by: Jake Reynolds <jake.reynolds@bidfx.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 352047314b)

Co-authored-by: jake2184 <jake2184@users.noreply.github.com>
2021-11-13 15:27:35 +01:00
patchback[bot]
94711ca506 Example command has wrong arg in redfish_command (#3711) (#3722)
Example command arg `boot_next` missing the underscore

(cherry picked from commit 4fe5d54b9e)

Co-authored-by: bluikko <14869000+bluikko@users.noreply.github.com>
2021-11-13 14:58:53 +01:00
patchback[bot]
d53052f27a Replace Bash codecov uploader by new Python codecov uploader. (#3713) (#3714)
ci_coverage

(cherry picked from commit 5948809162)

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-11-13 13:21:56 +01:00
patchback[bot]
95d57c338a BOTMETA.yml: add new maintainer to gitlab team (#3696) (#3705)
(cherry picked from commit 18a17acaa4)

Co-authored-by: Andrew Klychkov <aklychko@redhat.com>
2021-11-13 10:37:04 +01:00
patchback[bot]
4fd7a65a52 Fix dummy interface returning changed (#3625) (#3688)
* fix dummy interface bug

* fix dummy interface bug

* Update nmcli.py

* Update nmcli.py

* Update nmcli.py

* Update nmcli.py

* adding tests and requested conditional

* Fix pylint problems and remove 2 lines from previous version of bugfix

* Fix pep8 issue

* add changelog

* Update changelogs/fragments/3625-nmcli_false_changed_mtu_fix.yml

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

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

Co-authored-by: Alex Groshev <38885591+haddystuff@users.noreply.github.com>
2021-11-10 08:00:36 +01:00
patchback[bot]
0e3c1f867d Fix docs issues. (#3682) (#3684)
(cherry picked from commit 146af089e9)

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-11-09 20:28:13 +01:00
Felix Fontein
fa24edf89c Next release is probably 4.0.2. 2021-11-09 18:06:52 +01:00
Felix Fontein
ac3e803a36 Release 4.0.1. 2021-11-09 17:03:04 +01:00
Felix Fontein
8168ddca4f Prepare 4.0.1. 2021-11-09 08:02:15 +01:00
patchback[bot]
cc264be644 Replace Fedora 33 with Fedora 35 for devel tests (#3674) (#3680)
* Replace Fedora 33 with Fedora 35 for devel tests.

* Skip Fedora 35 for reiserfs tests.

(cherry picked from commit fc99893f10)

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-11-09 06:54:06 +01:00
patchback[bot]
9bd2d1ec90 Better handling of base64-encoded values in xattr module (#3675) (#3678)
* Fix exception in xattr module when existing extended attribute's value contains non-printable characters and the base64-encoded string contains a '=' sign

* Added changelog fragment for #3675

* Apply suggestions from code review

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

Co-authored-by: sc-anssi <sc-anssi@users.noreply.github.com>
2021-11-09 06:29:09 +01:00
patchback[bot]
01b2c48161 a_module test: fix crash in case of tombstoning (#3660) (#3662)
* Fix crash in case of tombstoning.

* Extend tests.

(cherry picked from commit c23bbb5c4a)

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-11-04 13:02:18 +01:00
Felix Fontein
a26792418e Next expected release will be 4.1.0. 2021-11-02 07:08:36 +01:00
Felix Fontein
485834526f Release 4.0.0. 2021-11-02 06:23:51 +01:00
Felix Fontein
5e68ea41e9 Prepare 4.0.0 release. 2021-11-02 06:20:21 +01:00
Felix Fontein
29af59822d Revert "Temporarily disable yaml callback tests. (#3651)" (#3657)
This reverts commit 2324f350bc.
2021-11-01 19:12:37 +01:00
Felix Fontein
5b10f8234c Add collection_version lookup (#3633)
* Add collection_verison lookup plugin.

* Document ansible-base 2.10 and ansible-core 2.11 special case.

* Add default for result_not_found.

* Simplify not existing test.

* Move metadata loading to function.

* Update plugins/lookup/collection_version.py

Co-authored-by: Brian Scholer <1260690+briantist@users.noreply.github.com>

* Extend tests.

* Fix tests for ansible-core < 2.12.

Co-authored-by: Brian Scholer <1260690+briantist@users.noreply.github.com>
2021-11-01 19:01:52 +01:00
Felix Fontein
c69810bf04 Add test plugin which allows to query whether a module or action plugin is available (#3628)
* Add test which allows to query whether an action is available.

* Add documentation.

* Fix FreeBSD / macOS compatibility.

* Rename an_action -> a_module.

* Forgot one place.
2021-11-01 19:00:24 +01:00
Alexei Znamensky
9eb638f651 fix modules' output by using publish_cmd (#3655)
* fix modules' output by using publish_cmd

* added changelog frag

* Update changelogs/fragments/3655-use-publish_cmd.yaml

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

* Update changelogs/fragments/3655-use-publish_cmd.yaml

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

* Update changelogs/fragments/3655-use-publish_cmd.yaml

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-11-01 13:53:02 +01:00
Alexei Znamensky
01887bf359 pipx: minor refactor (#3647)
* pipx: minor refactor

* added changelog fragment
2021-11-01 07:59:15 +01:00
Alexei Znamensky
927356dad3 mh/mixins/cmd - added publish_cmd parameter to CmdModuleHelper.run_command() (#3648)
* added publish_cmd parameter to CmdModuleHelper.run_command()

* added changelog fragment

* Update plugins/module_utils/mh/mixins/cmd.py

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-31 20:35:21 +01:00
hklausing
0df41241dd Fixed - TypeError: unexpected keyword argument (#3649)
* Fixed - TypeError: unexpected keyword argument

- File proxmox_group_info.py creates the error "TypeError: 
  get_group() got an unexpected keyword argument \'group\'\r\n'" if a
  group parameter is used.
  Issue is an argument naming conflict. After changing the argument 
  name to 'groupid', as used in method ProxmoxGroupInfoAnsible::get_group,
  testing a Proxmox group name is working now.

* Changelog fragment added for #3649

changelog fragment for TypeError: unexpected keyword argument #3649

* Update changelogs/fragments/3649-proxmox_group_info_TypeError.yml

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-31 20:21:38 +01:00
Maxime Brunet
aaa0f39f72 bitbucket: Support Basic Auth (#2045)
* bitbucket: Support Basic Auth

* Rename username to user

* Document user/password options

* Rename username to workspace

* Deprecate username

* Fix credentials_required error_message

* Fix credentials_required error_message

* Test user/password/workspace options and env vars

* Update a test to use user/password/workspace for each module

* Fix check auth arguments

* Use required_one_of/required_together

* Fix required typo

* Fix fetch_access_token

* Fix tests 🤞

* Switch things up in test_bitbucket_access_key

* Fix username/password are None

* Remove username/password properties, use params directly

* Update plugins/doc_fragments/bitbucket.py

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

* Update plugins/module_utils/source_control/bitbucket.py

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

* Update plugins/module_utils/source_control/bitbucket.py

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

* Update plugins/module_utils/source_control/bitbucket.py

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

* Update plugins/modules/source_control/bitbucket/bitbucket_access_key.py

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

* Update plugins/modules/source_control/bitbucket/bitbucket_pipeline_key_pair.py

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

* Update plugins/modules/source_control/bitbucket/bitbucket_pipeline_known_host.py

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

* Update plugins/modules/source_control/bitbucket/bitbucket_pipeline_known_host.py

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

* Update plugins/modules/source_control/bitbucket/bitbucket_pipeline_variable.py

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

* Update plugins/modules/source_control/bitbucket/bitbucket_pipeline_variable.py

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

* Update plugins/modules/source_control/bitbucket/bitbucket_access_key.py

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

* Update plugins/modules/source_control/bitbucket/bitbucket_pipeline_key_pair.py

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

* Document OAuth/Basic Auth precedence

* Apply suggestions from code review

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

* Remove no_log=False from user argument

* Add changelog fragment

* Correct wording and formatting in changelog

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

* Update changelogs/fragments/2045-bitbucket_support_basic_auth.yaml

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-31 19:09:25 +01:00
Felix Fontein
2324f350bc Temporarily disable yaml callback tests. (#3651) 2021-10-31 18:50:43 +01:00
Alexei Znamensky
bd96616e6f snap_alias - new module (#3642)
* snap_alias - manage snap aliases

* removed extraneous import

* executing the module, the new way

* added link and bot entry

* scaffolding from snap

* completed module + integration tests

* fixed sanity checks

* Update plugins/modules/packaging/os/snap_alias.py

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

* Update plugins/modules/packaging/os/snap_alias.py

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

* Update plugins/modules/packaging/os/snap_alias.py

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

* removed extraneous task from test

* added seealso, removed unused import

* added check_mode + plus check_mode and idempotency tests

* Update plugins/modules/packaging/os/snap_alias.py

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

* Improved RETURN description.

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-31 18:38:21 +01:00
Georg Gadinger
b429c520f5 opennebula: fix error message when renaming an image (#3626)
While porting this module to make use of `pyone` I have overlooked one
attribute.  Luckily the error only occurs when trying to rename an image
to a name that has already been taken.

Instead of telling the user which image ID already uses that name, the
module failed with the following error (along with a huge backtrace):

    AttributeError: 'IMAGESub' object has no attribute 'id'

With this commit the error message is much more obvous again.
2021-10-31 18:37:34 +01:00
Thomas Sjögren
d6e14276c8 add the possibility to restart all supervisorctl programs and groups (#3598)
* add the possibility to restart all supervisorctl programs and groups

Signed-off-by: Thomas Sjögren <konstruktoid@users.noreply.github.com>

* Update changelogs/fragments/3551-supervisor-all.yml

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

* add info about "all" in the name parameter description

Signed-off-by: Thomas Sjögren <konstruktoid@users.noreply.github.com>

* Update plugins/modules/web_infrastructure/supervisorctl.py

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-31 18:36:12 +01:00
nerrehmit
96de25fc94 provide more fitting description for runner timeout (#3624)
* provide more fitting description for runner timeout

* Update plugins/modules/source_control/gitlab/gitlab_runner.py

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

Co-authored-by: Tim Herren <tim.herren@gmx.ch>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-30 16:44:22 +02:00
Felix Fontein
753df78877 Fix CI (#3637)
* Replace yaml.load with yaml.safe_load in unit tests.

* Remove no longer needed loader arg in two instances.
2021-10-30 10:58:48 +02:00
Felix Fontein
3b82a6ff99 In the nightly CI run this test failed. Adjust it to be on the safe side. (#3638) 2021-10-30 10:58:01 +02:00
Pierre Dumuid
ca5a2b291a Bugfix keycloak client do not report changes when there is none (#3610)
* KeycloakClientDiffBugs - Introduce test that passes.

* KeycloakClientDiffBugs - Add test to show that checking of redirect_uri's fails.

* KeycloakClientDiffBugs - (Fix1) Update so that checking of `redirectUris` no longer shows a change.

* KeycloakClientDiffBugs - Add test to show that checking of attributes's fails (sorting issue)

* KeycloakClientDiffBugs - (Fix2) Update so that checking of `attributes` no longer shows a change.

* KeycloakClientDiffBugs - Add test to show that checking of protocol_mappers's fail

* KeycloakClientDiffBugs - (Fix3) Update so that checking of `protocol_mappers` no longer shows a change when there is none.

* Introduce code fragment.

* Update the changelog to be based on the PR instead of the issue.

* Fix the readme

* Fix yaml indentation.

* Fix pep8

* Update changelogs/fragments/3610-fix-keycloak-client-diff-bugs-when-sorting.yml

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

* Update changelogs/fragments/3610-fix-keycloak-client-diff-bugs-when-sorting.yml

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

* Update plugins/modules/identity/keycloak/keycloak_client.py

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

* Remove need for .copy() after making normalise_cr not mutate the dict.

Co-authored-by: Pierre Dumuid <pierre@knowyourdata.com.au>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-30 08:18:31 +02:00
Elie Moreau
38e0d97c8b [Pacman Module] Allow for the pacman repository check to be skipped when it's not needed (#3606)
* Allow for the pacman repository check to be skipped when it's not needed

* Adding a changelog fragment

* Undo the variable rename because the lint doesn't like it

* Update changelogs/fragments/3606-pacman-speed-up-check-if-package-is-installed.yml

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

Co-authored-by: Elie Moreau <emoreau@atlassian.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-30 08:17:45 +02:00
paytroff
cdfc4dcf49 gitlab_project_members: improve project name matching (#3602)
* Update gitlab_project_members.py

The actual search method doesn't accept path with namespace for project_name. If you have many project with same name, this module gitlab_project_members can't work.

* Update gitlab_project_members.py

* Update gitlab_project_members.py

* Update gitlab_project_members.py

* Create 3602-fix-gitlab_project_members-improve-search-method

* Rename 3602-fix-gitlab_project_members-improve-search-method to 3602-fix-gitlab_project_members-improve-search-method.yml
2021-10-30 08:15:12 +02:00
Mikhail Yohman
9fb76efde0 gitlab_project: Add initialize_with_readme option (#3601)
* Add initialize_with_readme option to gitlab_project. Update integration/unit tests.

* Fix pep8

* Revert unit tests

* Update plugins/modules/source_control/gitlab/gitlab_project.py

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

* Update plugins/modules/source_control/gitlab/gitlab_project.py

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

* Update plugins/modules/source_control/gitlab/gitlab_project.py

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

* Move initialize_with_readme to proper spot to only add if project does not exist.

* Update plugins/modules/source_control/gitlab/gitlab_project.py

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-30 08:14:30 +02:00
Alexei Znamensky
40ccd1501b pipx - fixed bug in state=inject (#3611)
* pipx - fixed bug in state=inject

* added changelog fragment

* copy/paste error in the integration test

* replaced injected package with simpler one

* testing force_lang = None

* disable UTF-8 emojis in pipx output

* better way to achieve the same outcome

* Adjsuted the changelog fragment
2021-10-30 08:11:57 +02:00
Waldek Maleska
8ba7fd5d61 fix gitlab_deploy_key task in check mode (#3622)
fixes #3621

* running check mode used to accidentally delete the existing
  ssh key; change it so deletion is skipped in check mode
2021-10-28 20:07:05 +02:00
Kris Budde
3a2f52c1db added module mssql_script (#3557)
* added module mssql_script

* Add changelog fragment

* fixed fragment file (yamllint)

* added me as maintainer

* minor cleanup. (PR comments)

* adjusted for PR comments

- changed key for query results depending on output
- removed "empty" string defaults

* convert unserializable values to string

* python 2 support

* Apply suggestions from code review

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

* updates to docs

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-27 22:38:35 +02:00
Thomas Sjögren
c40db6789a add random_words lookup plugin, based on the xkcdpass module (#3588)
* add random_words lookup plugin, based on the xkcdpass module

Signed-off-by: Thomas Sjögren <konstruktoid@users.noreply.github.com>

* add maintainer in BOTMETA

Signed-off-by: Thomas Sjögren <konstruktoid@users.noreply.github.com>

* Update plugins/lookup/random_words.py

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

* Update plugins/lookup/random_words.py

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

* Update plugins/lookup/random_words.py

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

* Update plugins/lookup/random_words.py

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

* Update plugins/lookup/random_words.py

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

* Update tests/integration/targets/lookup_random_words/test.yml

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

* Update tests/integration/targets/lookup_random_words/test.yml

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

* ignore E402, place imports below documentation

Signed-off-by: Thomas Sjögren <konstruktoid@users.noreply.github.com>

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-27 22:37:28 +02:00
Roberto Moreda
73acdaa489 dnf_versionlock: new module (#3552)
* dnf_versionlock: new module

* dnf_versionlock: fix style in doc

* dnf_versionlock: use check_rc in run_command

* dnf_versionlock: fix style and typos in doc
2021-10-27 22:36:48 +02:00
Victor Martinez
a362879ff6 [opentelemetry][callback] Support loops error handling (#3599)
* [opentelemetry][callback] simplify condition

* [opentelemetry][callback] initial support for loops

* [opentelemetry][callback] support for loops

* [opentelemetry][callback] enrich loop message with action and item

* [opentelemetry][callback] add UTs for get_error_message_from_results

* [opentelemetry][callback] add UTs for enrich_error_message_from_results

* [opentelemetry][callback] add changelog fragment

* Update plugins/callback/opentelemetry.py

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
2021-10-27 07:51:49 +02:00
Victor Martinez
7e1412e5e1 [opentelemetry][callback] transform args attribute in a list of attributes with redacted user/pass in URL values (#3564)
* [callback][opentelemetry] list of attributes for arguments

* [opentelemetry][callback] list of attributes for the args and redact user/pass from http

* [opentelemetry][callback] remove unused imports

* [opentelemetry][callback] fix E713

* [opentelemetry][callback] remove unused static method

* [opentelemetry][callback] remove duplicated functions

* Apply suggestions from code review

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* [opentelemetry][callback] fix ident

* [opentelemetry][callback] add changelog fragment

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
2021-10-24 19:00:00 +02:00
Pierre Dumuid
996dc617ed Keycloak module cleanup and consistency (#3280)
* Consistent Modules - Rename updated_?? to desired_?? in all the keycloak modules.

* Consistent Modules - Rename the comments, and add whitespace so that all the modules are a lot more consistent between each other.

* Consistent Modules - Remove final elif where a final else doesn't exist.

This is to address the inconsistency between the other modules.

Whilst I can see it being more descriptive, there should be a final "else:" to cater if the values is neither 'absent' or 'present'.

* Consistent Modules - Use dict() instead of {} like most of the other keycloak modules.

* Consistent Modules - Update keycloak authentication so that the if ordering is consistent for no-item.

* Consistent Modules - Move the 'Filter and map' process to always occur before getting an existing item.

* Consistent Modules - Be consistent with how to initialse before_?? and set it to dict() if it is None.

* Consistent Modules - Add module.exit_?? in the locations as per the other modules.

* Consistent Modules - Represent result['diff'] using dict(before=.., after=...) as per all the other modules.

* Consistent Modules - Add / Move location of when result['end_state'] is getting defined.

* Consistent modules - Add result['changed'] = False where we do nothing and exit because item exists.

* Consistent Modules - Set the value result['changed'] to True earlier so it shows up when in checking mode only.

* Consistent Modules - test for equality with a dict to assert there was no realm in the first place as per the other modules.

* Consistent Modules - Address the spelling.

* Consistent Modules - keycloak_group - Remove result['group'] as result['end_state'] is the consistent value used in the other modules.

* Consistent Modules - Order the lines in the section, Do nothing and exit consistently.

* Consistent Modules - Add result['end_state'] and still add deprecated `flow` return value.

* Consistent Modules - Add missing return documentation for `msg`.

* Consistent Modules - Tweak whitespace in the RETURN variable.

* Consistent Modules - Add result['group'] in addition to deprecated result['group'] response.

* Consistent Modules - Add return property, 'contains' to address test errors.

* Consistent Modules - Rename updated_?? to desired_?? in new modules since initial PR.

* Consistent Modules - Rename the comments, and add whitespace so that all the (recently added) modules are a lot more consistent between each other.

* Consistent Modules - Make indentation consistent within the response document.

* Consistent Modules - Use B(DEPRECATED) in a seperate line in the description.

* Consistent Modules - Add a lot of full stops to sentences.

* Consistent Modules - Use C(...) and I(...) formatting methods.

* Consistent Modules - Use "on success" everywhere for end_state response documentation.

* Consistent Modules - Update the documents for RETURN.proposed, RETURN.existing, RETURN.end_state to be the same.

* Consistent Modules - Add fragment.

* Remove period after short_description.

* Update changelog fragment.

* Consistent Modules - PRFeedback - Remove `module.exit_json(**result)` within the `Delete` section of the if statement.

There's a exit_json(..) immediately after.

* Consistent Modules - PRFeedback - Use `if not x_repr` instead of `if x_repr == dict()`.

* keycloak_authentication - Add a sample of the output.

* Replace `dict()` with `{}` for all the keycloak modules.

* Add the requested deprecated notices

* Update changelogs/fragments/3280-keycloak-module-cleanup-and-consistency.yml

Co-authored-by: Pierre Dumuid <pierre@knowyourdata.com.au>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-22 07:57:18 +02:00
Andreas Botzner
9b4b175ca3 Added redis_incr module (#3229)
* Added redis_incr module

Added redis_incr module and unit tests for the module.

Added suggested changes to increment_float, increment_int stuff

* rebased to main, version fix and unit test fix

* Renamed module,added check_mode and fixed retun value

* Update .github/BOTMETA.yml

* check_mode fix and version bump

* fix for lower Redis versions

* Update plugins/modules/database/misc/redis_data_incr.py

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-22 07:54:02 +02:00
Nate Coraor
86a22b5ed2 Fix exception in pkgin module when all packages are already installed (#3583)
* Fix exception in pkgin module when all packages are already installed.

* Update plugins/modules/packaging/os/pkgin.py

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

* Add changelog fragment for #3583

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-22 07:47:27 +02:00
Ross Williams
45d3661ccf pkgng: add basic integration tests (#3526)
* pkgng: package reinstallations count as changed

`upgrade_packages()` only looked for the string
"Number of packages to be upgraded", but the
`pkg upgrade` command also reports "Number of packages to be
reinstalled". Reinstallation occurs when package metadata other
than version changes (e.g. build options, single architecture to `*`
architecture). In any other respect, though, a required
reinstallation is the same as an upgrade.

* pkgng: check_mode should count queued actions

Writing tests caught a bug in PR #3393, which enabled
installing more than one package per `pkg` execution.

In converting the module's install/upgrade code to a
queue structure, check_mode got broken because the count
of actions performed was only updated in the `if not check_mode`
block that invokes `pkg`. This two-line change counts
the number of actions in the queue when check mode is
enabled.

* pkgng: add basic integration tests

Test installing a package
Test installing a package into a jail

* pkgng: test with zsh not bash package

Had been using bash package, because it's not
likely to disappear from the package repository
any time soon. Turns out that bash is already
installed on the Ansible community.general
FreeBSD CI VM image, which makes the test fail.

Zsh probably isn't going away any time soon,
either, and likely won't be installed on the
CI image.

* pkgng: remove redundant test for docker container

These tests should be skip/docker, but the test
playbook also redundantly checked whether it was
running in a docker container.

Checking whether `ansible_facts.distribution` is
`FreeBSD` is really sufficient to be sure whether
the test is running in an environment that supports
the `pkgng` module.

* pkgng: add state=absent test

Also renumber `jail=...` test to make diffs less
noisy when adding more non-jailed tests.

* pkgng: add state=latest idemptency test

Add test between state=present and
state=absent that ensures state=latest runs
successfully on an already up-to-date package
with changed=false.

* pkgng: add state=latest test

Including small filesize out-of-date package from
FreeBSD 11 package repository, because FreeBSD 11 is
currently EOL. This test might fail at some point in the
future if the pkg utility in a FreeBSD version > 14
makes breaking changes that prevents it from installing
older package formats.

If that occurs, the fix is to replace
`files/freebsd-release-manifests-20210413__FreeBSD_11.pkg`
with the version of freebsd-release-manifests from the oldest
non-breaking release of FreeBSD, and update the
references to it in tasks/main.yml accordingly.

* pkgng: use hand-generated test package

Instead of relying on a broken-ish installation
of an older package from FreeBSD 11, hand-generate
a package named `zsh` with no contents and a version
number of `0`. It can be installed on any architecture
and any revision of FreeBSD sucessfully, and it will
always be eligible for upgrade.

* pkgng: CI seems to dislike plus-signs in filenames

* pkgng: refactor renaming test package manifests

refactored to make intent of adding '+' sign clearer

* pkgng: refactor upgraded pattern matching

Implement russoz's suggestion to put all
variants in the pattern.

* pkgng: add cached=yes test

Changed idempotency test, because this covers both.

* pkgng: test pkg works on any FreeBSD version

Removing `ansible_distribution_version`, because the
test out-of-date zsh package should install on any
FreeBSD version.

* pkgng: move FreeBSD tasks to imported file

Refactoring tests for more reuse and easier
readability.

* pkgng: refactor tests for task reuse

Several tests need to install an out-of-date package
to test whether upgrades occur successfully, so this
commit refactors out the generation of the test package.

Also, factor out things like the name and path of the
test package so that is more maintainable should the
target test package (currently `zsh`) ever need to
change.

* pkgng: test install multiple packages

Multiple packages should install with a single
invocation of the `pkg` utility.

* pkgng: handle space- and comma-separated lists

The module expects a list of strings in the `name` parameter,
but long-standing documentation showed space- and comma-delimited
lists as a valid way of telling the module to act on multiple
packages. Passing these lists through to the `pkg` command can
have unexpected side-effects of upgrading packages when
`state=present` rather than `state=latest` and could result
in the module reporting the wrong number of packages for each
action performed.

* pkgng: test state=latest for mixed install/upgrade

Test that a list of packages given, one not installed
and one installed but out-of-date are handled correctly.

* pkgng: use YAML lists for multiple packages

I had been following the documentation examples, and
specifiying multiple packages on one line. The right way
to do it is with YAML list syntax.

* pkgng: add test for autoremove=yes

Install package with known dependencies, then
remove it and ask autoremove to run.

* pkgng: test autoremove=yes only on FreeBSD > 12

The CI test runner on FreeBSD 12.0 times out when
downloading large packages.

* pkgng: test jail creation logging less verbose

`ezjail-admin` had been spewing every filename copied
into the jail onto stderr, making the `ansible-test -v`
logs hard to scroll through. Changed it so that ezjail
output only shows up in the ansible task logs if
`ansible_verbosity > 1` (`-vv...`). Full `ezjail-admin`
output is always logged to `/tmp/ezjail.log`.

* pkgng: pass tests when package dependencies change

Tests that install packages with dependencies were failing
when those dependencies were not already installed, because
the count of installed packages was greater than the count
of requested to be installed packages. This change checks
for a count of installed packages that is greater than or
equal to the count of requested to be installed packages.

Example:
  - Test installs packages `zsh` and `fish`
  - `fish` has a dependency on `pcre2`
  - `pkg` reports `Number of packages to be installed: 3`

* pkgng: test annotation for single package

Add/modify/remove annotation for a single package

* pkgng: fix annotation operations

Annotation has been broken at least since the migration to
collections. There are some breaking typos and function argument
omissions in the code with nothing in `git blame` but "Initial commit".

New integration tests uncovered this breakage. Works now.

* pkgng: test multiple annotations

Test multiple annotations specified both in new (YAML list)
syntax and old (comma-delimited) syntax.

Rename some annotation test tags from the single-annotation
tests to make sure that single and multiple annotation tests
don't collide.

* pkgng: test invalid annotate strings

Ensure that some likely to occur, invalid strings
given to the annotate module parameter 1. fail,
2. do not cause an exception, and 3. do not create
any actual annotations on packages.

* pkgng: fix check_mode for annotate

Actions specified in the `annotate` parameter would
always be performed, even if `check_mode=yes`.

This commit fixes `check_mode` for the annotation
functions and adds integration tests to ensure that
check mode is honored in the future.

* pkgng: call module.run_command with list

Instead of calling `run_command` with a formatted
string, call it with a list to maintain safer argument
separation.

Also, introduce a wrapper for `run_command`, `run_pkgng`,
which manages the process environment and some common
command line switches, based upon the module parameters.

Introduced in this commit, also pass annotation values
to `pkg annotate` via stdin, which is safer with long
values than putting them in argv.

* pkgng: update documentation to match annotate type

Missed updating the documentation to match the change
of the annotate parameter from comma-separated string
to list of strings.

* pkgng: fix syntax for Python 2

Seems *args, **kwargs have to be the last
two arguments in Python 2 syntax. CI sanity
tests were failing.

* pkgng: oops, pkgsite should be from closure

I put `pkgsite` as a keyword argument to `run_pkgng()',
which wasn't correct at all and resulted it in capturing
the second positional argument given by any caller.

`pkgsite` should have been `p["pkgsite"]`, coming from the
closure environment of `main()`.

* pkgng: Fix changelog fragment quote formatting

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

* pkgng: add test prepare task

Make sure test environment does not contain the
test package.

* pkgng: make integration test package more flexible

Make integration test package building template-based,
so more flexible if in the future the name of the test package,
currently `zsh`, must change.

* pkgng: convert generator to list for 2.9

Ansible 2.9 can't count items from a generator,
so convert `select` filter output via `list`
before passing to `count`.

* pkgng: Ansible 2.9 has no "false" Jinja2 test

Apparently Ansible 2.9 doesn't have the "false" test
in Jinja2 contexts. Switching to use `rejectattr(...)`
instead of `selectattr(..., "false")`.

* pkgng: test pkgsite parameter

* pkgng: add tests for chroot and rootdir params

Refactor install tasks into an include file so they
can be reused and tested with various parameters.

* pkgng: clean up test package creation

Make pkg json manifest more readable. Create package using
FreeBSD's `pkg create` instead of manually using tar. This
change also simplifies the manifest to a single file for
the integration test role.

* pkgng: fix #3428; install from local file

Fixes a bug in which the module reported failure
when installing from a local (to the target host)
file path.

Fixes #3428

* pkgng: changelog fragment formatting issue

* pkgng: check for all test package extensions

pkg recently changed file extensions, so for the
tests to work on multiple recent versions of FreeBSD,
we must check for `pkg create` output with varying
filename.

* Revert "pkgng: fix #3428; install from local file"

As the module has invoked pkg with the `-g` flag for
at least 7 years, I'm not sure when it was possible
to install packages from files on the target host
filesystem, because pkg rejects file paths when
the `--glob` flag is enabled.

I considered doing a rework of the pkg invocation
to enable good support for installing from local
files, but it looks like more of a job than for this PR.

This reverts commit 5f94eac41f.

* pkgng: Add minor_changes fragment for #3526

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-22 07:32:35 +02:00
Mike Raineri
481fc48e51 Redfish: Do not set the boot source override mode if not provided by the user (#3581)
* Redfish: Do not set the boot source override mode if not provided by the user

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

* Corrected changelog file extension

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

* Update changelogs/fragments/3509-redfish_utils-SetOneTimeBoot-mode-fix.yml

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-22 07:29:26 +02:00
Matyáš Kroupa
e7e2ab94da nmcli: Fix ipv6.dns not being recongnized as list (#3563)
* nmcli: Fix ipv6.dns not being recongnized as list

There was a missing comma on the previous line.

* nmcli: Add changelog fragment for #3563

* nmcli: Update changelogs/fragments/3563-nmcli-ipv6_dns.yaml

Make the fix description more descriptive

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* nmcli: Remove ipv4.route-metric from list-typed properties

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* nmcli: Update fragment 3563 with ipv4.route-metric bug

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
2021-10-21 08:05:00 +02:00
Felix Fontein
a68445486e Remove and redirect all infoblox/nios content (#3592)
* Remove and redirect all infoblox/nios content.

* Remove ignore.txt entries.

* Update BOTMETA.
2021-10-21 08:02:06 +02:00
Mike Raineri
6580e7559b Redfish: perform manager network interface configuration even if property is missing (#3582)
* Redfish: perform manager network interface configuration even if property is missing

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

* Update changelogs/fragments/3404-redfish_utils-skip-manager-network-check.yml

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-20 17:26:15 +02:00
Victor Martinez
d9e8724b1d [callback][opentelemetry] enrich span with http attributes (#3558)
* [callback][elastic] enrich span with http attributes

* [callback][opentelemetry] fix linting

* [callback][opentelemetry] fix UTs

* [opentelemetry][changelog] add fragment for the service map feature

* Update plugins/callback/opentelemetry.py

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* [opentelemetry][callback] remove comments

* [opentelemetry][callback] fix UTs

* [opentelemetry][callback] return the value

otherwise a None value returns ParseResultBytes when using urlparse(None)

* [opentelemetry][callback] fix wrong parameter order

* [opentelemetry][callback] support for no interpolated URLs

* [opentelemetry][callback] support for URLs without interpolation in the hostname

* [opentelemetry][callback] fix linting

* Update changelogs/fragments/3558-callback_opentelemetry-enrich_service_map.yml

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

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-20 17:24:14 +02:00
Rossen
ef0b83fdf1 ipa_group: add append option (#3545)
* ipa: add append parameter to modify_if_diff

* ipa_group: add state: append

* ipa_group: rework append to an option instead of another state

* ipa_group: append default=no

* ipa_group: add change fragment for new append option

* ipa_group: restore descriptions for group and user

* ipa_group: re-add missed quotation mark

* ipa_group: set default for append in
argument_spec

* ipa_group: add .yml ext to fragement file

* ipa_group: corrections to append description

* ipa_group: refine change fragement text

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

* ipa_group: use correct macros in option descriptions

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

* ipa_group: include append in user and group descriptions

* ipa_group: add version_added

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-19 13:36:08 +02:00
Felix Fontein
e8c37ca605 Remove non-working example. (#3571) 2021-10-18 22:51:26 +02:00
Premkumar Subramanian
02c534bb8e Fixed typo in homebrew documentation (#3577)
Fixed typo in community.general.homebrew documentation
2021-10-18 22:43:57 +02:00
Vitaly Khabarov
3731064368 Misc doc issues (#3572)
* Add names to tasks in oneview module examples

* Fix task name in github_webhook module example

* Fix trailing whitespace

* Add changelog fragment

* Remove changelog fragment
2021-10-18 13:53:14 +02:00
Felix Fontein
c3813d4533 Use correct FQCN. (#3573) 2021-10-17 16:05:15 +02:00
Sergey
191d2e08bb Fix bug with returning results in IPA role (#3561)
* Fix bug with returning results in IPA role

Fix #3560

* Add changelog

* Fix typo in changelog

* Update changelogs/fragments/3561-fix-ipa-host-var-detection.yml

Co-authored-by: Brian Scholer <1260690+briantist@users.noreply.github.com>

* Update changelogs/fragments/3561-fix-ipa-host-var-detection.yml

Co-authored-by: Brian Scholer <1260690+briantist@users.noreply.github.com>

* Update changelogs/fragments/3561-fix-ipa-host-var-detection.yml

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

Co-authored-by: Brian Scholer <1260690+briantist@users.noreply.github.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-16 20:45:48 +02:00
Felix Fontein
249d490f10 Remove centos8 for devel from CI. (#3565) 2021-10-16 08:33:38 +02:00
Dominik Wombacher
71ea99d10f ssh_config: Add 'forwardagent' option (#3495)
* Integration Tests for Options added, includes 'proxycommand'

* New option 'forwardagent' added to integration tests

* Missing double quotes added to 'forwardagent' values to enforce handling as string

* New option 'forwardagent' added

* yamllint error resolved

* 'forwardagent' type changed from str to choices (yes/no)

* Changelog added

* correct typo

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

* version info added to new option

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

* fix(ssh_config): option name to snake_case, type str to bool

* fix(ssh_config): convert bool true/false to str yes/no

* fix(ssh_config): rename option to 'forward_agent' in integration test

* fix(ssh_config): args key 'forwardagent' renamed to 'forward_agent'

* fix(ssh_config): 'else' replaced with 'if' statement to cover case when value is 'None'

* increase version_added to 4.0.0

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

* simplify if statement for True/False to yes/no mapping

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

* update comment to better describe functionality

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

* fix(ssh_config): avoid overwrite of existing option in case of None value

* test(ssh_config): case added to verify no changes on existing option if not given in playbook

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-14 21:24:23 +02:00
Victor Martinez
18f8195983 [callback][elastic] enrich stacktrace errors (#3556)
* [callback][elastic] enrich stacktrace errors

* [callback][elastic] add changelog fragment
2021-10-14 21:19:02 +02:00
Felix Fontein
d25554df9d Improve opkg module (#3554)
* Allow name to be a YAML list as well, and be more lenient when splitting strings by comma.

* General docs improvements.
2021-10-14 21:14:32 +02:00
Felix Fontein
9546bbb55e Remove deprecated options, aliases and defaults (#3461)
* Remove deprecated options, aliases and defaults.

* Add changelog fragment.

* Small fixes.

* Apply suggestions from code review

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Lint.

* Update plugins/modules/system/xfconf.py

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

* Bump galaxy version to 4.0.0.

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-10-12 13:56:15 +02:00
Anand Victor
7038812465 Bugfix issue2692 logstash callbackmodule with no attribute options (#3530)
* Update logstash.py

replacing _options with context.cliargs

* Create 2692-logstash-callback-plugin-replacing_options

logstash callback plugin replace _option with context.CLIARGS

* Rename 2692-logstash-callback-plugin-replacing_options to 2692-logstash-callback-plugin-replacing_options.yml

missed out the extenstion

* Update logstash.py

context imported

* Update 2692-logstash-callback-plugin-replacing_options.yml

dict to string

* Update changelogs/fragments/2692-logstash-callback-plugin-replacing_options.yml

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-11 22:55:18 +02:00
Felix Fontein
316adebd68 Improve contributing instructions (#3541)
* Improve contributing instructions.

* Update CONTRIBUTING.md

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
2021-10-11 22:47:56 +02:00
linxside
ed2c1e4ac9 terraform: add parallelism parameter (#3540)
* terraform: add parallelism parameter

* terraform: add parallelism parameter version
2021-10-11 22:44:20 +02:00
Laurent Paumier
d44c85aa90 keycloak_identity_provider: Fix mappers update (#3538)
* set identityprovideralias by default

* refactor mappers change detection

* fix sanity check

* update tests

* add changelog fragment

* Update changelogs/fragments/3538-fix-keycloak-idp-mappers-change-detection.yml

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-11 22:43:50 +02:00
Phillipe Smith
9772485d3c Add new modules rundeck_job_run and rundeck_job_executions_info (#3521)
* Add new module rundeck_job_run

* Add new module rundeck_job_executions_info

* Removed supports_check_mode

* Fix supports_check_mode

* Fix version_added

* Fixes for PR#3521

* Fix default value for loglevel in the doc

* Fix job_status_check loop

* Add proposed changes in PR#3521

* Add proposed changes in PR#3521

* Change executions_info output to executions

* Add rundeck integration tests

* Fix rundeck integration test

* Add more tests to rundeck integration tests

* Update job_options doc

* Add more tests to rundeck integration tests

* Add more examples to rundeck_job_run doc

* Add proposed fixes for PR#3521

* Add proposed fixes for PR#3521

* Fix job_options

* Add proposed changes for PR#3521
2021-10-11 06:55:47 +02:00
Aoife Finch
8ece0d3609 macports: add stdout and stderr to status (#3499) (#3500)
* macports: add stdout and stderr to status (#3499)

* Add changelog fragment

* Update changelogs/fragments/3500-macports-add-stdout-and-stderr-to-status.yaml

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

Co-authored-by: Aoife Finch <aoife@finch.ink>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-11 06:55:09 +02:00
Victor Martinez
905f4dcfa2 Add elastic callback plugin (#3380)
* Add elastic callback plugin

* Capture task failures

* Catch errors and add UTs

* Skip 3.5< python versions and install dependency

* fix lint

* Fix linting

* Fix linting

* Add botmeta

* Apply suggestions from code review

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

* It's not required

* As suggested in the code review OrderedDict has been added to the Python stdlib since version 2.7

* Update plugins/callback/elastic.py

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-11 06:54:14 +02:00
Laurent Paumier
9de01e04f2 keycloak_role: quote role name in urls (#3536)
* quote role name in urls

* add changelog fragment

* Update changelogs/fragments/3536-quote-role-name-in-url.yml

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* fix linefeeds

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
2021-10-09 13:38:02 +02:00
Felix Fontein
d1f820ed06 Fix shellcheck error. (#3531) 2021-10-08 15:09:47 +02:00
Ross Williams
293c7a9fb3 Pkgng many packages one command (#3393)
* pkgng: join package list into one command

Change the pkgng module so all packages being
installed (or upgraded) are acted on in one
command (per action). This will make installs
and upgrades a bit faster, because pkg will be
invoked fewer times per module run. More important,
module actions will be more atomic, making it less
likely that some packages are acted on because they
appear earlier in the argument list.

This change also improves the status reporting of
packages acted on, specifying the number of packages
for each action (install or upgrade).

* pkgng: make upgrade check lazily evaluated

Make upgrade_available an inner function so that the
if statement that checks whether installed packages
are up-to-date only runs the upgrade check on packages
that are already installed. This gets lazily evaluated
because of boolean operator short-circuiting:
https://docs.python.org/3.8/library/stdtypes.html#boolean-operations-and-or-not

Previously, the module would always check for upgrades,
even for not-installed packages, when running with
`state=latest`.

* pkgng: add changelog fragment

* pkgng: Apply changelog suggestions from code review

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

* pkgng: resolve pep8 style issue

Remove inline function. It's purpose would be confusing for
future maintainers, and someone refactoring it to a variable,
with good intentions, would introduce a performance regression.

Including the `query_update()` call in the if expression makes
the intent more legible and still ensures lazy evaluation of the
function call if the first `and` is `False`.

* pkgng: Fix changelog fragment syntax issue

Need to escape quotes so YAML doesn't eat them

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

* pkgng: Improve output message English grammar

Make word "package" plural only if reporting on more than one package

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-08 07:41:56 +02:00
Dominik Wombacher
f0fcb221cd zypper_repository: Improve .repo file idempotency (#3474)
* If repo option points to .repo file, download for later parsing

* Parse downloaded .repo file content (ini format)

* Validate downloaded file, map values to repodata, workaround to ignore old .repo related code

* Integration Test adjusted to install python package 'requests' first

* Revert "Integration Test adjusted to install python package 'requests' first"

This reverts commit 0d18352c2238d098831ba6d59b66e731fa8f0cd9.
Not allowed to introduce new dependencies at this point, module_utils usage required

* Remove python 'requests' dependency, using 'fetch_url' and 'to_text' from 'ansible.module_utils' instead

* Prefer alias (name) if given instead repo (url)

* If gpgkey was given in .repo file ensure key get automatically imported

* ConfigParser Import made Python2 compatible

* New .repo code moved below existing run-time parameters checks to keep previous logic

* Obsolete workaround removed

* two pylint/pep8 errors fixed

* name added to autorefresh assert

* Missing assert for 'Delete test repo' added

* name added to priority option assert

* name added to check repo is updated by url assert

* name added to check repo is updated by name assert

* name added to check add a repo by releasever assert

* name added to check remove added repo assert

* name added to check add a repo by basearch assert

* name added to check remove added repo #2 assert

* Bugfix to avoid 'KeyError' Exception in if statements

* Refactoring of configparser related code, usage of module_utils, py2 compatibility

* Removal of some leftover from earlier testing

* Integration tests for add/remove repositories by url to .repo file added

* Additional name added to list of test repos that has to be removed

* Test added to verify cleanup of local .repo file after removal via zypper

* Changelog fragment related to PR #3474 added

* yamllint error resolved

* Refactoring to reduce indentation and removal of else statements

* Integration tests added for loading .repo file from local path

* Test .repo file added

* Dependency to setup_remote_tmp_dir added

* New entry added to 'remove repositories added during test'

* Support for .repo file from local path

* Changelog: Ref to https://github.com/ansible-collections/community.general/issues/3466 added

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-08 07:40:30 +02:00
Greg
80bb42325b [ufw] Insert or delete biased when deletion enabled - as for append or delete. (#3514)
* [ufw] Insert or delete biased when deletion enabled - as for append or delete.

* [ufw] Insert or delete biased when deletion enabled - as for append or delete.

* [ufw] Insert or delete biased when deletion enabled - as for append or delete.

* [ufw] Insert or delete biased when deletion enabled - as for append or delete.

* [ufw] Insert or delete biased when deletion enabled - as for append or delete.

* [ufw] Insert or delete biased when deletion enabled - as for append or delete.

* [ufw] Insert or delete biased when deletion enabled - as for append or delete.

* [ufw] Insert or delete biased when deletion enabled - as for append or delete.
2021-10-07 15:31:38 +02:00
Victor Martinez
3a460751a4 [opentelemetry][callback] add option to support enabling plugin in the CI (#3498)
* [opentelemetry][callback] add option to support enabling plugin in the CI only

* [opentelemetry][callback] add changelog fragment

* Apply suggestions from code review

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* [opentelemetry][callback] use enable_from_environment

* Apply suggestions from code review

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

* [opentelemetry] ensure the value is true otherwise the plugin is not enabled

* [opentelemetry][changelog] update entry with the new option

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-07 15:31:08 +02:00
Victor Martinez
e22fff2b12 [opentelemetry][callback] enrich stacktrace errors (#3496)
* [opentelemetry][callback] refactor get_error_message and add UTs

* [opentelemetry][callback] enrich exception with msg, exception and stderr fields

* [opentelemetry] fix linting

* [opentelemetry][callback] add changelog fragment

* Apply suggestions from code review

Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* [opentelemetry][callback] chore: remove comment

* [opentelemetry][callback] refactor tests

* [opentelemetry] refactor UTs

Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
2021-10-07 06:59:03 +02:00
Frank Dornheim
57e5f8c7be lxd_container: improvements to the comments (#3520)
* improvements to the comments

* next documentation improvements

Co-authored-by: Frank Dornheim <“dornheim@posteo.de@users.noreply.github.com”>
2021-10-07 06:57:45 +02:00
Alexei Znamensky
f1807d3323 pipx - new module (#3507)
* pipx - new module

* using python instead of python3

* removed ensure_path as it is unused

* ensuring we are running the same python as Ansible

* changed the last solution to adding a pipx_path parameter to the module, with a sensible default

* added docs for the new parameter

* changed param name to executable, and customized it for Darwin

* use executable if passed, otherwise use python -m pipx

* minor update

* added examples

* Update plugins/modules/packaging/language/pipx.py

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

* Update plugins/modules/packaging/language/pipx.py

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

* Update plugins/modules/packaging/language/pipx.py

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

* tests names 324 -> 3.24.0

* ensure tox is uninstalled by the beginning of the test

* Renamed option+suggestions from PR

* improved idempotency

* fixed sanity

* fixed test

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-06 07:01:54 +02:00
Jonathan Piron
0bc4518f3b Fix: gitlab_deploy_key idempotency (#3473)
* Fix: gitlab_deploy_key idempotency

The module was not retrieving all the deploy keys leading to non
idempotency on projects with multiple deploy keys.
SEE: https://python-gitlab.readthedocs.io/en/stable/api-usage.html#pagination

* Update changelogs/fragments/3473-gitlab_deploy_key-fix_idempotency.yml

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

Co-authored-by: Jonathan Piron <jonathanpiron@gmail.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-04 21:03:31 +02:00
Andreas Botzner
e95f63b067 Proxmox tasks module (#3226)
* Started creating Unit tests for Proxmox Tasks module

* Tried really hard to get the mock to work

* unit tests  for the module

* Fixed symslink and permissions

* Suggested changes and more unit tests

* Fixed isFalse

* Apply suggestions from code review

* Update plugins/modules/cloud/misc/proxmox_tasks_info.py

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-03 22:21:33 +02:00
Felix Fontein
106856ed86 Fix OSX 10.11 CI runs (#3501)
* Restrict to OSX 10.11 tests.

* See whether updating brew helps.

* Skip archive task for OSX.

* Refactor homebrew task to make changing the package name easier.

* Revert "See whether updating brew helps."

This reverts commit 8eceb9ef1f.

* Replace xz by gnu-tar.

* Uninstall first.

* Skip iso_extract task for OSX.

* Revert "Restrict to OSX 10.11 tests."

This reverts commit 81823d2f97.

* ci_complete
2021-10-02 21:18:03 +02:00
Felix Fontein
5895e50185 yaml callback: prevent plugin from modifying PyYAML (#3478)
* Prevent yaml callback from modifying PyYAML.

* Fix changelog fragment.

* Update changelogs/fragments/3478-yaml-callback.yml

Co-authored-by: Brian Scholer <1260690+briantist@users.noreply.github.com>

Co-authored-by: Brian Scholer <1260690+briantist@users.noreply.github.com>
2021-10-01 22:42:39 +02:00
Victor Martinez
774b2f642b [opentelemetry] minor changes in the import, docs and exception (#3450)
* OrderedDict has been added to the Python stdlib since version 2.7

* Docs: cosmetic change in the python lib

* See https://github.com/ansible/ansible/issues/75726

* Add changelog fragment

* Apply suggestions from code review

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-10-01 14:39:22 +02:00
Rasdva3
316e1d6bf2 Update redfish_info.py (#3485)
* Update redfish_info.py

* Update plugins/modules/remote_management/redfish/redfish_info.py

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

* Update plugins/modules/remote_management/redfish/redfish_info.py

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

* Update plugins/modules/remote_management/redfish/redfish_info.py

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

* Update plugins/modules/remote_management/redfish/redfish_info.py

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

* Update plugins/modules/remote_management/redfish/redfish_info.py

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

* Update plugins/modules/remote_management/redfish/redfish_info.py

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

* Update plugins/modules/remote_management/redfish/redfish_info.py

* Update plugins/modules/remote_management/redfish/redfish_info.py

* Update plugins/modules/remote_management/redfish/redfish_info.py

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>
2021-10-01 14:31:04 +02:00
Felix Fontein
0d3c4de6a2 devel dropped support for Python 2.6. (#3487) 2021-10-01 12:50:00 +02:00
Zach Biles
a14392fab0 fix structure xcc_redfish_command (#3479)
* adhere to proper task structure

* add changelog fragment

* return code formatting to original

* remove unnecessary fragment
2021-09-30 16:24:48 +02:00
Felix Fontein
3fee872d58 Stick to community.crypto 1.x.y for ubuntu1604. (#3470) 2021-09-29 19:35:50 +02:00
Felix Fontein
d0f82e2c27 Temporarily rename 'ansible-core version' back to 'Ansible version' to make bot happy. 2021-09-29 07:00:43 +02:00
Pan Luo
7cfdc2ce8c Copy the permissions along with file for jboss module (#3426)
* Copy the permissions along with file for jboss module

Issue: The deployment file is copied with file content only. The file
permission is set to 440 and belongs to root user. When the
JBossI(Wildfly) server is running under non root account, it can't read
the deployment file.

With is fix, the correct permission can be set from previous task for JBoss
server to pickup the deployment file.

* Update changelogs/fragments/3426-copy-permissions-along-with-file-for-jboss-module.yml

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
2021-09-29 06:51:18 +02:00
Sreekanth H
53fc2c477b nmcli: amended the routing-rules4 key values as list (#3401)
* Updated nmcli.py

Amended the routing-rules4 values as list. By this we could add the entries for "routing_rules4" in the form of a list .

* Update nmcli.py 

Fixed typo in line #1701

* 3395-nmcli-needs-type.yml

routing_rules4 module argument is currently accepting only string elements. In order to accept multiple values, amended the type of routing_rules4 as list.

* nmcli: amended the routing-rules4 key values as list

routing_rules4 module argument is currently accepting only string elements. In the case of adding multiple entries to routing_rules4, we need to accept values as list.

* Added 3401-nmcli-needs-type.yml

routing_rules4 module argument is currently accepting only string elements. In the case of adding multiple entries to routing_rules4, we need to accept values as lists

* Amended type to 'minor_changes' 

Amended type to 'minor_changes'  from 'bug_fixes'

* routing_rules4 to a list of element str

nmcli.py - routing_rules4 to a list of element str

* Update changelogs/fragments/3401-nmcli-needs-type.yml

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

* nmcli: allow routing-rules4 key values as list

* nmcli: amended the routing-rules4 key values as list

* nmcli: amended the routing-rules4 key values as list

* nmcli: amended the routing-rules4 key values as list

* test_nmcli: amended whitespaces

* Update 3401-nmcli-needs-type.yml

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-09-29 06:49:49 +02:00
Felix Fontein
71a655193c Update botmeta sanity test to accept notifications. 2021-09-28 22:39:34 +02:00
David Moreau Simard
845c406419 Enable ansibullbot notifications in issues and PRs (#3462)
The more recent version of Ansibullbot defaults notifications to false.
We need to set it to true so it can notify contributors and maintainers.
2021-09-28 22:37:57 +02:00
Felix Fontein
d6a1df3706 Split up 'Ansible version' in issue templates into ansible-core version + community.general version. (#3458) 2021-09-28 16:33:35 +02:00
Kristian Feldsam
806f1ea3c9 Added OpenNebula inventory plugin (#810)
* Added OpenNebula inventory plugin

Signed-off-by: Kristián Feldsam <feldsam@gmail.com>

* Apply suggestions from code review

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

* Apply suggestions from code review

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

* Removed matching inventory yaml files ending with "one"

Too general word

* Apply suggestions from code review

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

* Apply suggestions from code review

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
Signed-off-by: Kristian Feldsam <feldsam@gmail.com>

* Added BOTMETA

Signed-off-by: Kristian Feldsam <feldsam@gmail.com>

* Moved import

Signed-off-by: Kristian Feldsam <feldsam@gmail.com>

* Fix indentation problem

Signed-off-by: Kristian Feldsam <feldsam@gmail.com>

* Added group_by_labels, refactored so can be unit tested

Signed-off-by: Kristian Feldsam <feldsam@gmail.com>

* Added unit tests

Signed-off-by: Kristian Feldsam <feldsam@gmail.com>

* Removed blank line

Signed-off-by: Kristian Feldsam <feldsam@gmail.com>

* Apply suggestions from code review

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

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>
Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-09-28 16:32:15 +02:00
Felix Fontein
d96b85af9f Update CI matrix to include ansible-core's stable-2.12 branch (#3445)
* Update CI matrix to include ansible-core's stable-2.12 branch.

* Adjust README.

* Fix stage names.

* Avoid requirements clash.

* Thin matrix for older Ansible versions.
2021-09-28 15:35:33 +02:00
Frank Dornheim
ef07f9b9ff Enable deprecaded message for ignore_volatile_options (#3429)
* enable deprecate message for ignore_volatile_options

* fix E128

* add frament 3429

* remove default value and modify the resulting checks
spelling fixes
bump version for deprecated messge

* fix spelling and depricated version

Co-authored-by: Frank Dornheim <“dornheim@posteo.de@users.noreply.github.com”>
2021-09-28 07:07:55 +02:00
Chris Frage
1bb2ff5128 Fix require_two_factor_authentication can't be null (#3453)
* fix: require_two_factor_authentication default=false

* chore: add changelog fragment

* docs: require_two_factor_authentication default value

* fix: don't send require_two_factor_authentication null value

* chore: fix changelog
2021-09-27 21:50:21 +02:00
Frederic Werner
ba2917a7dc chore: add deprecation warning for gitlab group membership (#3451)
* chore: add deprecation warning

* chore: add deprecation message, version and collection

* chore: add changelog fragment

* docs: add deprecation info

* fix: max line length and whitespace

* fix continuation line under-indented

* Update changelogs/fragments/3451-gitlab-group-member-deprecate-name-and-path.yml

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

* Update plugins/modules/source_control/gitlab/gitlab_group_members.py

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-09-27 21:49:52 +02:00
Chris Frage
b6b7601615 Fix: GitLab API searches always return first found match (#3400)
* fix: return correct group id
match only full_path or name

* chore: add changelog fragment

* fix: indentation multiple of four

* refactor: use two loops

* fix: typo of group id

* fix: changelog fragment
2021-09-26 18:59:39 +02:00
Ricardo Sanchez
43a9f09a17 open-iscsi: adding mutual authentication support and updating authentication parameters description (#3422)
* Adding mutual athentication support and changing doucumentation about authentication credentials

* Removing blank line with whitspaces

* Update plugins/modules/system/open_iscsi.py

Adding version_added to node_user_in parameter

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Update plugins/modules/system/open_iscsi.py

adding version_added attibute to new parameter password_in

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Update plugins/modules/system/open_iscsi.py

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Adding changelog fragment for #3422

* Rename 3422-open-iscsi-mutual-authentication-support.yam to 3422-open-iscsi-mutual-authentication-support.yaml

* Update changelogs/fragments/3422-open-iscsi-mutual-authentication-support.yaml

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Update changelogs/fragments/3422-open-iscsi-mutual-authentication-support.yaml

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
2021-09-26 13:38:17 +02:00
Gaetan2907
147ca2fe66 Keycloak: Fix bug on keycloak_authentication, requirement not always updated (#3330)
* Fix diff mode when updating authentication flow with keycloak_authentication module

* Update documentation of create_or_update_executions function (return tuple instead of dict)

* Fix: Update requirement when new exex created

* Add changelog fragment

* Update changelogs/fragments/3330-bugfix-keycloak-authentication-flow-requirements-not-set-correctly.yml.yml

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

* Update changelogs/fragments/3330-bugfix-keycloak-authentication-flow-requirements-not-set-correctly.yml.yml

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

* Edit requirement of sublow

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-09-26 13:30:29 +02:00
Felix Fontein
3715b6ef46 Diable netcat conflict in zypper tests as one package seems to be no longer available. (#3438) 2021-09-25 17:16:22 +02:00
Felix Fontein
d0563e34a6 grpcio takes 7 minutes to build on Python 3.10 - make sure it's not installed indirectly. (#3435) 2021-09-25 16:55:09 +02:00
Felix Fontein
935348ae78 Fix CI (#3430)
* Restrict to unit tests with devel (to be reverted later).

* Restrict lxml for Python 2.6.

* Revert "Restrict to unit tests with devel (to be reverted later)."

This reverts commit d0d87a8a0f.
2021-09-25 08:43:16 +02:00
Felix Fontein
0d2bcf545e Prepare ansible-core devel branch version bump that is planned for later today. 2021-09-24 18:46:14 +02:00
Hartwig Hauschild
ae6cbc2d82 mail: adding capability to specify ehlo hostname (#3425)
* Adding capability to specify ehlo hostname

* Fixing default for ehlohost

the CI did not like "None" as default in the documentation,
judging from the rest of the definitions omitting that seems to be right

* Update plugins/modules/notification/mail.py

Proper spelling in documentation

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Adding Changelog Fragment

* Update changelogs/fragments/3425-mail_add_configurable_ehlo_hostname.yml

Proper phrasing in changelog

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* integration-test for ehlohost parameter

* proper description, increased async-time

changed body of ehlohost-mail to reflect ehlohost
increased async from 30 to 45 as CI failed because
smtp was already down.

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
2021-09-24 05:30:14 +00:00
Andrew Klychkov
e1cdad3537 Update README.md (#3402)
* Update README.md

* Update README.md

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

* Fix the link

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-09-21 10:02:01 +02:00
Felix Fontein
98d071f61e Make ready for split-controller testing in ansible-core (#3345)
* Accept context/ in aliases.

* Mark ansible_galaxy_install test as context/controller.

* Fix interfaces_file test.

ci_complete

* Install pyone dependency.

ci_complete
2021-09-21 08:16:42 +02:00
Frank Dornheim
8e7d49c1c6 lxd_container: do not ignore volatile configs by option (#3331)
* do not ignore volatile - fix #2466

* remove unnecessary checks

* fix ansible-tests sanity

* fix access to the option: ignore_volatile_options

* add fragment

* fix quotation marks error

* fix review findings

* fix sanity error

* fix description - in yaml examples use true not True
comment out the deprecate message

* remove "default=True" at ignore_volatile_options
fix spelling

* fix sanity error that ignore_volatile_options have no default value

* undo changes. add defaut value and remove keyword at dict.get()

* fix sanity error

* small spelling fixes

* change text for fragment

* Fix description sentence.

Co-authored-by: Frank Dornheim <“dornheim@posteo.de@users.noreply.github.com”>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-09-20 20:31:26 +02:00
Andreas Botzner
424af85929 Added redis_data module (#3230)
* Added redis_set module

Added redis_set module and unit tests for the new module.
Applied suggested changes and removed redis_del in favor of state
option.
Also added redis utility class that handles connection.

* Typos, added version and BOTMETA

* Fixed import error checking

* Fixed Unit tests

* Docfix and return consistency

* Added Check Mode

* Update plugins/modules/database/misc/redis_data.py

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-09-20 19:47:23 +02:00
Alexei Znamensky
2ad7ed4f83 kernel_blacklist - revamped the module (#3329)
* kernel_blacklist - revamped the module

* file default and setting "lines" when file does not exist

* added changelog fragment

* added change in arg_spec to the documentation block

* Update plugins/modules/system/kernel_blacklist.py

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

* Update plugins/modules/system/kernel_blacklist.py

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

* Update plugins/modules/system/kernel_blacklist.py

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

* fixed: initialize self.pattern before self.var.is_blacklisted

* File writing recoded

* added try/finally for the file

* multiple changes:

- fixed case when last line of the existing file has no newline char
- added integration tests

* PR: integration test now using remote_tmp_dir

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-09-20 19:39:35 +02:00
Laurent Paumier
2589e9a030 Add keycloak_user_federation module (#3340)
* new module

* fix unit tests

* fix documentation

* more fixes

* fix linefeeds

* Apply suggestions from code review

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

* use true/false instead of True/False

* Apply suggestions from code review

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

* fix result content + rename variable

* urlencode parameters

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-09-20 19:19:42 +02:00
Matthew Martin
02d0e3d286 openbsd_pkg: Fix KeyError (#3336)
If package installation has an error after the package is install (e.g.
when running tags), then there will be output on stderr and the fallback
regex will match; however, since pkg_add exited non-zero, changed is
never added as a key to the dictionary. As a result the code at the end
of main that checks if anything has changed raises a KeyError.
2021-09-20 19:19:04 +02:00
Chris Frage
9ce1009643 Add require_two_factor_authentication property to gitlab group (#3367)
* feat: add require_two_factor_authentication property

* chore: add changelog fragment

* chore: add gitlab_group test tasks

* chore: add gitlab tests

* chore: add gitlab group tests

* docs: apply suggestions

* fix: removing default value
2021-09-20 06:55:43 +02:00
Chris Frage
e48f9fdf74 Add gitlab_project CI/CD properties (#3379)
* feat: add ci_config_path property

* feat: add shared_runners_enabled property

* chore: add changelog fragment

* docs: add missing dot

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* docs: ci_config_path change description

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
2021-09-20 06:54:43 +02:00
Alexei Znamensky
7aae8d5386 Interfaces_file - improvements (#3328)
* pythonific!! no camel cases, bitte

* simplified iface attributes parsing

* some improvements, passing tests

* simplified set_interface_option()

* further simplifications

* remove unreachable stmt

* pythonified a file open

* added changelog fragment

* adjustment per PR

* PR: fixed the auto- case

* PR: added testcase and chglog frag for the misleading change report

* extra line removed

* integration is not destructive
2021-09-19 13:44:37 +02:00
Cliff Hults
8ab96d9533 Icinga2 inventory plugin (#3202)
* Added Icinga2 inventory plugin

* Added Icinga2 inventory plugin

* Linting

* Added tests

* Linting

* Linting

* Added tests

* Added tests for icinga2 inventory

* Added tests for icinga2 inventory

* Added tests for icinga2 inventory

* Added tests for icinga2 inventory

* Added tests for icinga2 inventory

* Added tests for icinga2 inventory

* Added tests for icinga2 inventory

* Added tests for icinga2 inventory

* Added tests for icinga2 inventory

* Added tests for icinga2 inventory

* Added tests for icinga2 inventory

* Added tests for icinga2 inventory

* Added tests for icinga2 inventory

* Added tests for icinga2 inventory

* Added tests for icinga2 inventory

* Added tests for icinga2 inventory

* Added tests for icinga2 inventory

* Added tests for icinga2 inventory

* Added tests for icinga2 inventory

* Added tests for icinga2 inventory

* Added tests for icinga2 inventory

* Added tests for icinga2 inventory

* Added tests for icinga2 inventory

* Resolved reviews and added host filters

* Linting

* Fixing yaml for example and updating tests

* Updating test data

* Fixing pep8 indentations

* Missed copywriting

* Missed copywriting

* Updated documentation grammar

* Removing Cacheable class and cleanup

* Update plugins/inventory/icinga2.py

* Update plugins/inventory/icinga2.py

* Bump version number

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

* Update plugins/inventory/icinga2.py

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-09-18 15:19:41 +02:00
Max Bidlingmaier
7a2efb4775 Get behavior of gitlab_project_members to the one of gitlab_group_members (#3319)
* Initial change to get behaviour of gitlab_project_members like the new gitlab_group_members

* added changelog

* linter: removed trainling whitespaces

* Update plugins/modules/source_control/gitlab/gitlab_project_members.py

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

* Update plugins/modules/source_control/gitlab/gitlab_project_members.py

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

* Update plugins/modules/source_control/gitlab/gitlab_project_members.py

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

* Update plugins/modules/source_control/gitlab/gitlab_project_members.py

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

* Update plugins/modules/source_control/gitlab/gitlab_project_members.py

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

* requested changes

* linter fixes

* undoing formatting changes to existing code

Co-authored-by: Max-Florian Bidlingmaier <Max.Bidlingmaier@konsolan.de>
Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Max Bidlingmaier <Max-Florian.Bidlingmaier@sap.com>
2021-09-16 22:26:31 +02:00
Patrick Pfurtscheller
331f5bdf24 redfish_utils: adding "Id" to the add user function (#3343)
* Adding "Id" to the add user function

Some implementations of Redfish (e.g. the one in Cisco's CIMC) seem to require the id of the new user for account creation.
I'm not that firm with Python but lines 982 and 983 should fix it.

* changed indention

* created changelog fragment

* Update changelogs/fragments/3343-redfish_utils-addUser-userId.yml

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

* Update change type

* supplemented the description of the ID parameter

* Update plugins/modules/remote_management/redfish/redfish_command.py

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-09-16 22:20:49 +02:00
Victor Martinez
06345839c6 opentelemetry callback: context propagation and error exception (#3378)
* opentelemetry callback: context propagation and error exception

* Apply suggestions from code review

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-09-16 20:22:44 +02:00
Felix Fontein
b20fc7a7c3 Install nios test requirements. (#3375) 2021-09-15 07:21:15 +02:00
Victor Martinez
517570a64f Add opentelemetry callback plugin (#3091)
* Add opentelemetry callback plugin

* Apply suggestions from code review

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

* Formatting (text), booleans and renamed env variables

* This should be done in a future release

* Remove insecure in favour of the OTEL env variable. Add descriptions

* Use OpenTelemetrySource

* Move generate_distributed_traces

* Move update_span_data and set_span_attribute

* Move finish_task

* Move start_task

* Refactor to support UTs

* Add first UT

* Fix codestyle

* opentelemetry callback entry in the botmeta

* Fix linting

* Fix signature

* Mock methods

* Use MagicMock

* Mock the methods

* UT for transform_to_boolean_or_default

* Fix linting

* Set test data

* Mock _time_ns

* Exclude tests for python <= 3.6

* Remove obsoleted setup task type configuration

* Remove unused docs

* Apply suggestions from code review

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

* Fix docs

* unrequired logic that was originally took from https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/callback/junit.py\#L226

* Use raise_from for the required dependencies

* Fix linting

* Add requirements for the UTs

* add missing dependency for the opentelemetry plugin in the UTs

* Add ANSIBLE_ prefix for the ansible specific options

* Add more context in the docs and remove duplicated docs

* As suggested in the code review

* Verify if the OTEL env variables for the endpoint were set

* Fix docs typo

* Fix linting

* Revert "Fix linting"

This reverts commit 3a54c827c5472553a6baf5598bc76a0f63f020c1.

* Revert "Verify if the OTEL env variables for the endpoint were set"

This reverts commit cab9d8648899c28c0345745690c4ec7a41f7e680.

* Remove console_output as suggested

* Apply suggestions from code review

Co-authored-by: flowerysong <junk+github@flowerysong.com>

* Delegate the definition of OTEL_EXPORTER_OTLP_INSECURE to the user

* Move definitions above, close to the class that uses them

Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: flowerysong <junk+github@flowerysong.com>
2021-09-14 21:05:02 +02:00
Martin Vician
dc8d076a25 tss: add option for token authorization (#3327)
* Added token parameter for AccessTokenAuthorizer

Parameters username and password are not required anymore because of
this.

* Added changelog fragments

* Apply suggestions from code review

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* token authorizer is prioritized

token authorizer is prioritized when token parameter is set

* Apply suggestions from code review

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

* domain optional if token not provided

* Updated examples

- `base_url` is required everywhere
- examples for user, name + domain authorization included
- token authorization included

* Update 3327-tss-token-authorization.yml

* Apply suggestions from code review

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

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-09-14 13:34:59 +02:00
John Losito
bd63da680d Allow dependabot to check github actions (#1604) 2021-09-13 21:52:30 +02:00
Ricky White
4e39a4b825 Added additional maintainer for the dsv and tss plugins (#3368) 2021-09-13 20:05:49 +02:00
Ajpantuso
118c040879 pids - refactor module to make version-based behavior consistent (#3315)
* Initial commit

* Adding changelog fragment

* Further refactoring

* Fixing bad copy/paste and adding task for psutil >= 5.7.0 install

* Inverting psutil installation order to reduce duplication

* Optimizing regex compilation
2021-09-13 07:16:49 +02:00
Raphaël Droz
0a5db85ad5 gitlab_runner: Support project-scoped runners registration (#2971)
* support project-scoped gitlab.com runners registration

* rename glproject variable to gitlab_project

* update version

* Update plugins/modules/source_control/gitlab/gitlab_runner.py

Co-authored-by: Raphaël Droz <raphael.droz+floss@gmail.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-09-13 07:16:06 +02:00
Ajpantuso
29e4066944 New filter plugin - unicode_normalization (#3359)
* Initial commit

* Adding maintainer in BOTMETA

* Adding changelog fragment

* Updating filter_guide

* Applying initial review suggestions
2021-09-12 13:46:53 +02:00
Roy Lenferink
612543919e Add ipaselinuxusermaporder option to the ipa_config module (#3178) 2021-09-12 13:46:17 +02:00
mkschuel
58d018ebbd Adds few more gitlab group options (#3248)
* Adds few more gitlab group options

* Update plugins/modules/source_control/gitlab/gitlab_group.py

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

* Removes default for new string options

* Removes default from argument_spec

* Adds changelog fragment

* Update plugins/modules/source_control/gitlab/gitlab_group.py

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

* Update plugins/modules/source_control/gitlab/gitlab_group.py

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

* Update plugins/modules/source_control/gitlab/gitlab_group.py

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

Co-authored-by: Maik Schueller <maik.schueller@sap.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-09-10 23:38:26 +02:00
Ajpantuso
05fe587a3e Adding new maintainer (#3349) 2021-09-09 07:58:21 -04:00
Felix Fontein
7c43cc3faa Improve CI (#3348)
* Remove superfluous test.

* Use remote_temp_dir instead of output_dir on remote.

* Read certificate from correct place.

* Adjust more places.

* Fix boolean.

* Improve cryptography setup.

* Fix java_keystore changes.

* Need to copy binary from remote.

* Use correct Python for serve script.

* Sleep before downloading.

* Use correct Python interpreter.

* Avoid failing shebang test.

* Fix permission error with macOS 11.1.

* Avoid shebang trouble.
2021-09-09 07:31:44 +02:00
Andreas Botzner
6b207bce4c Adds redis_data_info module (#3227)
* Added redis_data_info module

Added:
  - redis_data_info module and suggested 'exists' return flag.
  - module_utils for redis with a base class that handles database connections.
  - inhereited unit tests and added some new ones for the exit flag

* Docfix and sanity

* typo

* Suggested doc changes and ssl option

* TLS and validate_certs fix

* Set support_check_mode for info plugin

* Docfix and import errors

* Redis versioning Fix

* version bump and append fixes
2021-09-08 07:14:37 +02:00
Alexei Znamensky
dd25c0d3bf django_manage - split params (#3334)
* django_manage - fix fixures

* docs formatting adjustments

* param apps also in need of splitting

* oops, the splitted version was not being properly added to the command args

* added changelog fragment

* check for None

* moving to shlex.split()

* Update changelogs/fragments/3334-django_manage-split-params.yaml

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-09-07 06:22:46 +02:00
Felix Fontein
a20862797e Fix default value of new option. (#3338) 2021-09-07 08:37:10 +12:00
Alexei Znamensky
0f9311c3d9 zpool_facts - pythonification (#3332)
* pythonification

* added changelog fragment

* adjustment per PR
2021-09-06 19:23:33 +02:00
Manuel Gayer
76317d1f64 nmcli: Support GSM connections (#3313)
* nmcli: Support GSM connections

* Add GSM support
* Add GSM unit test

* nmcli: Add changelog fragment

* nmcli: Fix GSM unit test

* Fix copy-paste error in test_gsm_mod

* nmcli: Fix yaml formatting

* nmcli: Fix yaml formatting

* nmcli: Fix typeerror

* type must be str not string

* nmcli: Fix gsm_show_output

* gsm.username did not match input

* nmcli: Fix gsm_show_output

* doublechecked generated output with test-client

* nmcli: GSM fix unit test

* Removed `mocked_gsm_connection_unchanged`

* Revert "nmcli: GSM fix unit test"

This reverts commit 2d112b779a.

* nmcli: gsm fix unit test

* Add needed output to `TESTCASE_GSM_SHOW_OUTPUT`
* Move `mocked_gsm_connection_unchanged`to sort correctly

* nmcli: gsm fix _compare_conn_params

* Strip double-qoutes of gsm.apn if exist

* nmcli: GSM apply suggestions from code review

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* nmcli: GSM: Fix documentation

* Shorten too long lines

* nmcli: GSM apply suggestions from code review

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* nmcli: GSM add version

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

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-09-05 18:28:04 +02:00
Kyle Williams
3502f3b486 redfish: clean etag of quotes before patch (#3296)
* Some vendors surround header etag with quotes, which need to be cleaned before sending a patch

* Minor change fragment

* Add etag strip quote option

* Rebase

* Cleanup fragment

* Apply suggestions from code review

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

* Update plugins/modules/remote_management/redfish/redfish_command.py

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

* Description update

* Update plugins/modules/remote_management/redfish/redfish_config.py

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

Co-authored-by: Kyle Williams <kyle.williams@thetradedesk.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-09-01 22:59:27 +02:00
Silvie Chlupova
7c493eb4e5 Fix copr integration tests (#3237)
Fixes: #2084
2021-09-01 22:58:10 +02:00
Felix Fontein
c121e8685f Fix documentation bugs. (#3321) 2021-09-01 07:33:22 +02:00
Felix Fontein
bf8df21d27 Next expected release is 3.7.0. 2021-08-31 18:22:08 +02:00
Scott Anderson
135faf4421 django_manage: Remove scottanderson42 and tastychutney as maintainers. (#3314)
Note: tastychutney is another github account of mine that was also added as a maintainer.
2021-08-31 18:19:29 +02:00
Max Bidlingmaier
fce562ad6d Enhancement to gitlab_group_members to accept user lists as input (#3047)
* - fix to issue 3041
- add func to work with user lists
- add func to set members to the ones give

* Added version_added to new parameter

* fixed elements in definition of gitlab_users nad wrong import in gitlab_users

* linter issues fixed

* added list elelements to argument_spec

* More whitspeaces for the linter

* Update plugins/modules/source_control/gitlab/gitlab_group_members.py

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

* adapted changelog

* removed bugfix (other PR), changes due to review

* changed input handling according to review

* Fixed test findings

* Added list of dict to allow for specifying user/access_level tuples

* corrected doc section

* fixed parameter definitions

* removed strange additional import

* Update changelogs/fragments/3041-gitlab_x_members_fix_and_enhancement.yml

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

* Update plugins/modules/source_control/gitlab/gitlab_group_members.py

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

* Update plugins/modules/source_control/gitlab/gitlab_project_members.py

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

* Update plugins/modules/source_control/gitlab/gitlab_group_members.py

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

* Update plugins/modules/source_control/gitlab/gitlab_group_members.py

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

* fixed required if

* Update plugins/modules/source_control/gitlab/gitlab_group_members.py

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

* Added suggestions from PR

* fixed identation problem

* Update plugins/modules/source_control/gitlab/gitlab_group_members.py

Co-authored-by: Zainab Alsaffar <za5775@rit.edu>

* Update plugins/modules/source_control/gitlab/gitlab_group_members.py

Co-authored-by: Zainab Alsaffar <za5775@rit.edu>

* Update plugins/modules/source_control/gitlab/gitlab_group_members.py

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

* Update plugins/modules/source_control/gitlab/gitlab_group_members.py

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

* Recommended changes from discussionst

* Fixed issues from automatic tests

* added missing metaclass due to test finding

* added integration tests

* Update plugins/modules/source_control/gitlab/gitlab_group_members.py

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

* Update plugins/modules/source_control/gitlab/gitlab_group_members.py

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

* Update plugins/modules/source_control/gitlab/gitlab_group_members.py

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

* Update plugins/modules/source_control/gitlab/gitlab_group_members.py

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

* Update plugins/modules/source_control/gitlab/gitlab_group_members.py

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

* Update plugins/modules/source_control/gitlab/gitlab_group_members.py

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

* Update plugins/modules/source_control/gitlab/gitlab_group_members.py

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

* fixed optimization for only one user

* Reverted gitlab_project_members to original version - changes will be done in a separate branch

* added examples for new functionality

* - fixed changelog after reverting gitlab_project_memebers
- fully reverted gitlab_project_members

* Fixed error handling: when single users are not updateable in bulk mode the exception should not stop the code flow but document the problem in the result.

* Better error handling

* on error give username, not gitlab numeric userid

* Fixed broken check_mode

* Update plugins/modules/source_control/gitlab/gitlab_group_members.py

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

* Change from review

Co-authored-by: Max Bidlingmaier <Max-Florian.Bidlingmaier@sap.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Zainab Alsaffar <za5775@rit.edu>
2021-08-31 15:07:52 +02:00
Alexei Znamensky
1f5345881d open_iscsi - minor refactoring (#3286)
* open_iscsi - minor refactoring

* added changelog fragment
2021-08-31 13:09:29 +02:00
Alexei Znamensky
edd7b84285 pamd - fixed issue+minor refactorings (#3285)
* pamd - fixed issue+minor refactorings

* added changelog fragment

* added unit test suggested in issue

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

* fixed per PR + additional adjustment

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-08-31 12:34:57 +02:00
Ajpantuso
2d6816e11e proxmox inventory plugin - Update examples documentation (#3299)
* Initial commit

* Update plugins/inventory/proxmox.py

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-08-31 10:21:53 +02:00
Alexei Znamensky
b2bb7e3f9c django_manage - added splitting the command parameter for running (#3283)
* added splitting the command parameter for running

* added changelog fragment

* refactored variable names for improved readability
2021-08-31 07:14:08 +02:00
froebela
baa721ac22 zfs.py: treated received properties as local and added diff mode support (#502)
* zfs.py: treated received properties as local and added diff mode support

If you use "zfs set" to explicitly set ZFS properties, they are marked as from source "local". If ZFS properties are implicitly set by using "zfs send" and "zfs receive", for example as part of a template based installation, they are marked as from source "received". But as there is no technical difference between both types of them, the “received” ZFS properties should also be considered “local”. Otherwise Ansible would detect changes, which aren’t actual changes. Therefore I changed line 202/207 to reflect this.

For us it’s quite important, that Ansible modules support the diff mode in order to qualify changes. Therefore I added some code lines to address this.

* added changelog fragment for PR #502

* fixed typos in changelog fragment for PR #502

* minor changes in changelog fragment for PR #502

* added link to pull request in changelog fragment for PR #502

* extended the diff data structure to always include the name of the zfs filesystem

* added code to also maintain the diff data structure after a change

* reverted back some code lines for better code readability

* added an extra dict in the diff data structure to hold the zfs properties
2021-08-31 07:11:58 +02:00
Ajpantuso
58c6f6c95a Initial commit (#3300) 2021-08-31 07:10:10 +02:00
Laurent Paumier
97e2c3dec9 Keycloak: add identity providers management (#3210)
* init new module

* update

* add mappers

* improve mappers

* tests

* fix tests

* fix tests

* Update plugins/modules/identity/keycloak/keycloak_identity_provider.py

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

* Update plugins/modules/identity/keycloak/keycloak_identity_provider.py

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

* Update plugins/modules/identity/keycloak/keycloak_identity_provider.py

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

* Update plugins/modules/identity/keycloak/keycloak_identity_provider.py

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

* Update plugins/modules/identity/keycloak/keycloak_identity_provider.py

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

* Update plugins/modules/identity/keycloak/keycloak_identity_provider.py

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

* fix typos

* update botmeta

* improve change detection

* fix tests

* add integration tests

* remove updateProfileFirstLoginMode parameter

Co-authored-by: Laurent PAUMIER <laurent.paumier@externe.maif.fr>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-08-31 07:07:53 +02:00
Sebastian Damm
d9dcdcbbe4 udm_dns_record: Fix handling of PTR records (#3244) (#3256)
* udm_dns_record: Fix handling of PTR records (#3244)

Before, it was not possible to manage PTR records in Univention DNS,
due to broken zone lookups and improper used parameters of the object.
This patch fixes the PTR handling, allowing both v4 and v6 entries.

* udm_dns_record: [doc] add changelog fragment

* udm_dns_record: [fix] validation errors

* udm_dns_record: import ipaddress module conditionally (#3244)

* udm_dns_record: fix sanity check error, improve doc (#3244)

* udm_dns_record: Improve changes to meet community standards (#3244)
2021-08-30 06:53:30 +02:00
Reto Kupferschmid
1ce79db763 add deprecation warning for python-dnsimple 1 (#3267)
* add deprecation warning for python-dnsimple 1

* add changelog fragment

* Update changelogs/fragments/3267-dnsimple1-deprecation.yml

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

* Update plugins/modules/net_tools/dnsimple.py

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

* fix typo

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

* Update plugins/modules/net_tools/dnsimple.py

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

* Update changelogs/fragments/3267-dnsimple1-deprecation.yml

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-08-29 13:20:46 +02:00
Alexei Znamensky
df8fdcda79 mh CmdMixin - added ArgFormat.BOOLEAN_NOT and logic (#3290)
* mh CmdMixin - added ArgFormat.BOOLEAN_NOT and logic

* added changelog fragment
2021-08-29 13:03:15 +02:00
Felix Fontein
cf43356753 Fix unit tests (#3289)
* Force new enough requests version.

* Revert "Force new enough requests version."

This reverts commit 339d40bef7.

* Make sure we don't install a too new python-gitlab for Ansible 2.10.

* Change requirement instead of appending new one.

* Fix quoting.

* Try to skip if import fails.

* Revert "Try to skip if import fails."

This reverts commit 254bbd8548.

* Make other Python versions happy...

* Update tests/utils/shippable/units.sh

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

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-08-29 10:15:34 +02:00
Alexei Znamensky
a91eb6ae4f snap - improved error handling (#3211)
* snap - improved error handling

* added changelog fragment

* removed experiments left overs

* rolled back the smaller list of params for commands other than install
2021-08-28 21:54:39 +02:00
Alexei Znamensky
69641d36e1 openwrt_init - improvements (#3284)
* improvements on openwrt_init

* added changelog fragment
2021-08-28 21:50:09 +02:00
Atlas974
4e2d4e3c68 Fixed incorrect VMID: cloning to an existing VM (#3266)
* Fixed incorrect VMID: cloning to an existing VM

During a cloning operation, if the destination VM already exists the VMID returned is not correct.
The VMID returned should be that of the destination VM and not that of the source VM (consistent with line 1230).
A playbook that relies on the returned VMID, for example, to perform other operations on the destination VM, will not work properly if it is unexpectedly interrupted.

* Add files via upload

* moved 3266-vmid-existing-target-clone.yml to changelogs/fragments/
replaced line separator CRLF -> LF

* storing vmid list in variable to avoid multiple API calls
2021-08-27 18:48:32 +02:00
Kellin
e77adff0b7 Linode Inventory can use full IP data from APIv4 (#3203)
* Linode Inventory can use full IP data from APIv4

- The Linode dynamic inventory module does not currently distinguish
  between private and public IP addresses even though the Linode APIv4
  contains this information. This change keeps the current behavior as
  the default and adds an option to set `ip_style: api`. When set, this
  option allows administrators to differentiate between private, public,
  slaac, local_link, and pool network addresses providing a more nuanced
  and granular view of the remote host's network information.

Signed-off-by: Kellin <kellin@retromud.org>

* Review - amend changelog details

- Adds a link back to this pull request
- Uses markdown styles for easier to read publishing in the changelogs
- Amends the wording style to match the existing changelog styles

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

* Add scope to example invocation

- Adds the `community.general` scope to invocation example

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

* Convert lamda to list comprehension

- Change the ip type filter from a lambda to a list comprehension

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

* Add punctuation to description sentence

- Adds a period to the end of the description sentence

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-08-27 06:20:04 +02:00
Laurent Paumier
825e17c1cf Fix keycloak_realm module (#3231)
* fix events_listeners element type
add events_enabled parameter

* Update plugins/modules/identity/keycloak/keycloak_realm.py

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

* add changelog

* Update changelogs/fragments/3231-fix-keycloak-realm-events.yml

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

* Update changelogs/fragments/3231-fix-keycloak-realm-events.yml

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

* Update plugins/modules/identity/keycloak/keycloak_realm.py

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-08-27 06:17:04 +02:00
Nicolas Karolak
cc458f7c37 parse scw-cli config file for oauth_token (#3250)
If `api_token` is not set and config file exists, it will try to fetch
the value from the activated profile and fallback on default.

This should not break existing workflows.
2021-08-27 06:08:54 +02:00
zerotens
b8a081b9b2 nmcli: Support gre tunnels (#3262)
* Add gre tunnel support

* Add gre tunnel support

* Fix Blank Lines

* Fix unit test
Add changelog fragment

* Update plugins/modules/net_tools/nmcli.py

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

* Update Docs

* Update plugins/modules/net_tools/nmcli.py

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Update Docs

Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
2021-08-26 08:16:36 +02:00
Robin Roth
e40aa69e77 Stop notifications for apache2_module for me (#3261) 2021-08-26 08:09:26 +02:00
Ajpantuso
cbcb942b0e tss_lookup_plugin - Refactor and decoupling (#3252)
* Initial commit

* Adding changelog fragment

* Applying initial review suggestions

* Increasing unit coverage

* Removed unneccessary constant

* Improving test readability

* Cleanup constants
2021-08-25 06:41:05 +02:00
Felix Fontein
f2fa56b485 Fix apache2_module a2enmod/a2dismod detection and error message if not found. (#3258) 2021-08-25 06:36:19 +02:00
zerotens
1ca9c35010 nmcli: allow IPv4/IPv6 configuration on ipip and sit devices (#3239)
* Allow IPv4/IPv6 configuration on mode "sit" tunnel devices

* Update Unit Test for Allow IPv4/IPv6 configuration on mode "sit" tunnel devices

* Add changelog for Allow IPv4/IPv6 configuration on mode "sit" tunnel devices

* Update changelogs/fragments/3239-nmcli-sit-ip-config-bugfix.yaml

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Added ip4/ip6 configuration arguments for ipip tunnels

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
2021-08-23 06:24:05 +02:00
Matt 'Archer' Vaughn
23e7ef0255 Add option for retry_servfail (#3247)
* Add option for retry_servfail

cf. https://dnspython.readthedocs.io/en/latest/resolver-class.html#dns.resolver.Resolver.retry_servfail

Setting this option to `True` allows for the possibility of the lookup plugin to retry and thereby recover from potentially transient lookup failures, which would otherwise cause the task or play to bail with an unrecoverable exception.

* Create 3247-retry_servfail-for-dig

* documentation for `retry_servfail` option

* Rename 3247-retry_servfail-for-dig to 3247-retry_servfail-for-dig.yaml

* fix whitespace

* Update plugins/lookup/dig.py

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Update plugins/lookup/dig.py

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* rm try/except block

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
2021-08-21 21:57:28 +02:00
David Hummel
8a62b79ef2 nmcli: Disallow Wi-Fi options not supported by nmcli (#3141)
* nmcli: Disallow Wi-Fi options not supported by nmcli

By querying nmcli directly

* Added changelog fragment

* Added tests

* Simplify `get_available_options()`

* Update changelogs/fragments/3141-disallow-options-unsupported-by-nmcli.yml

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

* Remove redundant `802-11-wireless` settings from test show outputs

* Update `mocked_wireless_create(mocker)`

* Update plugins/modules/net_tools/nmcli.py

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Address comment re. creating function & use nmcli naming conventions

I.E. `setting`.`property` = `value`

```
nmcli> help set
set [<setting>.<prop> <value>]  :: set property value

This command sets property value.

Example: nmcli> set con.id My connection
```

* Added `ignore_unsupported_suboptions` option & improved `wifi(_sec)` doc

* Corrected pep8 issues

```
ERROR: Found 2 pep8 issue(s) which need to be resolved:
ERROR: plugins/modules/net_tools/nmcli.py:342:161: E501: line too long 
(236 > 160 characters)
ERROR: plugins/modules/net_tools/nmcli.py:359:161: E501: line too long 
(237 > 160 characters)
```

* Fixed remaining sanity check issues and added even more docs

* No need to split Note

* Update plugins/modules/net_tools/nmcli.py

3.5.0 has already been released.

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

* Followed uniformity guideline for format macros from Ansible's dev guide

* Addressed comment

https://github.com/ansible-collections/community.general/pull/3141#discussion_r689098383

* Documentation cleanup continuation

* Replace `NM_SETTING_*`s having a description with their numeric value

* Splitting up long paragraphs.

Also removed `wifi`.`seen-bssids` as it "`is only meant for reading`"

* Addressed remaining comments and clarified `wake-on-lan` note

* Update plugins/modules/net_tools/nmcli.py

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

* Update plugins/modules/net_tools/nmcli.py

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

* Update plugins/modules/net_tools/nmcli.py

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

* Update plugins/modules/net_tools/nmcli.py

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

* Finishing addressing documentation comments.

* Update plugins/modules/net_tools/nmcli.py

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Update plugins/modules/net_tools/nmcli.py

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Update nmcli.py

* Added wifi-related `list` type options to `settings_type` method

* Moved `edit_commands` `execution` logic into its own method

* Move `unsupported_property` deletion into `main` function

* Missing `.items()`

* Resolved missing proper `nmcli conn edit` arguments

* Resolve pylint issue `dangerous-default-value`

Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
Co-authored-by: David Hummel <dhummel@Fingerling>
2021-08-20 21:45:30 +02:00
Martin Vician
bcccf4e388 Add option for domain authorization (#3228)
Use DomainPasswordGrantAuthorizer if parameter `domain` is used.
2021-08-20 13:54:29 +02:00
Jacob
c7fccb2c01 redfish_info: Include Status property for GetChassisThermals (#3233)
* redfish_info: Include Status property for GetChassisThermals

Include Status property for Thermal objects when querying Thermal properties
via GetChassisThermals command.

FIXES #3232

* fixup for rename of fragments file

* Update changelogs/fragments/3233-include-thermal-sensor-status-via-redfish_info.yaml

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
2021-08-19 21:13:10 +02:00
Ricky White
6ac410b3f6 tss: added fix for bug report in issue #3192 (#3199)
* Added fix for bug report in issue #3192

* Added changelog fragment

* Typo fix

* Added Importerror to exception - as req by linters

* Moved the conditional import statement to try/except block
2021-08-18 09:26:44 +02:00
Alexei Znamensky
41101e55a0 module_helper - implemented classmethod to start the module (#3206)
* module_helper - implemented classmethod to start the module plus minor change

* rolled back the __changed__() method

* added changelog fragment

* Update plugins/module_utils/mh/base.py

Co-authored-by: Sviatoslav Sydorenko <wk.cvs.github@sydorenko.org.ua>

* no capt Piccards allowed in the base class

* removed extra piccards

Co-authored-by: Sviatoslav Sydorenko <wk.cvs.github@sydorenko.org.ua>
2021-08-17 10:43:18 +02:00
Felix Fontein
f19e191467 Temporarily disable datadog_downtime unit tests. (#3222) 2021-08-17 07:32:02 +02:00
Kellin
fccae19177 Linode inventory plugin typo fixes (#3218)
- Fix a typo in the Linode inventory plugin unit tests
- Fix some style issues in descriptions where punctuation was missing

Signed-off-by: Kellin <kellin@retromud.org>
2021-08-17 07:05:02 +02:00
Alexei Znamensky
8a4cdd2b8a slack - minor refactoring and pythonifying (#3205)
* slack - minor refactoring and pythonifying

* added changelog fragment

* Update changelogs/fragments/3205-slack-minor-refactor.yaml

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-08-16 12:24:15 +02:00
Alexei Znamensky
16945d3847 vdo - refactor (#3191)
* refactor to vdo

* adjusted if condition

* added changelog fragment

* Update plugins/modules/system/vdo.py

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

* adjustements per the PR

* more occurrences of bool compared with yes or no

* Update changelogs/fragments/3191-vdo-refactor.yml

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-08-16 12:23:06 +02:00
Paul Hauner
432c891487 Add ipv4 example to linode inventory docs (#3200)
* Add ipv4 example to linode inventory

* Update plugins/inventory/linode.py

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-08-15 13:11:16 +02:00
Daniel Ziegenberg
25267b8094 ini_file: add multiple options with same name to ini file (#3033)
* ini_file - prepare for fixing #273
 - restructure tests
 - fix error message call: fail_json() takes 1 positional argument but 2 were given

* ini_file - multiple values for one option (#273)
  - add module option 'exclusive' (boolean) for the abbility to add
    single option=value entries without overwriting existing options
    with the same name but different values
  - add abbility to define multiple options with the same name but
    different values

* ini_file - add more tests for ini_file

* ini_file - fix sanity tests

* apply suggested changes:

- rename 03-regressions.yml to 03-encoding.yml
- fix typos
- fix documentation

* apply suggested changes:

- test errors also for result is failed

* apply suggested changes:

- make state=absent also work with module option exclusive
- add more tests for state=absent and module option exclusive

* fix sanity test:

- 02-values.yml:251:9: hyphens: too many spaces after hyphen

* apply proposed changes

* apply proposed changes from review
- adjust version_added to 3.6.0
- small syntax change in changelog fragment
2021-08-15 12:59:50 +02:00
Felix Fontein
f7dba23e50 Remove deprecated netapp leftovers. (#3197) 2021-08-12 22:14:34 +02:00
Felix Fontein
e123623f5c Fix PR #. 2021-08-12 13:11:02 +02:00
Felix Fontein
1fec1d0c81 Fix new devel sanity errors. (#3194) 2021-08-12 12:07:50 +02:00
Felix Fontein
5855ef558a Next planned release is 3.6.0. 2021-08-12 08:35:33 +02:00
Ajpantuso
1e466df863 archive - idempotency enhancement for 4.0.0 (#3075)
* Initial Commit

* Comparing with tar file checksums rather than tar header checksums

* Added changelog fragment

* Revert "Comparing with tar file checksums rather than tar header checksums"

This reverts commit bed4b17107.

* Restricting idempotency tests by format

* Applying review suggestions
2021-08-12 08:18:38 +02:00
Sebastian
6033ce695b zypper: support transactional-updates (#3164)
* zypper: support transactional-updates

- Check if transactional updates are in use by checking for the
  existence of /var/lib/misc/transactional-update.state
- Prefix zypper-commands with /sbin/transactional-update --continue --drop-if-no-change --quiet run
  if this is the case

fixes ansible-collections/community.general#3159

* re-add get_bin_path for executables

* fix typo
2021-08-12 08:17:03 +02:00
Dag Wieers
b5d6457611 Support older version of psutil (RHEL7 and RHEL6) (#2808)
* Support older version of psutil (RHEL7 and RHEL6)

The psutil python module is a true mess, they changed the API twice. The function arguments, as well as the objects that are returned.
The documentation does not make it clear which version supports what so the safest implementation is this waterfall approach.

A better approach would be to inspect the returned information, rather than trust a version, but that would not be any more efficient.
In the end it is better to have something that at least works out-of-the-box on all platforms than something that requires custom updates to system packages before it works as expected. Especially for something as basic as `pids`.

* A little bit more concise

* Apply suggestions from code review

* Add changelog fragment.

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-08-10 07:49:18 +02:00
rainerleber
1705335ba7 SAP task list execution (#3169)
* add sap task list execute

* Apply suggestions from code review

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

* remove json out

* Apply suggestions from code review

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

* change logic

Co-authored-by: Rainer Leber <rainer.leber@sva.de>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-08-09 22:52:44 +02:00
zorun
56b5be0630 openbsd_pkg: Fix regexp matching crash (#3161)
When a package name contains special characters (e.g. "g++"), they are
interpreted as part of the regexp.

This can lead to a crash with an error in the python re module, for
instance with "g++":

    sre_constants.error: multiple repeat

Fix this by escaping the package name.

Co-authored-by: Baptiste Jonglez <git@bitsofnetworks.org>
2021-08-09 22:44:36 +02:00
Roy Lenferink
429359e977 Update the .gitignore with the latest version (#3177)
This because it contains new changes, e.g. ignore development
environments for Python projects.
2021-08-09 16:32:57 +02:00
David Hummel
7f96b7df60 nmcli: writing secrets to command line is a security hole (#3160)
* nmcli: use `stdin` for setting private `wifi_sec` options

I.E.:
* `802-11-wireless-security.leap-password`
* `802-11-wireless-security.psk`
* `802-11-wireless-security.wep-key0`
* `802-11-wireless-security.wep-key1`
* `802-11-wireless-security.wep-key2`
* `802-11-wireless-security.wep-key3`

* Changelog fragement formatting.

* Update changelogs/fragments/3160-pass-wifi-secrets-via-stdin-to-nmcli-module.yml

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

* Make `wifi_sec_secret_options()` into a constant

* Minor cleanup

`'set ' + key + ' ' + value`
=>
`'set %s %s' % (key, value)`

* Change `casing`

* Change `WIFI_SEC_SECRET_OPTIONS` from `list` to `tuple`

* Update `edit_connection()` to not reset `edit_commands`

It will just re`set` them if `edit_connection()` is called more than 
once.

* Do not call `edit_connection()` if `connection_update(*)` fails

* Fixed `pep8` issue `E713` in tests

`test for membership should be 'not in'`

* Simplify `create_connection()`/`modify_connection()` logic

* `WIFI_SEC_SECRET_OPTIONS`=>`SECRET_OPTIONS`, options are prefixed

* Moved `if key in self.SECRET_OPTIONS` into `if value is not None` check

We don't need to do anything is the value is None

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-08-08 18:35:52 +02:00
quidame
2831bc45f5 ini_file: fix empty-value vs. no-value inconsistency (#3074)
* fix empty-value vs. no-value inconsistency

* rename changelog fragment

* tests: omit value where there should be no value

* add integration tests
2021-08-08 18:34:34 +02:00
Sebastian
85bcef3f5a contributing: make expected behavior clearer (#3168)
* contributing: make expected behavior clearer

reformulate the preference of not having squashed commits clearer,
shorter and more precise.

https://github.com/ansible-collections/community.general/pull/3164#discussion_r684644504

* Update CONTRIBUTING.md

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-08-08 10:50:09 +02:00
Felix Fontein
87ba15fa45 Inform contributors on changelog fragments in CONTRIBUTING.md (#3167)
* Inform contributors on changelog fragments.

* Mention docs-only PRs as well.
2021-08-08 10:49:08 +02:00
Alexei Znamensky
771e9de010 mass-added the utf-8 marker (#3163)
* added the utf-8 marker

* fixed the utf-8 marker where it was missde before
2021-08-08 10:40:22 +02:00
David Hummel
6bfa6e40f4 nmcli: Fix change detection for Wi-Fi security options (#3136)
* Fixed `wifi_sec` option changes are not detected

Also updated `docs` URL and formatting to match that of the `wifi`
option

* Removed extraneous `appends` to `cmd` in `connection_update`

These really should have only been added to `connection_options` whose 
return values get `extended` onto `cmd`
2021-08-07 15:20:44 +02:00
Alexei Znamensky
da11a98cb7 fixed the utf-8 marker (#3162) 2021-08-07 15:02:21 +02:00
Bartosz
ff586f1105 pkgin: display stdout and stderr in case the error occurs (#3148)
* pkgin: display stdout and stderr in case the error occurs

* Update changelogs/fragments/pkgin-output-after-error.yml

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-08-06 10:01:05 +02:00
Felix Fontein
16476f5cb9 Update AZP config (#3111)
* Update AZP config.

* Skip 8.4 as well for django_manage (next to 8.3 and 8.2).

* Temporarily skip 8.4 for yum_versionlock.
2021-08-05 23:46:39 +02:00
rainerleber
e9494c12f2 Hana query userstore (#3125)
* add hdbuserstore ability

* add description

* fix

* add default

* add description

* add sample

* Apply suggestions from code review

Co-authored-by: quidame <quidame@poivron.org>

* add fragment, fix required if

* remove whitespace

* add coding fragment

* Apply suggestions from code review

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

* added test for userstore

* Update plugins/modules/database/saphana/hana_query.py

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

Co-authored-by: Rainer Leber <rainer.leber@sva.de>
Co-authored-by: quidame <quidame@poivron.org>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-08-05 22:42:43 +02:00
Ricky White
a73720c103 Updated the tss lookup plugin to reflect breaking changes introduced in the underpinning SDK (#3139)
* Updated the plugin to reflect breaking changes introduced in the underlying SDK v1.0.0 update.

* Added Changelog fragment

* Updates based on feedback/review

* Added newline to pass CI

* Added whitepace for linter

* Update changelogs/fragments/3139-tss-lookup-plugin-update-to-make-compatible-with-sdk-v1.yml

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
2021-08-05 19:28:32 +02:00
Reto Kupferschmid
3dba697e33 nmcli: manage dummy connections (#3132)
* manage dummy connections

* add issue reference in changelog fragment

* Update changelogs/fragments/3132-nmcli-dummy.yaml

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* resolve test conflicts

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
2021-08-05 14:25:42 +02:00
Scott Seekamp
75688cb632 redfish_command: allow setting the BootSourceOverrideMode property (#3135)
* For #3134

Expose BootOverrideMode parameter to redfish_command to allow setting by user during run.

* Fix trailing whitespace

* Add changelog fragment to contribution.

* Update changelogs/fragments/3135-add-redfish_command-bootoverridemode.yaml

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

* Update plugins/modules/remote_management/redfish/redfish_command.py

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

* Update plugins/modules/remote_management/redfish/redfish_command.py

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

* Update plugins/modules/remote_management/redfish/redfish_command.py

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

* Update plugins/modules/remote_management/redfish/redfish_command.py

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

* Update changelogs/fragments/3135-add-redfish_command-bootoverridemode.yaml

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-08-04 19:53:43 +02:00
Reto Kupferschmid
f2df1a7581 dnsimple update for python-dnsimple >=2.0.0 (#2946)
* update dnsimple module

* dnsimple: fixes for python-dnsimple >= 2.0.0

* Update plugins/modules/net_tools/dnsimple.py

Co-authored-by: Abhijeet Kasurde <akasurde@redhat.com>

* rewrite module to support dnsimple-python v1 and v2

* add changelog fragment

* fix sanity checks

* python 2 fixes

* fix dnsimple requirement

* add sandbox module parameter

* Update changelogs/fragments/2946-python-dnsimple-v2-rewrite.yml

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

* Update plugins/modules/net_tools/dnsimple.py

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

* return only the first traceback

* Update plugins/modules/net_tools/dnsimple.py

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

* Update plugins/modules/net_tools/dnsimple.py

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

* use separate classes for python-dnsimple 1 and 2

* add basic tests

* fix checks

* skip tests for unsupported python versions

* Update plugins/modules/net_tools/dnsimple.py

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

* fix conditions

Co-authored-by: Abhijeet Kasurde <akasurde@redhat.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-08-04 08:36:45 +02:00
David Hummel
857d2eee50 nmcli: Add support for additional Wi-Fi network options (#3081)
* nmcli: Add support for additional Wi-Fi network options

* Added `changelog fragment`

* Update changelogs/fragments/3081-add-wifi-option-to-nmcli-module.yml

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
2021-08-04 08:16:11 +02:00
quidame
afe2842b1b filesize: overwrite default unsafe_writes documentation (#3126)
* overwrite default `unsafe_writes` documentation

* Apply suggestions from code review

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-08-02 08:24:31 +02:00
Alexei Znamensky
047b7ada3c uf8 marker batch2 (#3128)
* added utf-8 markers to all .py files in plugins/filter

* added utf-8 markers to all .py files in plugins/inventory

* added utf-8 markers to all .py files in plugins/lookup
2021-08-01 12:36:53 +02:00
Alexei Znamensky
73c27d6a0e utf8 marker batch1 (#3127)
* added utf-8 markers to all .py files in plugins/{action,cache,callback}

* added utf-8 markers to all .py files in plugins/connection

* added utf-8 markers to all .py files in plugins/doc_fragments
2021-08-01 12:35:08 +02:00
Alexei Znamensky
789f06dffe removed extraneous dependency in integration test (#3119) 2021-07-31 09:10:54 +02:00
Alexei Znamensky
5f8d6a73d3 fixed RETURN doc (#3120) 2021-07-31 09:09:38 +02:00
Yvan Watchman
9ccce82113 Feature: implement hpilo_info system power info (#3079)
* report power state of host

* Modify sample information

* add changelog fragment

* apply feedback from github community

* apply feedback

Co-authored-by: Yvan E. Watchman <git@yvanwatchman.eu>
2021-07-31 17:43:45 +12:00
Gaetan2907
43fe26d83c Keycloak: add client_rolemapping management (#2941)
* Add Keycloak kc_client_rolemapping module

* Fix documentation

* Add unit tests for keycloak_client_rolemapping Keycloak module

* Update plugins/modules/identity/keycloak/keycloak_client_rolemapping.py

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

* Update plugins/modules/identity/keycloak/keycloak_client_rolemapping.py

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

* Update plugins/modules/identity/keycloak/keycloak_client_rolemapping.py

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

* Update plugins/modules/identity/keycloak/keycloak_client_rolemapping.py

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

* Update plugins/modules/identity/keycloak/keycloak_client_rolemapping.py

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

* Fix documentation

* Update plugins/modules/identity/keycloak/keycloak_client_rolemapping.py

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

* Minor fix

* Add check mode

* Refactoring: rename function from get_client_roles to get_client_roles_by_id

* BOTMETA.yml: keycloak_client_rolemapping - add myself as maintainer

* Update plugins/modules/identity/keycloak/keycloak_client_rolemapping.py

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

* Update plugins/modules/identity/keycloak/keycloak_client_rolemapping.py

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-07-30 20:03:57 +02:00
Alexei Znamensky
d9533c44aa apache2_module - multiple improvements (#3106)
* multiple improvements

* added changelog fragment

* comment and name in int test files

* added notes to the documentation

* removed the extraneous changelog frag

* Update plugins/modules/web_infrastructure/apache2_module.py

* adjusted doc text for sanity check

* Update plugins/modules/web_infrastructure/apache2_module.py

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

* removed extraneous dependency in integration test

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-07-30 18:07:38 +02:00
Alexei Znamensky
d974ca32ae removed extraneous dependency in integration test (#3114) 2021-07-30 18:00:14 +02:00
Alexei Znamensky
2935b011ed ansible_galaxy_install - new module (#2933)
* initial commit

* multiple changes:

- added a proper process_command_output()
- adjusted the output_params fields (and removed other *_params fields)

* added RETURN documentation, plus few adjustments

* fixed sanity tests

* updated BOTMETA.yml

* further adjustments

* integration tests - first commit

* removed unused files from integration test

* added role installation tests

* removed extraneous cmd line option

* added requirement-file installation tests

* adjusted documentation and output variable names

* fixed integration test

* Update plugins/modules/packaging/language/ansible_galaxy_install.py

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Update plugins/modules/packaging/language/ansible_galaxy_install.py

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Update plugins/modules/packaging/language/ansible_galaxy_install.py

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Update plugins/modules/packaging/language/ansible_galaxy_install.py

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Update plugins/modules/packaging/language/ansible_galaxy_install.py

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Update plugins/modules/packaging/language/ansible_galaxy_install.py

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Update plugins/modules/packaging/language/ansible_galaxy_install.py

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Update plugins/modules/packaging/language/ansible_galaxy_install.py

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

* Update tests/integration/targets/ansible_galaxy_install/aliases

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

* Per comments in the PR:

- fixed missing paths case
- fixed install parsing (regexp) for ansible-galaxy collection install in v2.10

* changed the collection installed in test to something unlikely to come embedded in Ansible itself

* fixed logic for Ansible 2.9

* kill trailing whitespace

* changed default language from C.UTF-8 to en_US.UTF-8

* updated c.g version

* skipping test in python 2.6, as ansible-galaxy no longer supports it in devel

* Multiple changes:

- improved docs on ansible 2.9 and python 2.6
- removed method __changed__() - unnecessary since tracking changes in the ansible29_change var
- renamed methods __run29__() and __run210plus__() to __setup29__() and __setup210plus__(), respectively
- ansible 2.9 warning for requirements_file only when type is "both"

* sanity fix

* further adjustments

* removed extraneous doc

* changed method to determine remote ansible version

* do not allow type=both in Ansible 2.9

* Update plugins/modules/packaging/language/ansible_galaxy_install.py

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

* Update plugins/modules/packaging/language/ansible_galaxy_install.py

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

* changed method names per PR

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-07-29 22:30:20 +02:00
Alexei Znamensky
cde9564163 deploy_helper - changed in-code condition to required_if (#3104)
* changed in-code condition to required_if

* added changelog fragment
2021-07-29 07:49:52 +02:00
Alexei Znamensky
549dfaae64 gunicorn - minor refactoring (#3092)
* minor refactoring in gunicorn module

* added changelog fragment

* reworked the gunicorn bin path part of the code, per PR

* Update changelogs/fragments/3092-gunicorn-refactor.yaml

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-07-28 08:43:09 +02:00
Alexei Znamensky
0b70b3baff django_manage - using list instead of string in run_command() (#3098)
* django_manage - using list instead of string in run_command()

* added changelog fragment
2021-07-28 08:22:18 +02:00
Alexei Znamensky
5be4adc434 ejabberd_user - refactoring and simplification (#3093)
* ejabberd_user - refactoring and simplification

* added changelog fragment

* Update changelogs/fragments/3093-ejabberd_user-refactor.yaml

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-07-28 07:49:37 +02:00
Felix Fontein
87baa5860a Actually enable BOTMETA sanity test to force new plugins/modules to have BOTMETA entry. (#3096) 2021-07-27 20:26:26 +02:00
Alexei Znamensky
7da2c16b4a added supports_check_mode=True to info/facts modules (#3084)
* added supports_check_mode=True to info/facts modules

* added changelog fragment

* rolled back vertica_info

* rolled back utm_proxy_*_info

* updated changelog fragment with latest adjustments

* Update changelogs/fragments/3084-info-checkmode.yaml

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

* added check mode to xenserver_facts + oneview_*_info

* added check mode to utm_proxy_*_info

* updated changelog

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-07-27 18:24:29 +02:00
Felix Fontein
024e7419da BOTMETA: enforce entries for new plugins/modules, add documentation for creating new plugins/modules (#3088)
* More BOTMETA improvements.

* Improve BOTMETA test, start reporting missing entries for new plugins/modules.

* Add instructions for creating new plugins and modules.
2021-07-26 16:54:00 +02:00
Felix Fontein
4982eaf935 Update BOTMETA, fix some plugin authors, improve BOTMETA extra sanity test (#3069)
* Update BOTMETA, fix some plugin authors, improve BOTMETA extra sanity test.

* Linting.
2021-07-26 11:44:41 +02:00
quidame
21d5668c97 java_cert: import certificate+key bundle from pkcs12 (#3080)
* import certificate+key bundle from pkcs12

* fix typo/syntax

* fix variable name

* fix passwords order and improve error handling

* add changelog fragment

* enter keystore pass only once if keystore already exists, and twice at creation

* nomalize tests

- Replace `command` tasks by dedicated (community.crypto) modules.
- Add spaces around jinja2 variable names.
- Call modules by their FQCNs.

* Add tests to check keystore has a private key

fix tests for RedHat/CentOS < 8 (run openssl command as an alternative to
`openssl_pkcs12` module)
2021-07-26 11:42:13 +02:00
Yvan Watchman
ac03881002 Succesful clone from proxmox_kvm should return new vm id, not id from cloned vm. (#3034)
* Clone sucess should return new vm id, not id from cloned vm.

* add changelog fragment

* Update changelogs/fragments/3034-promox-kvm-return-new-id.yaml

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

Co-authored-by: Yvan E. Watchman <git@yvanwatchman.eu>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-07-26 06:33:01 +02:00
Alexei Znamensky
c8b2d7c1e5 supervisorctl - bugfix + using ansible validation + pythonification (#3068)
* supervisorctl - bugfix + pythonification

* added changelog fragment

* rollback check on the binpath
2021-07-25 22:04:23 +02:00
Alexei Znamensky
95ceb53676 taiga_issue - bugfix + pythonification (#3067)
* taiga_issue - bugfix + pythonification

* added changelog fragment
2021-07-25 22:03:45 +02:00
Alexei Znamensky
20db4fc560 replace NBSP (non-blocking space) character with a regular SPACE char (#3071) 2021-07-25 13:53:38 +02:00
Alexei Znamensky
d54d2fa4a6 xfconf - deprecate get state in favour of the xfconf_info module (#3049)
* Deprecate get state in favour of the xfconf_info module

* added changelog fragment

* added comments in ignore files

* Update changelogs/fragments/3049-xfconf-deprecate-get.yaml

bummer, forgot that

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

* Update plugins/modules/system/xfconf.py

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

* Update plugins/modules/system/xfconf.py

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-07-25 11:14:30 +02:00
Felix Fontein
dc3e16113d Add BOTMETA extra sanity test (#3064)
* Add BOTMETA sanity test.

* Make compile with Python 2.6.
2021-07-25 10:00:10 +02:00
Alexei Znamensky
20f46f7669 xfconf_info - new module (#3045)
* xfconf_info initial commit

* Update plugins/modules/system/xfconf_info.py

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

* Update plugins/modules/system/xfconf_info.py

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

* Update plugins/modules/system/xfconf_info.py

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

* added register to all examples

* Update plugins/modules/system/xfconf_info.py

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-07-24 22:30:46 +02:00
Ajpantuso
31189e9645 archive - fixing determination of archive root when root is '/' (#3036)
* Initial commit

* Fixing units and path joins

* Ensuring paths are consistently ordered

* Adding changelog fragment

* Using os.path.join to ensure trailing slashes are present

* optimizing use of root in add_targets

* Applying initial review suggestions
2021-07-24 22:10:56 +02:00
Max Bidlingmaier
d057b2e3b2 gitlab_group_members/gitlab_project_members - fix pagination issue (#3054)
* Fix

* fixed linter stuff

* typo in section name of changlog fragment

Co-authored-by: Max Bidlingmaier <Max-Florian.Bidlingmaier@sap.com>
2021-07-24 21:13:09 +02:00
The Right Honourable Reverend
99c28313e4 proxmox inventory plugin: Easy fix (#3052)
* Don't know why this works but it does.

Plugin was crashing on this line on Python 3.9.2 deployed on qemu image with debian bullseye. It doesn't crash anymore.

* Create 3052_proxmox_inventory_plugin.yml

* Update changelogs/fragments/3052_proxmox_inventory_plugin.yml

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
2021-07-24 20:40:08 +02:00
Alexei Znamensky
9631de4939 fixed doc in xfconf (#3050) 2021-07-23 08:17:14 +02:00
Alexei Znamensky
35e0a61217 missed composer when created commments in ignore files (#3051) 2021-07-23 08:16:14 +02:00
Jeffrey van Pelt
32e9a0c250 Proxmox inventory: Added snapshots fact (#3044)
* Added snapshots fact

* Added changelog

* Made linter happy again

* Processed feedback

* Fix changelog type

* Punctuation ;-)

* Punctuation ;-), take 2
2021-07-22 22:55:07 +02:00
Max Bidlingmaier
38e70ae0e4 github_repo: support GitHub on premise installations (#3039)
* added possibility to manage on prem github

* added changelog

* fixed module tests

* Update changelogs/fragments/3038-enhance_github_repo_api_url.yml

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

* Update plugins/modules/source_control/github/github_repo.py

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

Co-authored-by: Max Bidlingmaier <Max-Florian.Bidlingmaier@sap.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-07-22 16:55:09 +02:00
Felix Fontein
11cdb1b661 Next expected release is 3.5.0. 2021-07-19 23:39:57 +02:00
Gaetan2907
4a392372a8 Keycloak: add clientscope management (#2905)
* Add new keycloak_clienscope module

* Add description and protocol parameter + Indentation Fix

* Add protocolMappers parameter

* Add documentation and Fix updatating of protocolMappers

* Update plugins/modules/identity/keycloak/keycloak_clientscope.py

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

* Update plugins/modules/identity/keycloak/keycloak_clientscope.py

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

* Update plugins/modules/identity/keycloak/keycloak_clientscope.py

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

* Update plugins/modules/identity/keycloak/keycloak_clientscope.py

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

* Update plugins/modules/identity/keycloak/keycloak_clientscope.py

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

* Update plugins/modules/identity/keycloak/keycloak_clientscope.py

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

* Add sanitize_cr(clientscoperep) function to sanitize the clientscope representation

* Add unit tests for clientscope Keycloak module

* Apply suggestions from code review

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-07-19 23:39:02 +02:00
Laurent Paumier
d7c6ba89f8 Add Keycloak roles module (#2930)
* implement simple realm and client role

* fix documentation

* code cleanup

* separate realm and client roles functions

* remove blank lines

* add tests

* fix linefeeds

* fix indentation

* fix error message

* fix documentation

* fix documentation

* keycloak_role integration tests

* keycloak_role integration tests

* remove extra blank line

* add version_added tag

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-07-19 23:17:39 +02:00
suukit
a3607a745e Feature/gitlab project configuration (#3002)
* added
-         only_allow_merge_if_all_discussions_are_resolved
- only_allow_merge_if_all_discussions_are_resolved
- only_allow_merge_if_pipeline_succeeds
- only_allow_merge_if_pipeline_succeeds
- packages_enabled
- remove_source_branch_after_merge
- squash_option

* minor fix

* added changelog

* Fixedlinter findings

* changed version_added to 3.4 -> check requires to do so

* Update changelogs/fragments/3001-enhance_gitlab_module.yml

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

* Update plugins/modules/source_control/gitlab/gitlab_project.py

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

* Update plugins/modules/source_control/gitlab/gitlab_project.py

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

* Update plugins/modules/source_control/gitlab/gitlab_project.py

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

* Update plugins/modules/source_control/gitlab/gitlab_project.py

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

* Update plugins/modules/source_control/gitlab/gitlab_project.py

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

* Update plugins/modules/source_control/gitlab/gitlab_project.py

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

* rework due to review of felixfontein:
- changed option description to full sentences
- change default behaviour of new properties

* Requested changes

Co-authored-by: Max Bidlingmaier <Max-Florian.Bidlingmaier@sap.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-07-19 11:52:32 +02:00
Ajpantuso
9fd2ba60df archive - staging idempotency fix (#2987)
* Initial Commit

* Fixing PY26 filter

* Adding changelog fragment

* Removing checksum related code

* Removing list comparisons due to Jinja errors

* Applying review suggestions

* Applying review suggestions - typos
2021-07-19 08:14:23 +02:00
Felix Fontein
7b9687f758 Fix snap's channel option. (#3028) 2021-07-19 13:36:59 +12:00
Werner Dijkerman
7734430f23 Added module for creating protected branches (#2781)
* Added module for creating protected branches

* Applied some changes due to comments and added a test that currently fails

* Changing no_access to nobody due to comment on PR

* Changing the description to clarify it a bit more

* Added working tests for module 'gitlab_protected_branch'

* Fixing lint issues

* Added doc that minimum of v2.3.0 is needed to work correctly

* Fixed the requirements notation

* Check the version of the module

* Hopefully fixed the tests by skipping it when lower version of 2.3.0 is installed

* Fix lint issues

* Applying changes due to comments in PR

* Remove commented code

* Removing the trailing dot ...

Co-authored-by: jenkins-x-bot <jenkins-x@googlegroups.com>
Co-authored-by: Werner Dijkerman <iam@werner-dijkerman.nl>
2021-07-17 08:49:09 +02:00
Felix Fontein
27ba98a68e Check targets (#3019)
* Add extra sanity test to check aliases files.

* Remove invalid target name.
2021-07-16 19:52:09 +02:00
Felix Fontein
9b1c6f0743 Enable tests (#3015)
* Enable tests.

* Fix error message check.

* Fix boolean tests.

* Adjust to Python version.
2021-07-16 19:29:00 +02:00
Scott Seekamp
ea822c7bdd Redfish Bootoverride Disable behaves incorrectly (#3006)
* https://github.com/ansible-collections/community.general/issues/3005

Bypass the boot device argument check when the command is: DisableBootOverride
as it isn't needed to perform this operation.

* Add changelog fragment
2021-07-16 19:02:34 +02:00
Alexei Znamensky
a3a40f6de3 pamd - fixed single line issue (#2989)
* fixed pamd single line issue

* added changelog fragment

* supported case for 0 lines, improved test
2021-07-14 13:04:35 +02:00
Andrew Klychkov
28193b699b Update README.md (#3003) 2021-07-14 08:26:12 +02:00
omula
9ffc1ef393 [nmcli] add runner and runner-hwaddr-policy for network teaming (#2901)
* [nmcli] add runner and runner-hwaddr-policy for network teaming

* [nmcli] delete extra space

* Update plugins/modules/net_tools/nmcli.py

* Update plugins/modules/net_tools/nmcli.py

* [nmcli] add changelog fragment

* Update plugins/modules/net_tools/nmcli.py

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

Co-authored-by: Oriol MULA VALLS <oriol.mula@lxp.lu>
Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
Co-authored-by: Amin Vakil <info@aminvakil.com>
2021-07-14 08:24:27 +02:00
Gaetan2907
3fc97bf80a Keycloak: Improve diff mode on keycloak_authentication module (#2963)
* Fix diff mode when updating authentication flow with keycloak_authentication module

* Add changelog fragment

* Fix unit test

* Update plugins/modules/identity/keycloak/keycloak_authentication.py

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Update changelogs/fragments/2963-improve-diff-mode-on-keycloak_authentication.yml

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Update documentation of create_or_update_executions function (return tuple instead of dict)

* Update plugins/modules/identity/keycloak/keycloak_authentication.py

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Update plugins/modules/identity/keycloak/keycloak_authentication.py

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
2021-07-13 06:57:16 +02:00
Mark Chappell
5079ef0e82 feature request template - replace ansible-core with community.general - looks like a C&P error (#2992) 2021-07-11 16:38:58 +02:00
Alexei Znamensky
d56d34bce6 added missing copyright notes to MH integration tests (#2990) 2021-07-11 16:34:59 +02:00
Alexei Znamensky
c5cbe2943b module_helper cmd - added feature flag to control whether CmdMixin adds rc, out and err t… (#2922)
* added feature flag to control whether CmdMixin adds rc, out and err to the result of the module

* added changelog fragment

* changed from a global flag to parameters in run_command

* updated changelog

* fixed brainless copy-paste of yours truly
2021-07-11 11:43:40 +12:00
Tyler Schwend
7a41833e59 feat: support datadog_monitor composite type (#2958)
* feat: support datadog_monitor composite type

* docs: note support for composite types

* lint

* lint: line lengths

* doc: changelog frag
2021-07-10 19:24:09 +02:00
Ajpantuso
111c5de550 proxmox inventory - fix parsing for offline nodes (#2967)
* Initial commit

* Adding changelog fragment

* Applying initial review suggestions
2021-07-10 16:39:51 +02:00
quidame
9023d4dba1 filesystem: extend support for FreeBSD (#2902)
* extend support for FreeBSD

* Check if FS exists with `fstyp` if `blkid` fails to find FS signature
  (fix a potential data loss)
* Add support for FreeBSD special devices (character devices).
* Add support for FreeBSD native fstype (UFS).
* Update DOCUMENTATION accordingly.

* add/update integration tests

* Add tests for `fstype=ufs` on FreeBSD.
* Run `remove_fs` tests (`state=absent`) on FreeBSD.
* Run `overwrite_another_fs` tests on FreeBSD.

* add a changelog fragment

* fix indentation

* restrict new tests to regular files

* fix typo

* fix searching of providersize (block count)

* add '-y' option to growfs command

* remove references to versions older than the collection itself

* bump version adding new feats to 3.4.0

* reformat *collection* and *version added* for better DOCUMENTATION parsing

* skip tests for FreeBSD < 12.2

* run tests for FreeBSD >= 12.2

* re-enable tests for FreeBSD < 12.2 and give it a try with group1

* util-linux not available on FreeBSD < 12.2
2021-07-10 16:37:31 +02:00
Felix Fontein
4ae392e5de Temporarily disable passwordstore lookup tests on macOS and OSX. (#2979) 2021-07-10 13:31:54 +02:00
Alexei Znamensky
0e90ff48b5 rax_mon_notification_plan - fixed validation check (#2955)
* fixed validation-modules for plugins/modules/cloud/rackspace/rax_mon_notification_plan.py

* fixed sanity check

* added changelog fragment
2021-07-10 13:05:20 +02:00
Alexei Znamensky
1990f79d8a launchd - fixed validation check (#2960)
* replaced use of expanduser() with value from HOME var

* fixed sanity check

* added changelog fragment
2021-07-10 13:03:41 +02:00
Alexei Znamensky
ad8c4e4de6 added comments to the ignore files (#2972) 2021-07-10 13:01:16 +02:00
Ajpantuso
288fe1cfc6 archive - adding dest_state return value and enhancing integration tests. (#2913)
* Initial commit

* Adding changelog fragment

* fixing changelog fragment

* Updating documentation

* Applying review suggestions
2021-07-10 12:58:30 +02:00
Gaetan2907
1b80a9c587 Add option to the keycloak_client module (#2949)
* Add authentication_flow_binding_overrides option to the keycloak_client module

* Add changelog fragment

* Update changelogs/fragments/2949-add_authentication-flow-binding_keycloak-client.yml

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

* Update plugins/modules/identity/keycloak/keycloak_client.py

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

* Update plugins/modules/identity/keycloak/keycloak_client.py

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

* Add unit test authentication_flow_binding_overrides feature on keycloak_client module

Co-authored-by: Amin Vakil <info@aminvakil.com>
2021-07-09 08:33:35 +02:00
Tong He
d97a9b5961 jenkins_job_info: Remove necessities of password or token. (#2948)
* Remove necessities on password or token.

* Upper case letter -> Lower case letter

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

* Documentation update.

* C -> I

Co-authored-by: Amin Vakil <info@aminvakil.com>
2021-07-09 08:32:46 +02:00
John R Barker
518ace2562 Update commit-rights.md
aminvakil is no longer involved with the Ansible Community due to United
States export controls and economic sanctions laws apply to U.S.
persons, entities, and controlled software and technology that is of
U.S. origin or that enters the U.S., including open source software.
2021-07-08 13:15:58 +01:00
Alexei Znamensky
56acd4356f MH - dicts and lists change-tracking is fixed (#2951)
* dicts and lists change-tracking is fixed

* added changelog fragment

* fixed sanity check
2021-07-08 07:20:01 +02:00
Amin Vakil
c0740ca398 pacman: fix changed status when ignorepkg has been defined (#2936)
* pacman: fix returned code when ignorepkg has been defined

* add changelog

* make ignored check preciser
2021-07-06 22:06:36 +02:00
Amin Vakil
b2b4877532 lvol: honor check_mode on thinpool (#2935)
* lvol: support check_mode on thinpool

* add changelog

* Add %s when needed

* correct changelog sentence

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-07-05 20:46:19 +02:00
Alexei Znamensky
9b02230477 snap - fixed param order (#2918)
* fixed param order

* added changelog fragment

* rebased and uncommented tests per PR

* added /snap link in RH

* typo in tests

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-07-03 16:31:30 +02:00
Shahar Mor
a0915036f9 npm - fix installing from package.json (#2924)
correctly handle cases where a dependency does not have a `version` property because it is either missing or invalid
2021-07-02 21:42:50 +02:00
Ajpantuso
ffe505a798 archive - fix removal failures for nested files with tar archives (#2923)
* Initial commit

* Adding changelog fragment
2021-07-02 21:30:40 +02:00
Amin Vakil
00aa1250ee Add integration test for classic snap (#2920)
* Add integration test for classic snap

* Add comments and check remove without classic

* Comment new tests for now
2021-07-02 12:52:00 +02:00
Felix Fontein
c63dc624b7 Fix snap module, and module helper behavior on rc != 0 in output (#2912)
* Try some snap fixes.

* Fix logic.

* Try to run tests privileged.

* Prevent failure on rc != 0.

* Fix formatting.

* Revert "Try to run tests privileged."

This reverts commit 77ca91f502.

* Try to run tests on RHEL instead.

* Make sure that snapd is running.

* Add changelog fragment.

* str -> to_native.

* Make sure that installed binary is actually found.

* Add check mode tests.

* Mention #2835 in changelog fragment.
2021-07-01 18:53:48 +02:00
Amin Vakil
a97d82be88 Add integration tests for snap (#2907)
* Add integration tests for snap

* Also test on fedora and remove snapd if it was not installed

* disable test for now
2021-06-30 15:06:56 +02:00
Gaetan2907
0e829e6a23 Fix bug when 2 identical executions in same auth flow (#2904)
* Fix bug when 2 identical executions in same auth flow

* Add changelog fragment

* Fix unit tests

* Update changelogs/fragments/2904-fix-bug-when-2-identical-executions-in-same-auth-flow.yml

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-06-30 15:01:17 +02:00
Felix Fontein
677e88b257 The next release will be 3.4.0. 2021-06-29 12:38:55 +02:00
NivKeidan
9c7b539ef6 Add fallback url for jenkins plugin (#1334)
* uncoupled updates_url from plugin download urls
added new parameters: versioned_plugins_url, latest_plugins_url

* parameters updates_url, latest_plugins_url and versioned_plugins_url changed type to list of strings to implement fallback URLs usage
added type conversion if they are string (backward compatibility)

* removed type conversion this is handled by ansible validation
fix: dont fail if first url fails

* added fallback: if installation from plugin manager fails, try downloading the plugin manually

* fixed test failures

* PEP8 indent fix

* changelog fragment

* added debug outputs for new url fallback behavior

* added version_added in description for latest_plugins_url

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

* added version_added in description for versioned_plugins_url

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

* Update changelogs/fragments/1334-jenkins-plugin-fallback-urls.yaml

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

* improve backwards-compatibility
add optional arg to allow custom update-center.json targets

* pep8 fixes

* fix inconsistency in argument documentation

* Apply suggestions from code review

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

* add unit tests

* fix pep8

* Apply suggestions from code review

Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Amin Vakil <info@aminvakil.com>
2021-06-29 10:26:59 +04:30
omula
2d1527a564 [nmcli] add connection.slave-type for teamed devices (#2827)
* [nmcli] add connection.slave-type for teamed devices

* [nmcli] add fragment with changes for #2827

* [nmcli] add tests for network team

* [nmcli] fix testing

Co-authored-by: Oriol MULA VALLS <oriol.mula@lxp.lu>
2021-06-28 20:46:44 +02:00
Martin
debb15efbe pacman: Descriptive state documentation (#2894)
* pacman: Descriptive state documentation

* Update plugins/modules/packaging/os/pacman.py

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

Co-authored-by: Martin Rys <martin@rys.pw>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-06-27 18:47:11 +02:00
Amin Vakil
0a9cf38118 yum_versionlock: fix idempotency when using wildcard (asterisk) (#2787)
* Check idempotency on yum_versionlock

* Lock packages wildcard

* fix formatting

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

* Fix formatting in asserts

* little closer but not still there

* Import fnmatch

* Change check_mode logic

* Add check_mode for add

* Add changelog

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-06-27 16:40:49 +02:00
Stef Graces
c7cf6f2eb7 gitlab_project - Add ability to create project under a user (#2824)
* Add ability to create project under a user

* Add changelog

* Add username option

* Update changelogs/fragments/2824-gitlab_project-project-under-user.yml

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

* Make group and username mutually exclusive

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-06-27 18:39:41 +04:30
quidame
199ead85d0 java_keystore: fix keystore type (#2516)
* fix keystore type; update unit tests

* add changelog fragment

* document new param 'keystore_type'

* add keystore_type support (backward compatible)

* check JKS format with magic bytes
* update integration tests
* revert first changes in unit tests
* update changelog fragment

* fix magic bytes for python2/python3

* fix integration tests (irrelevant check_mode)

* fix unit test (keystore removed before failure => changed=true)

* fix typo

* fix spelling

* shorten a branch

* mock is_jks_or_pkcs12

* fix function path in unit tests

* Apply suggestions from code review (spelling)

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* rename a method (module + unit tests)

* move ArgumentSpec class content to main()

* refactor create() to not loose existing keystore in case of error

* update unit tests

* add integration test (error handling)

* fix keystore backup cleanup

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
2021-06-27 14:56:43 +02:00
Stef Graces
2fb0877577 Fix/gitlab project user workspace (#2881)
* Add ability to create project under a user

* Add changelog

* Change minor_changes in changelog

As suggested in this comment https://github.com/ansible-collections/community.general/pull/2824#discussion_r653411741

* Fix user's namespace

* Delete changelog

* Add changelog

* Fix changelog

Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Amin Vakil <info@aminvakil.com>

* Change user_group_id to namespace_group_id

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

* Change to namespace_id

Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Amin Vakil <info@aminvakil.com>
2021-06-27 16:31:06 +04:30
Alexei Znamensky
9dd91f949a terraform - added check_destroy (#2874)
* added check_destroy

This is based on the work done in PR 398. Authors from that PR:

Co-authored-by: effaamponsah <kamponsah.amponsah@gmail.com>
Co-authored-by: m-yosefpor
Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

* added changelog fragment

* Update plugins/modules/cloud/misc/terraform.py

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Update changelogs/fragments/2874-terraform-check-destroy.yml

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

Co-authored-by: effaamponsah <kamponsah.amponsah@gmail.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>
Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
Co-authored-by: Amin Vakil <info@aminvakil.com>
2021-06-27 12:38:04 +02:00
Felix Fontein
147425ef93 ini_file: fix regression reported in #2578 (#2875)
* Add regression test.

* Add more Unicode tests.

* Add fix.

* Add changelog.

* Work completely with Unicode.

* Update plugins/modules/files/ini_file.py

Co-authored-by: quidame <quidame@poivron.org>

Co-authored-by: quidame <quidame@poivron.org>
2021-06-27 10:00:01 +02:00
Felix Fontein
1b94d09209 Add option type validation. (#2878) 2021-06-27 09:57:51 +02:00
Alexei Znamensky
acf7b106c9 _mount module utils - fixed sanity checks (#2883)
* updated _mount.py, removed ignore lines

* added changelog fragment
2021-06-27 09:39:08 +02:00
Felix Fontein
fafabed9e6 Replace ansible.module_utils._text by ansible.module_utils.common.text.converters (#2877)
* Replace ansible.module_utils._text by ansible.module_utils.common.text.converters.

* Also adjust tests.
2021-06-26 23:59:11 +02:00
Ajpantuso
d180390dbc modprobe - fix task status when module cannot be loaded (#2843)
* Initial Commit

* Adding changelog fragment

* Ensured params are present during verbose output and enhanced check_mode

* Making specific to builtins

* Removing unneccessary external call

* Acutal bugfix
2021-06-26 23:27:41 +12:00
Felix Fontein
d2a984ded1 Adjust example to remove unnecessary offensive language. (#2869) 2021-06-24 22:57:40 +02:00
Felix Fontein
2d1f5408d3 Redis: slave -> replica (#2867)
* Redis: slave -> replica

* Fallback for old Redis versions in CI.
2021-06-24 22:33:29 +02:00
Gaetan2907
24c5d4320f Keycloak: add authentication management (#2456)
* Allow keycloak_group.py to take token as parameter for the authentification

Refactor get_token to pass module.params + Documentation

Fix unit test and add new one for token as param

Fix identation

Update plugins/modules/identity/keycloak/keycloak_client.py

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

Update plugins/modules/identity/keycloak/keycloak_clienttemplate.py

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

Allow keycloak_group.py to take token as parameter for the authentification

Refactor get_token to pass module.params + Documentation

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

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

Check if base_url is None before to check format

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

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

Update plugins/modules/identity/keycloak/keycloak_client.py

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

Update plugins/modules/identity/keycloak/keycloak_clienttemplate.py

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

Switch to modern syntax for the documentation (e.g. community.general.keycloak_client)

Update keycloak_client.py

Update keycloak_clienttemplate.py

Add keycloak_authentication module to manage authentication

Minor fixex

Fix indent

* Update plugins/modules/identity/keycloak/keycloak_authentication.py

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

Update plugins/modules/identity/keycloak/keycloak_authentication.py

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

Update plugins/modules/identity/keycloak/keycloak_authentication.py

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

Update plugins/modules/identity/keycloak/keycloak_authentication.py

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

Update plugins/modules/identity/keycloak/keycloak_authentication.py

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

Removing variable ANSIBLE_METADATA from beginning of file

Minor fix

Refactoring create_or_update_executions :add change_execution_priority function

Refactoring create_or_update_executions :add create_execution function

Refactoring create_or_update_executions: add create_subflow

Refactoring create_or_update_executions: add update_authentication_executions function

Minor fix

* Using FQCN for the examples

Minor fix

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

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

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

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

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

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

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

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

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

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

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

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

* Update plugins/modules/identity/keycloak/keycloak_authentication.py

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

Update plugins/modules/identity/keycloak/keycloak_authentication.py

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

Refactoring: rename isDictEquals into is_dict_equals

Refactoring: rename variable as authentication_flow

Refactoring: rename variable as new_name

Refactoring: rename variable as flow_list

Refactoring: rename variable as new_flow

Refactoring: changing construction of dict newAuthenticationRepresentation and renaming as new_auth_repr

Minor fix

* Refactoring: rename variables with correct Python syntax (auth_repr, exec_repr)

Move create_or_update_executions function from keycloak.py to keycloak_authentication.py

Minor fix

Remove mock_create_or_update_executions not needed anymore

Fix unit test

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

is_dict_equals function return True if value1 empty

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

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

Rename is_dict_equal as is_struct_included and rename params as struct1 and struct2

Rename variables according to Python naming conventions

Refactoring: add find_exec_in_executions function in keycloak_authentication to remove code duplication

typo

Add blank line

Add required parameter, either creds or token

Typo

try/except only surround for loop containing struct2[key]

Add sub-options to meta_args

assigment of result['changed'] after if-elif-else block

Fix CI error: parameter-type-not-in-doc

Fix unit test: none value excluded from comparison

Minor fix

Simplify is_struct_included function

Replace 'type(..) is' by isinstance(..)

Remove redundant required=True and redundant parenthesis

Add check_mode, check if value is None (None value added by argument spec checker)

Apply suggestions from code review

Update plugins/modules/identity/keycloak/keycloak_authentication.py

* Update plugins/modules/identity/keycloak/keycloak_authentication.py

* Add index paramter to configure the priority order of the execution

* Minor fix: authenticationConfig dict instead of str

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-06-24 13:35:00 +02:00
Ajpantuso
24dabda95b archive - refactor and bugfix (#2816)
* Initial Commit

* Further refinement

* Fixing archive name distortion for single file zips

* Applying initial review suggestions

* Updating path value for single target

* Adding test case for single target zip archiving

* Fixing integration for RHEL/FreeBSD on ansible 2.x

* Fixing integration second attempt

* Adding changelog fragment

* Updating changelog fragment
2021-06-24 13:33:10 +02:00
Tong He
860b2b89a3 jenkins_build: Support stop a running Jenkins build (#2850)
* Support stop a running Jenkins build. Meanwhile enrich document content and test cases.

* Fix the inconsistencies regarding the function name.

* Submit the changelog and fix a PEP8 issue.

* Remedy whitespace related PEP8 issues.

* Implement the idempotent test case for the stop build function.

* Make sure it returns proper changed status when we stop a build repeatedly.

* Fix incorrect usages on comparison with True or False and incorrect usages on validating the changed status.

* In this mocking situation, adjust the mock return value and test case to perform unit testing.

* Implement JenkinsMockIdempotent() to mock return value in idempotent test cases.

* Fix issues reported by CI.

* Refactor the code to avoid CI exception and remove get_build_status() from mock function as they should not be there.

* Update plugins/modules/web_infrastructure/jenkins_build.py

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-06-23 23:29:50 +02:00
Felix Fontein
07085785a3 Dynamically add meta/runtime.yml redirects before integration tests. (#2633)
ci_coverage
2021-06-22 08:16:26 +02:00
Lennert Mertens
d6d0b6f0c1 gitlab_user: add support for identity provider (#2691)
* Add identity functionality

* Add functionality for user without provider or extern_uid

* Fix missing key error and documentation

* Fix failing tests

* Update docs

* Add changelog fragment

* Update plugins/modules/source_control/gitlab/gitlab_user.py

Add version

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

* Update plugins/modules/source_control/gitlab/gitlab_user.py

Update boolean default

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

* Update plugins/modules/source_control/gitlab/gitlab_user.py

Fix syntax

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

* Update plugins/modules/source_control/gitlab/gitlab_user.py

Remove no_log

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

* Update changelogs/fragments/2691-gitlab_user-support-identity-provider.yml

Update syntax

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

* Update plugins/modules/source_control/gitlab/gitlab_user.py

Update syntax

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

* Update docs

* Add functionality to add multiple identities at once

* Fix identity example

* Add suboptions

* Add elements

* Update plugins/modules/source_control/gitlab/gitlab_user.py

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

* Apply comma's at the end of dictionaries

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

* Add check mode

* Change checkmode for user add and identity delete

* Update plugins/modules/source_control/gitlab/gitlab_user.py

* Update changelogs/fragments/2691-gitlab_user-support-identity-provider.yml

Add more features to changelog as suggested here https://github.com/ansible-collections/community.general/pull/2691#discussion_r653250717

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

* Add better description for identities list and overwrite_identities boolean

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

Co-authored-by: lennert.mertens <lennert.mertens@nubera.eu>
Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: stef.graces <stef.graces@nubera.eu>
Co-authored-by: Stef Graces <stefgraces@hotmail.com>
Co-authored-by: Stef Graces <sgraces@sofico.be>
Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-06-21 21:32:07 +02:00
Stanislav German-Evtushenko
ce35d88094 gem_module: Add bindir option (#2837)
* gem_module: Add bindir option

This option allows to specify directory to install executables, e.g.
`/home/user/bin` or `/home/user/.local/bin`. This comes especially handy
when used with user_install option as the default path of executables is
not in PATH.

* Update changelogs/fragments/gem_module_add_bindir_option.yml

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* gem_module: Integration tests for bindir option

* gem_module: Update Integration tests for bindir option

* gem_module: Update Integration tests for bindir option

Make sure gist is not installed system-wide prior the tests

* Revert "gem_module: Update Integration tests for bindir option"

This reverts commit 04eec6db27.

* Do not check "install_gem_result is changed" for ansible develop on openSUSE

* Revert "Do not check "install_gem_result is changed" for ansible develop on openSUSE"

This reverts commit 48ecb27889.

* gem_module: Use --norc to avoid surprises

Run install and uninstall actions with `--norc`. This way ansible has
more control over the way gems are installed.

* Revert "gem_module: Use --norc to avoid surprises"

This reverts commit 66f40bcfe6.

* gem_module: bindir - Ignore openSUSE Leap

* Update plugins/modules/packaging/language/gem.py

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

* gem_module: Use --norc to avoid surprises

Run install and uninstall actions with `--norc` when supported (rubygems >= 2.5.2).
This way ansible has more control over the way gems are installed.

* Try distutils.version instead of packaging

* ver is an list, not string

* ver is not list either but tuple

* Update changelogs/fragments/gem_module_add_bindir_option.yml

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

* ver can be None (when can this happen?)

* gem: Add norc option

* Apply suggestions from code review

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

* Update plugins/modules/packaging/language/gem.py

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

* Use tuples to compare versions

* Apply suggestions from code review

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

* Update plugins/modules/packaging/language/gem.py

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

* lost norc option check is back

* Move handling norc option to separate function

* cosmetic

* fix for the previos commit

* Apply suggestions from code review

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

* Cache result of get_rubygems_version

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
Co-authored-by: Amin Vakil <info@aminvakil.com>
2021-06-21 19:53:03 +12:00
Alexei Znamensky
519411e026 ali_instance_info - marked parameters for deprecation in c.g. 5.0.0 (#2844)
* marked parameters for deprecation in c.g. 5.0.0

* added changelog fragment

* deprecate params in arg_spec

* doc adjusment per PR
2021-06-20 13:17:58 +02:00
Alexei Znamensky
2768eda895 serverless - deprecating unused param (#2845)
* deprecating unused param

* added changelog fragment

* deprecate param in arg_spec

* Update plugins/modules/cloud/misc/serverless.py

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-06-20 13:07:45 +02:00
Anup Chenthamarakshan
db713bd0f5 proxmox_kvm: Fix ZFS device string parsing (#2841)
ZFS-backed block devices may contain just the bare device name and
not have extra options like `,size=foo`, `,format=qcow2` etc. This
breaks an assumption in existing regex (which expects a comma).

Support such device strings and add a couple of testcases to validate.
2021-06-20 12:42:19 +02:00
Felix Fontein
08f7ad06be Remove inventory and vault scripts (#2696)
* Remove inventory and vault scripts.

* Remove foreman inventory script tests.
2021-06-19 15:06:58 +02:00
omula
67cabcb2aa Nmcli add options (#2732)
* [nmcli] add new network configuration options

* [nmcli_add_options] add documentation for new parameters nad add disabled method for IPv6

* [nmcli] fix and version adding. Add changelog fragment

* Update plugins/modules/net_tools/nmcli.py

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

* Update changelogs/fragments/2732-nmcli_add_options.yml

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

* Update changelogs/fragments/2732-nmcli_add_options.yml

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

* [nmcli_add_options] fix testing

* Update plugins/modules/net_tools/nmcli.py

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

* Update plugins/modules/net_tools/nmcli.py

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

* Update changelogs/fragments/2732-nmcli_add_options.yml

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

* Update plugins/modules/net_tools/nmcli.py

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

* Update plugins/modules/net_tools/nmcli.py

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

* Update plugins/modules/net_tools/nmcli.py

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

Co-authored-by: Oriol MULA VALLS <oriol.mula@lxp.lu>
Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Amin Vakil <info@aminvakil.com>
2021-06-19 14:42:05 +02:00
Shahar Mor
1ed4394c5e npm - fix updating version specific modules (#2830)
* npm - fix updating version specific modules

if a version specific module is used, the comparison will be used with the version and not only by name

* Update plugins/modules/packaging/language/npm.py

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Update changelogs/fragments/2830-npm-version-update.yml

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>

* Update changelogs/fragments/2830-npm-version-update.yml

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

* Update changelogs/fragments/2830-npm-version-update.yml

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

Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
Co-authored-by: Amin Vakil <info@aminvakil.com>
2021-06-18 22:08:46 +02:00
TizeN85
ee23c26150 fix sudorule_add_allow_command_group (#2821)
* fix sudorule_add_allow_command_group

fix sudorule_add_allow_command_group is not working on freeIPA 4.8.7 at least, sudorule_add_allow_command should be used instead with item sudocmdgroup

* Added changelog fragment
2021-06-17 19:08:42 +02:00
Anas
c9cf641188 datadog_event : Adding api_host as an optional parameter (#2775)
* 2774 Module datadog_event _ Adding api_host as an optional parameter

* Update changelogs/fragments/2774-datadog_event_api_parameter.yml

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

* Update plugins/modules/monitoring/datadog/datadog_event.py

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

* Update datadog_event.py

* Update datadog_event.py

* Update datadog_event.py

* Update datadog_event.py

* Update datadog_event.py

* Update datadog_event.py

* Update datadog_event.py

* Update datadog_event.py

* Update plugins/modules/monitoring/datadog/datadog_event.py

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

* Update plugins/modules/monitoring/datadog/datadog_event.py

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

* Update plugins/modules/monitoring/datadog/datadog_event.py

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

* Update plugins/modules/monitoring/datadog/datadog_event.py

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

* Update plugins/modules/monitoring/datadog/datadog_event.py

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

* Update plugins/modules/monitoring/datadog/datadog_event.py

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

Co-authored-by: Anas Hamadeh <anas.hamadeh@klarna.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Amin Vakil <info@aminvakil.com>
2021-06-17 19:05:35 +02:00
Andrew Klychkov
e9f3455b62 Update README (#2802)
* Update README

* Update README.md

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

* Change

* Fix

* Update README.md

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

* Update README.md

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

* Fix

* Fix

* Fix

* Fix

* Fix

* Fix

* Fix

* Update README.md

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

Co-authored-by: Amin Vakil <info@aminvakil.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-06-17 21:48:39 +12:00
Amin Vakil
13ab8f412d Rename test_pr_quick_start_guide.rst to test_pr_locally_guide.rst (#2823) 2021-06-17 21:47:28 +12:00
Alexei Znamensky
3997d5fcc8 flatpak - allow to add/remove multiple flatpaks at once (#2521)
* reviving flatpack PR

* added changelog fragment

* adjusted integration tests per PR

* adjusted examples to use the full name of the module

* Use new local artifacts.

* Re-add StrictVersion import.

* Try to clean up PR.

* ...

* Use original name in installed/not installed list.

* More fixes.

* Work around flatpak bug.

* Fix bug I introduced.

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-06-17 08:00:49 +02:00
Abhijeet Kasurde
4a47d121aa pamd: Add a note in docs about authselect profiles (#2815)
pamd module does not handle or modify authselect profiles
which are basically template files for authselect. The autheselect
generates pam.d files from these profiles.

Fixes: #1954

Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>
2021-06-16 21:23:54 +02:00
Ajpantuso
3ca98c2edd callback_splunk - Add user-configurable event correlation id (#2790)
* Initial commit

* Adding changelog fragment

* Updating batch description

* Update plugins/callback/splunk.py

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-06-16 22:28:09 +04:30
Tong He
2f2f384b4e redhat_subscription: Add server_prefix and server_port as supported arguments (#2779)
* Add server_prefix and server_port as supported arguments for the redhat_subscription module.

* Adjust the argument sequence in the test case to be consistent with the original code in line 364 in redhat_subscription.py and add the changelog fragment.

* Grammatical changes such as adding full stops and using 'an HTTP' instead of 'a HTTP'.

* Commit the suggested changelog update.

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

* Fix typo.

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

Co-authored-by: Amin Vakil <info@aminvakil.com>
2021-06-16 11:31:54 +04:30
Amin Vakil
adf50b106a Add Test PRs locally section to CONTRIBUTING.md (#2738)
* Add Test PRs locally section to CONTRIBUTING.md

* fix formatting

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

* Adjust PR now that ansible-collections/community-docs#16 has been merged

* improve sentence

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>
2021-06-15 19:19:18 +02:00
Andrew Klychkov
b1b34ee12e BOTMETA.yml: grant supershipit (#2807) 2021-06-15 13:11:48 +00:00
Andrew Klychkov
bccf317814 BOTMETA.yml: supershipit to quidame (#2801) 2021-06-14 20:38:28 +02:00
Abhijeet Kasurde
0bd345bfb0 timezone: change warning to debug (#2789)
* timezone: change warning to debug

Convert warning message to debug when timedatectl found but not usable.

Fixes: #1942

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

* add changelog entry

Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>
2021-06-14 18:22:01 +02:00
Felix Fontein
a55c96d5c1 Make extra sanity test runner produce ansibullbot and JUnit output. (#2794) 2021-06-14 07:25:46 +02:00
Felix Fontein
d4c4d00ad1 CI: Remove scripts that are no longer needed (#2793)
* Remove scripts that are no longer needed.

ci_complete

* Remove sanity ignores.
2021-06-13 23:01:46 +02:00
Alina Buzachis
343339655d Documentation fix for access_level parameter of gitlab_runner (#2788)
* * Documentation fix for access_level parameter of gitlab_runner

Signed-off-by: Alina Buzachis <abuzachis@redhat.com>

* Address reviewer's comments

Signed-off-by: Alina Buzachis <abuzachis@redhat.com>
2021-06-13 08:25:50 +02:00
Abhijeet Kasurde
4b37b1bca6 scaleway: Misc doc changes (#2776)
* Updated example section for ``variables``
* Added link about token generation
* Misc changes in doc

Fixes: #467

Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>
2021-06-11 13:24:11 +02:00
Amin Vakil
19549058ce yum_versionlock: enable fedora34 integration test (#2543)
* Re-enable Fedora 34

* Update procps-ng before anything in yum_versionlock integration test

* Move procps-ng installation to block

* Revert "Move procps-ng installation to block"

This reverts commit 3aa873a110.

* Update procps-ng only on Fedora 34
2021-06-11 13:12:01 +02:00
Loïc
c2ce7a0752 [scaleway inventory] Fix JSON object must be str, not 'bytes' (#2771)
* Fix JSON object decoding

* Code improvement : python 3.5 fix

* Add changelog fragment

* Update changelogs/fragments/2771-scaleway_inventory_json_accept_byte_array.yml

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-06-11 13:05:29 +02:00
Rémy Keil
f44300cec5 add inventory plugin unit test test_verify_file (#2773)
* add inventory plugin unit test `test_verify_file`

* fix typos in `test_verify_file_bad_config` unit test
2021-06-10 22:05:04 +02:00
Felix Fontein
1e968bce27 Next expected release is 3.3.0. 2021-06-08 14:47:51 +02:00
Amin Vakil
dab5d941e6 Add domain option to onepassword lookup (#2735)
* Add domain to onepassword lookup

* Add changelog

* Add default to domain documentation

* Improve format

* Fix sanity issue

* Add option type to documentation

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

* Add domain to init

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-06-08 11:41:21 +02:00
Alexei Znamensky
eef645c3f7 with great powers come great responsibility (#2755) 2021-06-08 10:36:14 +02:00
Alexei Znamensky
9f344d7165 Fixed sanity checks for cloud/scaleway/ modules (#2678)
* fixed validation-modules for plugins/modules/cloud/scaleway/scaleway_image_info.py

* fixed validation-modules for plugins/modules/cloud/scaleway/scaleway_ip_info.py

* fixed validation-modules for plugins/modules/cloud/scaleway/scaleway_security_group_info.py

* fixed validation-modules for plugins/modules/cloud/scaleway/scaleway_server_info.py

* fixed validation-modules for plugins/modules/cloud/scaleway/scaleway_snapshot_info.py

* fixed validation-modules for plugins/modules/cloud/scaleway/scaleway_volume_info.py

* sanity fix
2021-06-08 10:33:57 +02:00
Felix Fontein
bb37b67166 flatpak: add tests in CI, add no_dependencies parameter (#2751)
* Similar version restrictions than flatpak_remote tests.

* ...

* Try to work around missing dependencies.

* Revert "Try to work around missing dependencies."

This reverts commit 66a4e38566.

* Add changelog.

* App8 -> App2; make sure that there are two apps App1 and App2.

* Fix forgotten variabe.

* Remove test notices.

* Seems like flatpak no longer supports file:// URLs.

The tests would need to be rewritten to offer the URL via http:// instead.

* Try local HTTP server for URL tests.

* ...

* Lint, add status check.

* Add boilerplate.

* Add 'ps aux'.

* Surrender to -f.

* Work around apparent flatpak bug.

* Fix YAML.

* Improve condition.

* Make sure test reruns behave better.
2021-06-08 08:46:20 +02:00
Amin Vakil
94a53adff1 zypper_repository: fix idempotency on adding repo with releasever and basearch variables (#2722)
* zypper_repository: Check idempotency on adding repo with releasever

* Name required when adding non-repo files.

* Initial try to fix releasever

* Replace re.sub with .replace

* name releaseverrepo releaseverrepo

* Change  to ansible_distribution_version for removing repo

* improve asserts format

* add changelog

* Fix changelog formatting

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

* improve command used for retrieving releasever variable

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

* add basearch replace

* Add basearch to changelog fragment

* Check for releasever and basearch only when they are there

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-06-08 08:23:32 +02:00
Felix Fontein
4c50f1add7 Re-enable flatpak_remote tests (#2747)
* Automate test repo creation, re-enable flatpak_remote tests.

* Linting.

* Another try.
2021-06-07 21:22:21 +02:00
Amin Vakil
7c3f2ae4af Remove aminvakil from supershipit section as it is not needed anymore (#2743) 2021-06-07 18:57:51 +04:30
Amin Vakil
1e34df7ca0 Add aminvakil to committers (#2739) 2021-06-07 15:17:57 +02:00
Alexei Znamensky
6a41fba2f8 ModuleHelper - also uses LC_ALL to force language (#2731)
* also uses LC_ALL to force language

* adjusted test_xfconf and test_cpanm

* added changelog fragment

* Update changelogs/fragments/2731-mh-cmd-locale.yml

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

* adjusted chglog frag per PR

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-06-07 13:06:23 +02:00
Alexei Znamensky
f74b83663b Bugfix + sanity checks for stacki_host (#2681)
* fixed validation-modules for plugins/modules/remote_management/stacki/stacki_host.py

* sanity fix

* added changelog fragment

* extra fix to the documentation

* Update plugins/modules/remote_management/stacki/stacki_host.py

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

* Update plugins/modules/remote_management/stacki/stacki_host.py

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

* rollback params

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-06-07 07:58:26 +02:00
quidame
463c576a67 iptables_state: fix async status call (-> action plugin) (#2711)
* fix call to async_status (-> action plugin)

* add changelog fragment

* Apply suggestions from code review

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

* rename a local variable for readability

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-06-06 08:20:52 +02:00
The Binary
9d8bea9d36 open_iscsi: allow same target selected portals login and override (#2684)
* fix: include portal and port for logged on check

* refactor: remove extra space

* fix: allow None portal and port on target_loggedon test

* add auto_portal_startup argument

* fix: change param name for automatic_portal

* add changelog fragment

* refactor: Update changelogs/fragments/2684-open_iscsi-single-target-multiple-portal-overrides.yml

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

* add version added info to auto_portal_startup arg

* add example for auto_portal_startup

* fix: remove alias for auto_portal form arg_spec as well

* refactor: elaborate in fragment changelogs

Elaborate change

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

* open_iscsi: elaborate changelog fragment

* Update plugins/modules/system/open_iscsi.py

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

Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Amin Vakil <info@aminvakil.com>
2021-06-05 22:40:49 +02:00
fkuep
0e6d70697c Wire token param into consul_api #2124 (#2126)
* Wire token param into consul_api #2124

* Update changelogs/fragments/2124-consul_kv-pass-token.yml

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

* #2124 renamed release fragment to match pr, removed parse_params.

* putting look back in, do some linting   #2124

* try more linting

* linting

* try overwriting defaults in parse_params with get_option vals, instead of removing that function completely.

* Revert "back to start, from 2nd approach: allow keyword arguments via parse_params for compatibility."

This reverts commit 748be8e366.

* Revert " linting"

This reverts commit 1d57374c3e.

* Revert " try more linting"

This reverts commit 91c8d06e6a.

* Revert "putting look back in, do some linting   #2124"

This reverts commit 87eeec7180.

* Revert " #2124 renamed release fragment to match pr, removed parse_params."

This reverts commit d2869b2f22.

* Revert "Update changelogs/fragments/2124-consul_kv-pass-token.yml"

This reverts commit c50b1cf9d4.

* Revert "Wire token param into consul_api #2124"

This reverts commit b60b6433a8.

* minimal chnages for this PR relative to current upstream.

* superfluous newline in changlog fragment.

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2021-06-05 22:38:42 +02:00
Anton Nikolaev
1a4af9bfc3 Reduce stormssh searches based on host (#2568)
* Reduce stormssh searches based on host

Due to the stormssh searches in the whole config values, we need to reduce the search results based on the full matching of the hosts

* Removed whitespaces in the blank line

* Added changelog fragment and tests for the fix.

* Added newline at the end of the changelog fragment

* Added newline at the end of the tests

* Fixed bug with name in tests

* Changed assertion for the existing host

* Update changelogs/fragments/2568-ssh_config-reduce-stormssh-searches-based-on-host.yml

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

* Adjusted tests

* New line at the end of the tests

Co-authored-by: Anton Nikolaev <anikolaev@apple.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-06-05 14:53:02 +02:00
christophemorio
c49a384a65 Terraform: ensure workspace is reset to current value (#2634)
* fix: ensure workspace is reset to current value

* chore: linter

* chore: changelog
2021-06-04 19:12:29 +02:00
Alex Willmer
a343756e6f Fix repeated word in description of fs_type (#2717) 2021-06-04 19:11:46 +02:00
Felix Fontein
4396ec9631 Fix action plugin BOTMETA entries. (#2707) 2021-06-04 10:35:35 +02:00
Felix Fontein
d49783280e Add new module/plugin maintainers to BOTMETA. (#2708) 2021-06-04 10:34:27 +02:00
Felix Fontein
2e8746a8aa Fix spurious test errors. (#2709) 2021-06-04 09:53:34 +02:00
rainerleber
a4f46b881a Add module sapcar_extract to make SAP administration easier. (#2596)
* add sapcar

* integrate test

* test integration

* Revert "integrate test"

This reverts commit 17cbff4f02.

* add requiered

* change test

* change binary

* test

* add bin bath

* change future

* change download logic

* change logic

* sanity

* Apply suggestions from code review

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

* add url and error handling

* sanity

* Apply suggestions from code review

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

* Apply suggestions from code review

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

* cleanup and fixes

* sanity

* add sec library

* add description

* remove blanks

* sanity

* Apply suggestions from code review

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

Co-authored-by: Rainer Leber <rainer.leber@sva.de>
Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>
2021-06-04 07:36:35 +02:00
George Rawlinson
5ddf0041ec add module pacman_key (#778)
* add module pacman_key

* add symlink and fix documentation for pacman_key

* documentation fix for pacman_key

* improve logic around user input

* Update plugins/modules/packaging/os/pacman_key.py

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

* Update plugins/modules/packaging/os/pacman_key.py

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

* Update plugins/modules/packaging/os/pacman_key.py

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

* Update plugins/modules/packaging/os/pacman_key.py

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

* Update plugins/modules/packaging/os/pacman_key.py

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

* Update plugins/modules/packaging/os/pacman_key.py

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

* Update plugins/modules/packaging/os/pacman_key.py

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

* Update plugins/modules/packaging/os/pacman_key.py

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

* Update plugins/modules/packaging/os/pacman_key.py

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

* Update plugins/modules/packaging/os/pacman_key.py

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

* Improve parameter checking

required_one_of=[] is neat.

Co-authored-by: Alexei Znamensky

* Revert "Improve parameter checking"

This reverts commit 044b0cbc85.

* Simplify a bunch of code.

* fix typos pointed out by yan12125

* replaced manual checks with required-if invocation

* added default keyring to documentation

* some initial tests

* updated metadata

* refactored to make sanity tests pass

* refactor to make sanity tests pass ... part deux

* refactor: simplify run_command invocations

* test: cover check-mode and some normal operation

* docs: fix grammatical errors

* rip out fingerprint code

a full length (40 characters) key ID is equivalent to the fingerprint.

* refactor tests, add a couple more

* test: added testcase for method: data

* Update plugins/modules/packaging/os/pacman_key.py

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

* docs: correct yaml boolean type

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

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>
Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-06-04 07:08:54 +02:00
Matthias Vogelgesang
d93bc039b2 BOTMETA.yml: remove myself from zypper_repository (#2701) 2021-06-03 22:54:19 +02:00
Benjamin Schubert
efbda2389d keycloak_realm.py: Fix the ssl_required parameter according to the API (#2693)
* keycloak_realm.py: Fix the `ssl_required` parameter according to the API

The `ssl_required` parameter is a string and must be one of 'all',
'external' or 'none'. Passing a bool will make the server return a 500.

* fixup! keycloak_realm.py: Fix the `ssl_required` parameter according to the API

* Update changelogs/fragments/keycloak_realm_ssl_required.yml

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-06-03 21:44:54 +02:00
Benjamin Schubert
fe5717c1aa keycloak_realm.py: Mark 'reset_password_allowed' as no_log=False (#2694)
* keycloak_realm.py: Mark 'reset_password_allowed' as no_log=False

This value is not sensitive but Ansible will complain about it otherwise

* fixup! keycloak_realm.py: Mark 'reset_password_allowed' as no_log=False

* Apply all suggestions from code review

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-06-03 21:42:05 +02:00
Gene Gotimer
ca1506fb26 Added SHA1 option to maven_artifact (#2662)
* Added SHA1 option

* Add changelog fragment

* Update plugins/modules/packaging/language/maven_artifact.py

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

* Update plugins/modules/packaging/language/maven_artifact.py

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

* Combined hash functions

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

* Update plugins/modules/packaging/language/maven_artifact.py

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

* Update plugins/modules/packaging/language/maven_artifact.py

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

* Removed unused functions (rolled into _local_checksum)

* Update changelogs/fragments/2661-maven_artifact-add-sha1-option.yml

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-06-01 22:06:26 +02:00
Chih-Hsuan Yen
1ad85849af nmcli: new arguments to ignore automatic dns servers and gateways (#2635)
* nmcli: new arguments to ignore automatic dns servers and gateways

Closes #1087

* Add changelog fragment

* Address review comments
2021-06-01 22:04:09 +02:00
Felix Fontein
3516acf8d4 Add filter docs (#2680)
* Began with filter docs.

* Add more filters.

* Add time unit filters.

* Add TOC and filters to create identifiers.

* Add more filters.

* Add documentation from ansible/ansible for json_query and random_mac.

* Update docs/docsite/rst/filter_guide.rst

Co-authored-by: Abhijeet Kasurde <akasurde@redhat.com>

Co-authored-by: Abhijeet Kasurde <akasurde@redhat.com>
2021-06-01 19:03:07 +02:00
Ajpantuso
b6c0cc0b61 archive - Adding exclusion_patterns option (#2616)
* Adding exclusion_patterns option

* Adding changelog fragment and Python 2.6 compatability

* Minor refactoring for readability

* Removing unneccessary conditional

* Applying initial review suggestions

* Adding missed review suggestion
2021-05-31 07:51:29 +02:00
Alexei Znamensky
bef3c04d1c Fixed sanity checks for cloud/online/ modules (#2677)
* fixed validation-modules for plugins/modules/cloud/online/online_server_info.py

* fixed validation-modules for plugins/modules/cloud/online/online_user_info.py

* sanity fix
2021-05-29 16:48:59 +02:00
quidame
f09c39b71e iptables_state: fix broken query of async_status result (#2671)
* use get() rather than querying the key directly

* add a changelog fragment

* re-enable CI tests

* Update changelog fragment

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-29 10:50:24 +02:00
Ajpantuso
b281d3d699 proxmox_kvm - Fixed vmid result when VM with name exists (#2648)
* Fixed vmid result when VM with name exists

* Adding changelog fragment
2021-05-29 09:00:12 +02:00
Amin Vakil
c3cab7c68c composer: add composer_executable (#2650)
* composer: add composer_executable

* Add changelog

* Improve documentation thanks to felixfontein

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-28 12:49:29 +02:00
Felix Fontein
14813a6287 Stop mentioning Freenode. We're on Libera.chat. (#2666) 2021-05-28 07:09:57 +02:00
Felix Fontein
14f13904d6 Add extra docs tests (#2663)
* Add extra docs tests.

* Linting.

* Fix copy'n'paste error.
2021-05-27 22:59:42 +02:00
Alexei Znamensky
3afcf7e75d minor refactors on plugins/modules/cloud/misc (#2557)
* minor refactors on plugins/modules/cloud/misc

* added changelog fragment

* removed unreachable statement

* Update plugins/modules/cloud/misc/terraform.py

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

* Update plugins/modules/cloud/misc/rhevm.py

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

* adjusted per PR comment

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-27 19:13:21 +02:00
Abhijeet Kasurde
43c12b82fa random_string: a new lookup plugin (#2572)
New lookup plugin to generate random string based upon
constraints.

Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>
2021-05-27 19:09:26 +02:00
Merouane Atig
95794f31e3 Fix drain example with correct wait values (#2603) 2021-05-27 19:08:35 +02:00
Abhijeet Kasurde
795125fec4 xml: Add an example for absent (#2644)
Element node can be deleted based upon the attribute
value.

Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>
2021-05-27 19:04:52 +02:00
christophemorio
285639a4f9 Terraform overwrite init (#2573)
* feat: implement overwrite_init option

* chore: changelog
2021-05-27 19:03:39 +02:00
Felix Fontein
7cd96d963e meta/runtime.yml and __init__.py cleanup (#2632)
* Remove superfluous __init__.py files.

* Reformat and sort meta/runtime.yml.

* The ovirt modules have been removed.

* Add changelog entry.
2021-05-27 18:49:26 +02:00
Andrew Klychkov
dc793ea32b hana_query module: add a maintainer (#2647) 2021-05-27 18:46:38 +02:00
rainerleber
b79969da68 Add module hana_query to make SAP HANA administration easier. (#2623)
* new

* move link

* Apply suggestions from code review

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

* add more interesting return value in test

* remove unused objects

* removed unneeded function

* extend test output

* Update tests/unit/plugins/modules/database/saphana/test_hana_query.py

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

Co-authored-by: Rainer Leber <rainer.leber@sva.de>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-27 18:46:12 +02:00
quidame
909e9fe950 fix a regression in initialization_from_null_state() (iptables-nft > 1.8.2) (#2604) 2021-05-27 08:47:16 +02:00
Felix Fontein
b45298bc43 Temporarily disable iptables_state tests. (#2641) 2021-05-27 08:23:35 +02:00
sgalea87
4aa50962cb influxdb_user: Fix bug introduced by PR 2499 (#2614)
* Update influxdb_user.py

Fixed function name

* Create 2614-influxdb_user-fix-issue-introduced-in-PR#2499

Added changelog

* Rename 2614-influxdb_user-fix-issue-introduced-in-PR#2499 to 2614-influxdb_user-fix-issue-introduced-in-PR#2499.yml

Fixed extension

* Update changelogs/fragments/2614-influxdb_user-fix-issue-introduced-in-PR#2499.yml

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

Co-authored-by: Amin Vakil <info@aminvakil.com>
2021-05-27 08:01:28 +02:00
Sylvia van Os
26757edfb2 Add one-liner lookup example (#2615)
* Add one-liner lookup example

* Remove trailing whitespace

* Update plugins/lookup/tss.py

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

* Update plugins/lookup/tss.py

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

Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Amin Vakil <info@aminvakil.com>
2021-05-27 07:57:06 +02:00
Felix Fontein
0b4a2bea01 Use become test framework for sudosu tests. (#2629) 2021-05-26 10:34:35 +02:00
Amin Vakil
d0f8eac7fd Add CONTRIBUTING.md (#2602)
* Initial file shamelessly copied from community.mysql

* Add some notes on pull requests

* Add CONTRIBUTING.md link to README.md

* Add quick-start development guide link

* Apply felixfontein's suggestions

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

* add note about rebasing and merge commits

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

* add note about easyfix and waiting_on_contributor tags

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-26 09:42:21 +02:00
Alexei Znamensky
4764a5deba redis cache - better parsing of connection uri (#2579)
* better parsing of connection uri

* added changelog fragment

* fixed tests for ansible 2.9

* Update tests/unit/plugins/cache/test_redis.py

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

* Update tests/unit/plugins/cache/test_redis.py

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

* Adjustments from PR

* Update test_redis.py

* Update test_redis.py

* Update plugins/cache/redis.py

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

* Update plugins/cache/redis.py

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

* Update tests/unit/plugins/cache/test_redis.py

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-26 07:07:09 +02:00
Alexei Znamensky
aa74cf4d61 ini_file - added note in documentation for utf-8 bom (#2599)
* added note in documentation for utf-8 bom

* Update plugins/modules/files/ini_file.py

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-26 07:06:23 +02:00
Alexander Moiseenko
6df3685d42 jenkins_plugin: HTTP Error 405: Method Not Allowed on disable/enable plugin #2510 (#2511)
* define POST method for pluginManager api requests

Jenkins makeEnable/makeDisable api requests requires to use POST method

* add changelog fragment

* fix my yoda lang thx to aminvakil

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

* update changelog fragment

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

Co-authored-by: Amin Vakil <info@aminvakil.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-26 07:00:53 +02:00
Brian Coca
d871399220 json_query, no more 'unknown type' errors (#2607)
Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>
2021-05-25 13:04:19 +02:00
DasSkelett
63012eef82 Use str() to get exception message (#2590) 2021-05-25 12:58:20 +02:00
Tong He
593d622438 rhsm_release: Fix the issue that rhsm_release module considers 8, 7Client and 7Workstation as invalid releases (#2571)
* rhsm_release: Fix the issue that rhsm_release module considers 8, 7Client and 7Workstation as invalid releases.

* Fix the unit test error: The new release_matcher could pass a wider range of patterns but that would not cause extra issue to the whole module.

* Submit the changelog fragment.

* Update changelogs/fragments/2571-rhsm_release-fix-release_matcher.yaml

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

Co-authored-by: Amin Vakil <info@aminvakil.com>
2021-05-24 21:59:52 +02:00
Alexei Znamensky
cc293f90a2 ini_file - opening file as utf-8-sig (#2578)
* opening file as utf-8-sig

* added changelog fragment

* using io.open()

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

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-22 22:20:37 +02:00
Alexei Znamensky
d7e55db99b Massive adjustment in integration tests for changed and failed (#2577)
* Replaced ".changed ==" with "is [not] changed". Same for failed

* Mr Quote refused to go
2021-05-22 13:51:36 +02:00
abikouo
3100c32a00 ovir4 inventory script (#2461)
* update configparser

* changelog

* handle multiple python version

* Update changelogs/fragments/2461-ovirt4-fix-configparser.yml

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

* Update ovirt4.py

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-22 13:34:19 +02:00
absynth76
8f083d5d85 java_cert - fix incorrect certificate alias on pkcs12 import (#2560)
* fix wrong certificate alias used when importing pkcs12, modify error output, stdout is more relevant than stderr

* add changelog fragment

* fix changelog fragment
2021-05-22 13:33:27 +02:00
Abhijeet Kasurde
852e240525 Add missing author name (#2570)
Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>
2021-05-21 18:45:22 +02:00
momcilo78
7a169af053 Add comment_visibility parameter for comment operation for jira module (#2556)
* Add comment_visibility parameter for comment operation for jira module

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

* Update plugins/modules/web_infrastructure/jira.py

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

* Update plugins/modules/web_infrastructure/jira.py

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

* addressed pep8 E711

* Added missing parameter.

* params is not in use anymore.

* It appears other modules are using options, where in documentation they use suboptions. Inconsistancy?

* adjusted indentation

* tweaked suboptions, fixed documentation

* Added fragment

* Update changelogs/fragments/2556-add-comment_visibility-parameter-for-comment-operation-of-jira-module.yml

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

* Update plugins/modules/web_infrastructure/jira.py

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

Co-authored-by: felixfontein <felix@fontein.de>
2021-05-20 22:06:00 +02:00
Alexei Znamensky
1403f5edcc ModuleHelper: CmdMixin custom function for processing cmd results (#2564)
* MH: custom function for processing cmd results

* added changelog fragment

* removed case of process_output being a str
2021-05-20 19:43:16 +02:00
Alexei Znamensky
452a185a23 removed supporting code for testing module "nuage" - no longer exists here (#2559) 2021-05-19 19:38:11 +02:00
Andre Lehmann
c4624d3ad8 pacman: add 'executable' option to use an alternative pacman binary (#2524)
* Add 'bin' option to use an alternative pacman binary

* Add changelog entry

* Incorporate recommendations

* Update plugins/modules/packaging/os/pacman.py

* Apply suggestions from code review

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-18 12:59:11 +02:00
Felix Fontein
31687a524e Next planned release is 3.2.0. 2021-05-18 11:57:59 +02:00
quidame
2c1ab2d384 iptables_state: fix per-table initialization command (#2525)
* refactor initialize_from_null_state()

* Use a more neutral command (iptables -L) to load per-table needed modules.

* fix 'FutureWarning: Possible nested set at position ...' (re.sub)

* fix pylints (module + action plugin)

* unsubscriptable-object
* superfluous-parens
* consider-using-in
* unused-variable
* unused-import
* no-else-break

* cleanup other internal module_args if they exist

* add changelog fragment

* Apply suggestions from code review (changelog fragment)

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

* Remove useless plugin type in changelog fragment

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

Co-authored-by: Felix Fontein <felix@fontein.de>
Co-authored-by: Amin Vakil <info@aminvakil.com>
2021-05-18 11:51:37 +02:00
quidame
f6db0745fc filesystem: revamp module (#2472)
* revamp filesystem module to prepare next steps

* pass all commands to module.run_command() as lists
* refactor grow() and grow_cmd() to not need to override them so much
* refactor all existing get_fs_size() overrides to raise a ValueError if
  not able to parse command output and return an integer.
* override MKFS_FORCE_FLAGS the same way for all fstypes that require it
* improve documentation of limitations of the module regarding FreeBSD
* fix indentation in DOCUMENTATION
* add/update function/method docstrings
* fix pylint hints

filesystem: refactor integration tests

* Include *reiserfs* and *swap* in tests.
* Fix reiserfs related code and tests accordingly.
* Replace "other fs" (unhandled by this module), from *swap* to *minix*
  (both mkswap and mkfs.minix being provided by util-linux).
* Replace *dd* commands by *filesize* dedicated module.
* Use FQCNs and name the tasks.
* Update main tests conditionals.

* add a changelog fragment

* Apply suggestions from code review

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

* declare variables as lists when lists are needed

* fix construction without useless conversion

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-18 06:46:45 +02:00
Alexei Znamensky
d24fc92466 ModuleHelper - cmd params now taken from self.vars instead of self.module.params (#2517)
* cmd params now taken from self.vars instead of self.module.params

* added changelog fragment

* Update changelogs/fragments/2517-cmd-params-from-vars.yml

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-17 22:44:00 +02:00
Xabier Napal
b89eb87ad6 influxdb_user: allow creation of first user with auth enabled (#2364) (#2368)
* influxdb_user: allow creation of first user with auth enabled (#2364)

* handle potential exceptions while parsing influxdb client error

* fix changelog

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

* influxdb_user: use generic exceptions to be compatible with python 2.7

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-17 21:00:35 +02:00
Alexei Znamensky
2a376642dd ModuleHelper - better mechanism for customizing "changed" behaviour (#2514)
* better mechanism for customizing "changed" behaviour

* dont drink and code: silly mistake from late at night

* added changelog fragment
2021-05-17 20:28:21 +02:00
quidame
2b1eff2783 java_keystore: pass in secret to keytool via stdin (#2526)
* java_keystore: pass in secret to keytool via stdin

* add changelog fragment
2021-05-17 20:05:24 +02:00
Lauri Tirkkonen
dc0a56141f zfs_delegate_admin: drop choices from permissions (#2540)
instead of whitelisting some subset of known existing permissions, just
allow any string to be used as permissions. this way, any permission
supported by the underlying zfs commands can be used, eg. 'bookmark',
'load-key', 'change-key' and all property permissions, which were
missing from the choices list.
2021-05-17 18:55:00 +02:00
Alexei Znamensky
345d5f2dfa snap - revamp + implementing enabled/disabled states (#2411)
* revamp of snap module

* added changelog fragment

* fixed description

* Update changelogs/fragments/2411-snap-revamp-enabled-disabled-states.yml

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-17 14:03:15 +02:00
Jan Baier
350380ba8c Add option missing to passwordstore lookup (#2500)
Add ability to ignore error on missing pass file to allow processing the
output further via another filters (mainly the default filter) without
updating the pass file itself.

It also contains the option to create the pass file, like the option
create=true does.

Finally, it also allows to issue a warning only, if the pass file is not
found.
2021-05-17 13:50:40 +02:00
Amin Vakil
da7e4e1dc2 yum_versionlock: disable fedora34 integration test (#2536)
* Disable yum_versionlock integration test on Fedora 34

* Remove --assumeyes and add a comment regarding this

* Update update task name
2021-05-17 10:02:20 +02:00
Felix Fontein
2cc848fe1a Use --assumeyes with explicit yum call. (#2533) 2021-05-17 08:11:17 +02:00
Dennis Israelsson
448b8cbcda fix error when cache is disabled (#2518) 2021-05-17 07:35:15 +02:00
sgalea87
ea200c9d8c Update influxdb_user.py Fixed Multiple No Privileges (#2499)
* Update influxdb_user.py

Fixed Multiple No Privileges

* Update influxdb_user.py

Fixed line spaces

* Update influxdb_user.py

Fixed whitespace

* Create 2499-influxdb_user-fix-multiple-no-privileges.yml 

Added changelog
2021-05-17 07:33:40 +02:00
iridian
5b77515308 1085 updating the hcl whitelist to include all supported options (#2495)
* 1085 updating the hcl whitelist to include all supported options

* Update changelogs/fragments/1085-consul-acl-hcl-whitelist-update.yml

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

Co-authored-by: Dillon Gilmore <dgilmor@rei.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-17 07:32:51 +02:00
Alexei Znamensky
c8f402806f Cleanup connections plugins (#2520)
* minor refactors

* minor refactors in plugins/connection/saltstack.py

* minor refactors in plugins/connection/qubes.py

* minor refactor in plugins/connection/lxc.py

* minor refactors in plugins/connection/chroot.py

* minor refactors in plugins/connection/funcd.py

* minor refactors in plugins/connection/iocage.py

* minor refactors in plugins/connection/jail.py

* added changelog fragment
2021-05-16 13:24:37 +02:00
Ajpantuso
a385cbb11d java_keystore: New ssl_backend option for cryptography (#2485)
* Adding cryptography as a backend for OpenSSL operations

* Updating unit tests and adding changelog fragment

* Allowing private key password option when using unprotected key

* Incorporating suggestions from initial review

* Centralizing module exit path
2021-05-14 22:31:44 +02:00
Abhijeet Kasurde
5d0a7f40f2 random_pet: Random pet name generator (#2479)
A lookup plugin to generate random pet names based
upon criteria.

Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>
2021-05-14 10:55:27 +02:00
Amin Vakil
e2dfd42dd4 proxmox_nic: set mtu on interface even if it's not virtio (#2505)
* Set mtu on interface whatsoever

* add changelog fragment

* Revert "add changelog fragment"

This reverts commit 5f2f1e7feb.
2021-05-14 10:33:30 +02:00
Amin Vakil
054eb90ae5 gitlab_user: add expires_at option (#2450)
* gitlab_user: add expires_at option

* Add changelog

* Add integration test

* Add expires_at to addSshKeyToUser function

* password is required if state is set to present

* Check expires_at will not be added to a present ssh key

* add documentation about present ssh key

* add expires_at to unit tests

* Improve documentation

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

* Only pass expires_at to api when it is not None

* Emphasize on SSH public key

* Apply felixfontein suggestion

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-14 10:00:59 +02:00
Felix Fontein
ee9770cff7 Deprecate nios content (#2458)
* Deprecate nios content.

* Make 2.9's ansible-test happy.

* Add module_utils deprecation.
2021-05-13 21:50:40 +02:00
Felix Fontein
384655e15c Add groupby_as_dict filter (#2323)
* Add groupby_as_dict filter.

* Test all error cases.
2021-05-13 21:49:57 +02:00
Kogelvis
23dda56913 Add proxmox_nic module (#2449)
* Add proxmox_nic module

Add proxmox_nic module to manage NIC's on Qemu(KVM) VM's in a Proxmox VE
cluster.
Update proxmox integration tests and add tests for proxmox_nic module.

This partially solves https://github.com/ansible-collections/community.general/issues/1964#issuecomment-790499397
and allows for adding/updating/deleting network interface cards after
creating/cloning a VM.

The proxmox_nic module will keep MAC-addresses the same when updating a
NIC. It only changes when explicitly setting a MAC-address.

* Apply suggestions from code review

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

* Add check_mode and implement review comments

- check_mode added
- some documentation updates
- when MTU is set, check if the model is virtio, else fail
- trunks can now be provided as list of ints instead of vlanid[;vlanid...]

* Make returns on update_nic and delete_nic more readable

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

* Increase readability on update_nic and delete_nic

* Implement check in get_vmid

- get_vmid will now fail when multiple vmid's are returned as proxmox
  doesn't guarantee uniqueness
- remove an unused import
- fix a typo in an error message

* Add some error checking to get_vmid

- get_vmid will now return the error message when proxmoxer fails
- get_vmid will return the vmid directly instead of a list of one
- Some minor documentation updates

* Warn instead of fail when setting mtu on unsupported nic

- When setting the MTU on an unsupported NIC model (virtio is the only
  supported model) this module will now print a warning instead of
  failing.
- Some minor documentation updates.

* Take advantage of proxmox_auth_argument_spec

Make use of proxmox_auth_argument_spec from plugins/module_utils/proxmox.py
This provides some extra environment fallbacks.

* Add blank line to conform with pep8

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-13 21:48:49 +02:00
Alexei Znamensky
265d034e31 linode - docs/validation changes + minor refactorings (#2410)
* multiple changes:

- documentation fixes
- minor refactorings

* added param deprecation note to the documentation

* added changelog fragment

* Update changelogs/fragments/2410-linode-improvements.yml

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

* Update changelogs/fragments/2410-linode-improvements.yml

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

* Update plugins/modules/cloud/linode/linode.py

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-12 17:37:31 +02:00
Xabier Napal
83a0c32269 influxdb_retention_policy - add state argument to module spec (#2383) (#2385)
* influxdb_retention_policy: add state option to module argument spec

* influxdb_retention_policy: simplify duration parsing logic (suggested in #2284)

* add changelog

* fix documentation and changelog

* add constants for duration and sgduration validations

* restyle ansible module spec

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

* improve changelog

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

* set changed result in check mode for state absent

* remove required flag in optional module arguments

* influxdb_retention_policy: improve examples readability

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-12 17:33:27 +02:00
spike77453
b9fa9116c1 nmcli: Remove dead code, 'options' never contains keys from 'param_alias' (#2417)
* nmcli: Remove dead code, 'options' never contains keys from 'param_alias'

* Update changelogs/fragments/2417-nmcli_remove_dead_code.yml

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-11 19:35:30 +02:00
CWollinger
0912e8cc7a discord.py: Add new module for discord notifications (#2398)
* first push: add discord module and test for notifications

* fix the yaml docs and edit the result output

* add link

* fix link

* fix docs and remove required=False in argument spec

* add elements specd and more info about embeds

* called str...

* elements for embeds oc.

* fix typo's in description and set checkmode to false

* edit docs and module return

* support checkmode with get method

* fix unit test

* handle exception and add new example for embeds

* quote line

* fix typos

* fix yaml
2021-05-11 19:31:46 +02:00
Alexei Znamensky
d22dd5056e module_helper.py Breakdown (#2393)
* break down of module_helper into smaller pieces, keeping compatibility

* removed abc.ABC (py3 only) from code + fixed reference to vars.py

* multiple changes:

- mh.base - moved more functionalities to ModuleHelperBase
- mh.mixins.(cmd, state) - CmdMixin no longer inherits from ModuleHelperBase
- mh.mixins.deps - DependencyMixin now overrides run() method to test dependency
- mh.mixins.vars - created class VarsMixin
- mh.module_helper - moved functions to base class, added VarsMixin
- module_helper - importing AnsibleModule as well, for backward compatibility in test

* removed unnecessary __all__

* make pylint happy

* PR adjustments + bot config + changelog frag

* Update plugins/module_utils/mh/module_helper.py

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

* Update plugins/module_utils/mh/module_helper.py

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

Co-authored-by: Felix Fontein <felix@fontein.de>
2021-05-11 19:31:10 +02:00
TrevorSquillario
9d46ccf1b2 modified redfish_config and idrac_redfish_config to skip incorrect attributes (#2334)
* modified redfish_config and idrac_redfish_config to skip incorrect attributes

Signed-off-by: Trevor Squillario Trevor_Squillario@Dell.com

* modified redfish_utils.py and idrac_redfish_config.py to return empty warning message

* modified redfish_config.py and idrac_redfish_config.py to use module.warn()

* updated changelog fragment for pr 2334
2021-05-11 19:30:09 +02:00
Felix Fontein
eea4f45965 Add dependent lookup plugin (#2164)
* Add dependent lookup plugin.

* Use correct YAML booleans.

* Began complete rewrite.

* Only match start of error msg.

* Improve tests.

* Work around old Jinja2 versions.

* Fix metadata.

* Fix filter name.
2021-05-11 19:27:05 +02:00
Felix Fontein
624eb7171e Run unit tests also with Python 3.10. (#2486)
ci_complete
2021-05-11 07:52:57 +02:00
sam-lunt
8e7aff00b5 Avoid incorrectly marking zfs tasks as changed (#2454)
* 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>
2021-05-10 17:55:19 +02:00
Felix Fontein
2e58dfe52a Clarify Windows (non-)support. (#2476) 2021-05-10 13:45:10 +01:00
vbarba
4cdff8654a fix stackpath_compute validate_config (#2448)
* 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>
2021-05-09 22:25:00 +02:00
Mike Russell
7386326258 Small Documentation Example Of Cask Leveraging (#2462)
* 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
2021-05-08 11:58:55 +02:00
Felix Fontein
9906b9dbc7 Remove vendored ipaddress module. (#2441) 2021-05-05 12:31:01 +02:00
Felix Fontein
188a4eeb0c Add more plugin authors to BOTMETA. (#2451) 2021-05-05 07:32:53 +02:00
Jan Orel
aaa561163b OpenNebula one_vm.py: Fix missing keys (#2435)
* OpenNebula one_vm.py: Fix missing keys

* fixup OpenNebula one_vm.py: Fix missing keys
2021-05-04 12:21:55 +02:00
Felix Fontein
1f41e66f09 Remove shippable config. (#2440) 2021-05-03 22:24:33 +02:00
zigaSRC
06bdabcad9 lvol - bug fix - Convert units to lowercase when using LVS or VGS command (#2369)
* Added lower call for units when checking lvs/vgs size

* Changelog

* Size roudning correction

* Rounding

* Changelog

* Remove whitespace
2021-05-03 21:25:52 +02:00
David Lundgren
7007c68ab7 Clean up test entries from sysrc tests (#2330)
* 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
2021-05-03 21:05:07 +02:00
Alexei Znamensky
5064aa8ec6 linode_v4 - fixed error message (#2430)
* fixed error message

* added changelog fragment
2021-05-03 13:27:16 +02:00
Felix Fontein
6a72c3b338 Make plugins pass validation. (#2414) 2021-05-03 13:22:11 +02:00
Daniel-Sanchez-Fabregas
4b0d2dcfe0 📝 Document nested node addition with "_" in xml module (#2371)
* 📝 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>
2021-05-03 07:42:58 +02:00
spike77453
7359b1fbe5 nmcli: Compare MAC addresses case insensitively (#2416)
* 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>
2021-05-03 07:28:53 +02:00
spike77453
b5f8ae4320 nmcli: Add 'slave-type bridge' to nmcli command if type is bridge-slave (#2409) 2021-05-03 07:27:56 +02:00
Amin Vakil
26aba8e766 puppet - replace stdout with console in logdest option (#2407)
* 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>
2021-05-03 07:26:47 +02:00
Daniel Werner
cd957fae4c Fix #2373 - TypeError: a bytes-like object is required, not 'str' (#2375)
* 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>
2021-05-03 07:25:08 +02:00
Andrew Klychkov
c0221b75af BOTMETA.yml: terraform - add a new maintainer (#2290) 2021-05-02 11:28:27 +02:00
Felix Fontein
4e90ee752e Add ansible-test config file. (#2404) 2021-05-01 22:21:17 +02:00
George Angelopoulos
eb455c69a2 composer: --no-interaction when discovering available options (#2348)
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
2021-05-01 18:23:14 +02:00
Xabier Napal
26c3bd25f6 influxdb_retention_policy: fix duration parsing to support INF values (#2396)
* influxdb_retention_policy: fix duration parsing to support INF values

* add changelog
2021-05-01 14:19:05 +02:00
Felix Fontein
276880aac1 Remove resmo as composer maintainer. (#2392) 2021-05-01 09:51:35 +02:00
Amin Vakil
ae21af8820 Add Fedora 34 to CI (#2384)
* 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>
2021-04-30 23:49:33 +02:00
Felix Fontein
5fbe946c3a Spread nightly runs out. (#2387) 2021-04-30 21:13:46 +01:00
Felix Fontein
b3f436aa63 Use Ansible's codecov uploader. (#2377) 2021-04-30 04:28:43 +02:00
Felix Fontein
77d4bc2942 No longer required for devel's ansible-test. (#2365)
ci_complete
2021-04-27 22:13:40 +02:00
Alexei Znamensky
48ef05def3 spotinst_aws_elastigroup - fixed elements for many lists (#2355)
* fixed elements for many lists

* added changelog fragment

* Removed verbose types in description - still missing formatting and properly documenting dicts
2021-04-27 13:18:29 +02:00
Andrew Klychkov
9d13acd68e BOTMETA.yml: team_suse - add a maintainer (#2354) 2021-04-27 13:16:24 +02:00
Alan Rominger
2ad004b97b Make inventory scripts executable (#2337)
* 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>
2021-04-26 21:24:26 +02:00
Felix Fontein
cd116120ad Run CI for old branches only once per week. 2021-04-26 18:43:14 +02:00
Felix Fontein
9931cdc1e7 stable-3 has been created, prepare for next 3.x.y release. 2021-04-26 18:33:30 +02:00
658 changed files with 19333 additions and 30952 deletions

View File

@@ -24,14 +24,15 @@ schedules:
always: true
branches:
include:
- stable-2
- stable-3
- stable-4
- cron: 0 11 * * 0
displayName: Weekly (old stable branches)
always: true
branches:
include:
- stable-1
- stable-2
variables:
- name: checkoutPath
@@ -68,6 +69,19 @@ stages:
- test: 3
- test: 4
- test: extra
- 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
displayName: Sanity 2.11
dependsOn: []
@@ -117,7 +131,6 @@ stages:
nameFormat: Python {0}
testFormat: devel/units/{0}/1
targets:
- test: 2.6
- test: 2.7
- test: 3.5
- test: 3.6
@@ -125,6 +138,22 @@ stages:
- test: 3.8
- test: 3.9
- test: '3.10'
- 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: 2.7
- test: 3.5
- test: 3.6
- test: 3.7
- test: 3.8
- test: '3.10'
- stage: Units_2_11
displayName: Units 2.11
dependsOn: []
@@ -150,13 +179,8 @@ stages:
nameFormat: Python {0}
testFormat: 2.10/units/{0}/1
targets:
- test: 2.6
- test: 2.7
- test: 3.5
- test: 3.6
- test: 3.7
- test: 3.8
- test: 3.9
- stage: Units_2_9
displayName: Units 2.9
dependsOn: []
@@ -186,8 +210,8 @@ stages:
test: macos/11.1
- name: RHEL 7.9
test: rhel/7.9
- name: RHEL 8.4
test: rhel/8.4
- name: RHEL 8.5
test: rhel/8.5
- name: FreeBSD 12.2
test: freebsd/12.2
- name: FreeBSD 13.0
@@ -196,6 +220,23 @@ stages:
- 1
- 2
- 3
- stage: Remote_2_12
displayName: Remote 2.12
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.12/{0}
targets:
- name: macOS 11.1
test: macos/11.1
- name: RHEL 8.4
test: rhel/8.4
- name: FreeBSD 13.0
test: freebsd/13.0
groups:
- 1
- 2
- stage: Remote_2_11
displayName: Remote 2.11
dependsOn: []
@@ -204,8 +245,6 @@ stages:
parameters:
testFormat: 2.11/{0}
targets:
- name: macOS 11.1
test: macos/11.1
- name: RHEL 7.9
test: rhel/7.9
- name: RHEL 8.3
@@ -227,14 +266,6 @@ stages:
test: osx/10.11
- name: 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:
- 1
- 2
@@ -248,6 +279,8 @@ stages:
targets:
- name: RHEL 8.2
test: rhel/8.2
- name: RHEL 7.8
test: rhel/7.8
- name: FreeBSD 12.0
test: freebsd/12.0
groups:
@@ -263,16 +296,12 @@ stages:
parameters:
testFormat: devel/linux/{0}
targets:
- name: CentOS 6
test: centos6
- name: CentOS 7
test: centos7
- name: CentOS 8
test: centos8
- name: Fedora 33
test: fedora33
- name: Fedora 34
test: fedora34
- name: Fedora 35
test: fedora35
- name: openSUSE 15 py2
test: opensuse15py2
- name: openSUSE 15 py3
@@ -285,6 +314,28 @@ stages:
- 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: CentOS 8
test: centos8
- name: Fedora 34
test: fedora34
- name: openSUSE 15 py3
test: opensuse15
- name: Ubuntu 20.04
test: ubuntu2004
groups:
- 1
- 2
- 3
- stage: Docker_2_11
displayName: Docker 2.11
dependsOn: []
@@ -293,14 +344,12 @@ stages:
parameters:
testFormat: 2.11/linux/{0}
targets:
- name: CentOS 8
test: centos8
- name: CentOS 7
test: centos7
- name: Fedora 33
test: fedora33
- name: openSUSE 15 py3
test: opensuse15
- name: Ubuntu 20.04
test: ubuntu2004
- name: openSUSE 15 py2
test: opensuse15py2
groups:
- 2
- 3
@@ -312,12 +361,8 @@ stages:
parameters:
testFormat: 2.10/linux/{0}
targets:
- name: CentOS 8
test: centos8
- name: Fedora 32
test: fedora32
- name: openSUSE 15 py3
test: opensuse15
- name: Ubuntu 16.04
test: ubuntu1604
groups:
@@ -331,8 +376,6 @@ stages:
parameters:
testFormat: 2.9/linux/{0}
targets:
- name: CentOS 8
test: centos8
- name: Fedora 31
test: fedora31
- name: openSUSE 15 py3
@@ -350,6 +393,17 @@ stages:
parameters:
nameFormat: Python {0}
testFormat: devel/cloud/{0}/1
targets:
- test: 2.7
- 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:
- test: 3.8
- stage: Cloud_2_11
@@ -361,7 +415,6 @@ stages:
nameFormat: Python {0}
testFormat: 2.11/cloud/{0}/1
targets:
- test: 2.7
- test: 3.6
- stage: Cloud_2_10
displayName: Cloud 2.10
@@ -372,7 +425,7 @@ stages:
nameFormat: Python {0}
testFormat: 2.10/cloud/{0}/1
targets:
- test: 3.6
- test: 3.5
- stage: Cloud_2_9
displayName: Cloud 2.9
dependsOn: []
@@ -382,7 +435,7 @@ stages:
nameFormat: Python {0}
testFormat: 2.9/cloud/{0}/1
targets:
- test: 3.6
- test: 2.7
- stage: Summary
condition: succeededOrFailed()
dependsOn:
@@ -390,21 +443,26 @@ stages:
- Sanity_2_9
- Sanity_2_10
- Sanity_2_11
- Sanity_2_12
- Units_devel
- Units_2_9
- Units_2_10
- Units_2_11
- Units_2_12
- Remote_devel
- Remote_2_9
- Remote_2_10
- Remote_2_11
- Remote_2_12
- Docker_devel
- Docker_2_9
- Docker_2_10
- Docker_2_11
- Docker_2_12
- Cloud_devel
- Cloud_2_9
- Cloud_2_10
- Cloud_2_11
- Cloud_2_12
jobs:
- template: templates/coverage.yml

View File

@@ -11,7 +11,7 @@ mkdir "${agent_temp_directory}/coverage/"
options=(--venv --venv-system-site-packages --color -v)
ansible-test coverage combine --export "${agent_temp_directory}/coverage/" "${options[@]}"
ansible-test coverage combine --group-by command --export "${agent_temp_directory}/coverage/" "${options[@]}"
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.

View File

@@ -0,0 +1,101 @@
#!/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

@@ -1,27 +0,0 @@
#!/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
fi
ansible-test coverage xml --stub --venv --venv-system-site-packages --color -v
ansible-test coverage xml --group-by command --stub --venv --venv-system-site-packages --color -v

View File

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

102
.github/BOTMETA.yml vendored
View File

@@ -1,3 +1,4 @@
notifications: true
automerge: true
files:
plugins/:
@@ -48,6 +49,9 @@ files:
maintainers: dagwieers
$callbacks/diy.py:
maintainers: theque5t
$callbacks/elastic.py:
maintainers: v1v
keywords: apm observability
$callbacks/hipchat.py: {}
$callbacks/jabber.py: {}
$callbacks/loganalytics.py:
@@ -114,6 +118,8 @@ files:
$doc_fragments/xenserver.py:
maintainers: bvitnik
labels: xenserver
$filters/counter.py:
maintainers: keilr
$filters/dict.py:
maintainers: felixfontein
$filters/dict_kv.py:
@@ -152,11 +158,17 @@ files:
maintainers: conloos
$inventories/nmap.py: {}
$inventories/online.py:
maintainers: sieben
maintainers: remyleone
$inventories/opennebula.py:
maintainers: feldsam
labels: cloud opennebula
keywords: opennebula dynamic inventory script
$inventories/proxmox.py:
maintainers: $team_virt ilijamt
$inventories/xen_orchestra.py:
maintainers: ddelnano shinuza
$inventories/icinga2.py:
maintainers: bongoeadgc6
maintainers: BongoEADGC6
$inventories/scaleway.py:
maintainers: $team_scaleway
labels: cloud scaleway
@@ -167,6 +179,8 @@ files:
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:
@@ -197,9 +211,6 @@ files:
$lookups/manifold.py:
maintainers: galanoff
labels: manifold
$lookups/nios:
maintainers: $team_networking sganesh-infoblox
labels: infoblox networking
$lookups/onepass:
maintainers: samdoran
labels: onepassword
@@ -212,8 +223,12 @@ files:
maintainers: Akasurde
$lookups/random_string.py:
maintainers: Akasurde
$lookups/random_words.py:
maintainers: konstruktoid
$lookups/redis.py:
maintainers: $team_ansible_core jpmens
$lookups/revbitspss.py:
maintainers: RevBits
$lookups/shelvefile.py: {}
$lookups/tss.py:
maintainers: amigus endlesstrax
@@ -245,9 +260,6 @@ files:
$module_utils/module_helper.py:
maintainers: russoz
labels: module_helper
$module_utils/net_tools/nios/api.py:
maintainers: $team_networking sganesh-infoblox
labels: infoblox networking
$module_utils/oracle/oci_utils.py:
maintainers: $team_oracle
labels: cloud
@@ -312,6 +324,10 @@ files:
$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:
maintainers: UnderGreen
ignore: skvidal
@@ -331,7 +347,7 @@ files:
$modules/cloud/oneandone/:
maintainers: aajdinov edevenport
$modules/cloud/online/:
maintainers: sieben
maintainers: remyleone
$modules/cloud/opennebula/:
maintainers: $team_opennebula
$modules/cloud/opennebula/one_host.py:
@@ -401,11 +417,11 @@ files:
$modules/cloud/scaleway/scaleway_ip_info.py:
maintainers: Spredzy
$modules/cloud/scaleway/scaleway_organization_info.py:
maintainers: sieben Spredzy
maintainers: Spredzy
$modules/cloud/scaleway/scaleway_security_group.py:
maintainers: DenBeke
$modules/cloud/scaleway/scaleway_security_group_info.py:
maintainers: sieben Spredzy
maintainers: Spredzy
$modules/cloud/scaleway/scaleway_security_group_rule.py:
maintainers: DenBeke
$modules/cloud/scaleway/scaleway_server_info.py:
@@ -469,11 +485,16 @@ files:
maintainers: paginabianca
$modules/database/misc/redis_data.py:
maintainers: paginabianca
$modules/database/misc/redis_data_incr.py:
maintainers: paginabianca
$modules/database/misc/riak.py:
maintainers: drewkerrigan jsmartin
$modules/database/mssql/mssql_db.py:
maintainers: vedit Jmainguy kenichi-ogawa-1988
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/:
@@ -519,6 +540,8 @@ files:
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:
maintainers: kris2kris
$modules/identity/keycloak/keycloak_role.py:
@@ -604,6 +627,8 @@ files:
labels: cloudflare_dns
$modules/net_tools/dnsimple.py:
maintainers: drcapulet
$modules/net_tools/dnsimple_info.py:
maintainers: edhilgendorf
$modules/net_tools/dnsmadeeasy.py:
maintainers: briceburg
$modules/net_tools/gandi_livedns.py:
@@ -639,31 +664,6 @@ files:
maintainers: amasolov nerzhul
$modules/net_tools/pritunl/:
maintainers: Lowess
$modules/net_tools/nios/:
maintainers: $team_networking
labels: infoblox networking
$modules/net_tools/nios/nios_a_record.py:
maintainers: brampling
$modules/net_tools/nios/nios_aaaa_record.py:
maintainers: brampling
$modules/net_tools/nios/nios_cname_record.py:
maintainers: brampling
$modules/net_tools/nios/nios_fixed_address.py:
maintainers: sjaiswal
$modules/net_tools/nios/nios_member.py:
maintainers: krisvasudevan
$modules/net_tools/nios/nios_mx_record.py:
maintainers: brampling
$modules/net_tools/nios/nios_naptr_record.py:
maintainers: brampling
$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:
maintainers: alcamie101
$modules/net_tools/snmp_facts.py:
@@ -730,6 +730,8 @@ files:
maintainers: mwarkentin
$modules/packaging/language/bundler.py:
maintainers: thoiberg
$modules/packaging/language/cargo.py:
maintainers: radek-sprta
$modules/packaging/language/composer.py:
maintainers: dmtrs
ignore: resmo
@@ -753,6 +755,8 @@ files:
ignore: jle64
$modules/packaging/language/pip_package_info.py:
maintainers: bcoca matburt maxamillion
$modules/packaging/language/pipx.py:
maintainers: russoz
$modules/packaging/language/yarn.py:
maintainers: chrishoffman verkaufer
$modules/packaging/os/apk.py:
@@ -765,6 +769,8 @@ files:
maintainers: evgkrsk
$modules/packaging/os/copr.py:
maintainers: schlupov
$modules/packaging/os/dnf_versionlock.py:
maintainers: moreda
$modules/packaging/os/flatpak.py:
maintainers: $team_flatpak
$modules/packaging/os/flatpak_remote.py:
@@ -861,6 +867,9 @@ files:
$modules/packaging/os/snap.py:
maintainers: angristan vcarceler
labels: snap
$modules/packaging/os/snap_alias.py:
maintainers: russoz
labels: snap
$modules/packaging/os/sorcery.py:
maintainers: vaygr
$modules/packaging/os/svr4pkg.py:
@@ -904,6 +913,10 @@ files:
$modules/remote_management/manageiq/:
labels: 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:
maintainers: evertmulder
$modules/remote_management/manageiq/manageiq_tenant.py:
@@ -954,6 +967,8 @@ files:
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:
maintainers: yeukhon
$modules/storage/emc/emc_vnx_sg_member.py:
@@ -1089,6 +1104,8 @@ files:
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:
maintainers: bcoca
$modules/system/syspatch.py:
@@ -1153,6 +1170,10 @@ files:
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/:
maintainers: $team_e_spirit
keywords: sophos utm
@@ -1174,6 +1195,8 @@ files:
maintainers: inetfuture mattupstate
$modules/web_infrastructure/taiga_issue.py:
maintainers: lekum
$tests/a_module.py:
maintainers: felixfontein
#########################
tests/:
labels: tests
@@ -1200,6 +1223,7 @@ macros:
module_utils: plugins/module_utils
modules: plugins/modules
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_bsd: JoergFiedler MacLemon bcoca dch jasperla mekanix opoplawski overhacked tuxillo
@@ -1207,7 +1231,7 @@ macros:
team_cyberark_conjur: jvanderhoof ryanprior
team_e_spirit: MatrixCrawler getjack
team_flatpak: JayKayy oolongbrothers
team_gitlab: Lunik Shaps dj-wasabi marwatk waheedi zanssa scodeman metanovii
team_gitlab: Lunik Shaps dj-wasabi marwatk waheedi zanssa scodeman metanovii sh0shin
team_hpux: bcoca davx8342
team_huawei: QijunPan TommyLike edisonxiang freesky-edward hwDCN niuzhenguo xuxiaowei0512 yanzhangi zengchen1024 zhongjun2
team_ipa: Akasurde Nosmoht fxfitz justchris1
@@ -1220,9 +1244,9 @@ macros:
team_opennebula: ilicmilan meerkampdvv rsmontero xorel nilsding
team_oracle: manojmeda mross22 nalsaber
team_purestorage: bannaych dnix101 genegr lionmax opslounge raekins sdodsley sile16
team_redfish: mraineri tomasg2012 xmadsen renxulei
team_redfish: mraineri tomasg2012 xmadsen renxulei rajeevkallur bhavya06
team_rhn: FlossWare alikins barnabycourt vritant
team_scaleway: QuentinBrosse abarbare jerome-quere kindermoumoute remyleone sieben
team_scaleway: remyleone abarbare
team_solaris: bcoca fishman jasperla jpdasma mator scathatheworm troy2914 xen0l
team_suse: commel dcermak evrardjp lrupp toabctl AnderEnder alxgu andytom sealor
team_virt: joshainglis karmab tleguern Thulium-Drake Ajpantuso

View File

@@ -62,6 +62,20 @@ body:
validations:
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
attributes:
label: Configuration

View File

@@ -62,6 +62,20 @@ body:
validations:
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
attributes:
label: Configuration

View File

@@ -21,7 +21,7 @@ body:
placeholder: >-
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
every other user of ansible-core because of Z.
every other user of community.general because of Z.
validations:
required: true

6
.github/dependabot.yml vendored Normal file
View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -26,6 +26,7 @@ Also, consider taking up a valuable, reviewed, but abandoned pull request which
* 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 respository 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).
@@ -42,7 +43,12 @@ Creating new modules and plugins requires a bit more work than other Pull Reques
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. When creating a new module or plugin, please make sure that you follow various guidelines:
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
@@ -52,7 +58,7 @@ Creating new modules and plugins requires a bit more work than other Pull Reques
- 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.
3. For modules and action plugins, make sure to create your module/plugin in the correct subdirectory, and create a symbolic link
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.)
@@ -60,7 +66,7 @@ Creating new modules and plugins requires a bit more work than other Pull Reques
(`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/`.
4. Make sure to add a BOTMETA entry for your new module/plugin in `.github/BOTMETA.yml`. Search for other plugins/modules in the
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.

View File

@@ -1,6 +1,6 @@
# Community General Collection
[![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)
[![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)
[![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.
@@ -17,7 +17,7 @@ If you encounter abusive behavior violating the [Ansible Code of Conduct](https:
## Tested with Ansible
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.
Tested with the current Ansible 2.9, ansible-base 2.10, ansible-core 2.11, ansible-core 2.12 releases and the current development version of ansible-core. Ansible versions before 2.9.10 are not supported.
## External requirements
@@ -64,13 +64,13 @@ We are actively accepting new contributors.
All types of contributions are very welcome.
You don't know how to start? Refer to our [contribution guide](https://github.com/ansible-collections/community.general/blob/main/CONTRIBUTING.md)!
You don't know how to start? Refer to our [contribution guide](https://github.com/ansible-collections/community.general/blob/stable-4/CONTRIBUTING.md)!
The current maintainers are listed in the [commit-rights.md](https://github.com/ansible-collections/community.general/blob/main/commit-rights.md#people) file. If you have questions or need help, feel free to mention them in the proposals.
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).
Also for some notes specific to this collection see [our CONTRIBUTING documentation](https://github.com/ansible-collections/community.general/blob/main/CONTRIBUTING.md).
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
@@ -80,7 +80,7 @@ See [here](https://docs.ansible.com/ansible/devel/dev_guide/developing_collectio
To learn how to maintain / become a maintainer of this collection, refer to:
* [Committer guidelines](https://github.com/ansible-collections/community.general/blob/main/commit-rights.md).
* [Committer guidelines](https://github.com/ansible-collections/community.general/blob/stable-4/commit-rights.md).
* [Maintainer guidelines](https://github.com/ansible/community-docs/blob/main/maintaining.rst).
It is necessary for maintainers of this collection to be subscribed to:
@@ -108,7 +108,7 @@ See the [Releasing guidelines](https://github.com/ansible/community-docs/blob/ma
## Release notes
See the [changelog](https://github.com/ansible-collections/community.general/blob/stable-3/CHANGELOG.rst).
See the [changelog](https://github.com/ansible-collections/community.general/blob/stable-4/CHANGELOG.rst).
## Roadmap

File diff suppressed because it is too large Load Diff

View File

@@ -3,3 +3,4 @@ sections:
- title: Guides
toctree:
- filter_guide
- test_guide

View File

@@ -297,6 +297,84 @@ This produces:
.. versionadded: 2.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
Working with times
------------------

View File

@@ -0,0 +1,28 @@
.. _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
name: general
version: 3.7.0
version: 4.3.0
readme: README.md
authors:
- Ansible (https://github.com/ansible)

View File

@@ -12,20 +12,11 @@ plugin_routing:
hashi_vault:
redirect: community.hashi_vault.hashi_vault
nios:
deprecation:
removal_version: 5.0.0
warning_text: The community.general.nios lookup plugin has been deprecated.
Please use infoblox.nios_modules.nios_lookup instead.
redirect: infoblox.nios_modules.nios_lookup
nios_next_ip:
deprecation:
removal_version: 5.0.0
warning_text: The community.general.nios_next_ip lookup plugin has been deprecated.
Please use infoblox.nios_modules.nios_next_ip instead.
redirect: infoblox.nios_modules.nios_next_ip
nios_next_network:
deprecation:
removal_version: 5.0.0
warning_text: The community.general.nios_next_network lookup plugin has been
deprecated. Please use infoblox.nios_modules.nios_next_network instead.
redirect: infoblox.nios_modules.nios_next_network
modules:
ali_instance_facts:
tombstone:
@@ -266,85 +257,37 @@ plugin_routing:
removal_version: 3.0.0
warning_text: Use community.general.nginx_status_info instead.
nios_a_record:
deprecation:
removal_version: 5.0.0
warning_text: The community.general.nios_a_record module has been deprecated.
Please use infoblox.nios_modules.nios_a_record instead.
redirect: infoblox.nios_modules.nios_a_record
nios_aaaa_record:
deprecation:
removal_version: 5.0.0
warning_text: The community.general.nios_aaaa_record module has been deprecated.
Please use infoblox.nios_modules.nios_aaaa_record instead.
redirect: infoblox.nios_modules.nios_aaaa_record
nios_cname_record:
deprecation:
removal_version: 5.0.0
warning_text: The community.general.nios_cname_record module has been deprecated.
Please use infoblox.nios_modules.nios_cname_record instead.
redirect: infoblox.nios_modules.nios_cname_record
nios_dns_view:
deprecation:
removal_version: 5.0.0
warning_text: The community.general.nios_dns_view module has been deprecated.
Please use infoblox.nios_modules.nios_dns_view instead.
redirect: infoblox.nios_modules.nios_dns_view
nios_fixed_address:
deprecation:
removal_version: 5.0.0
warning_text: The community.general.nios_fixed_address module has been deprecated.
Please use infoblox.nios_modules.nios_fixed_address instead.
redirect: infoblox.nios_modules.nios_fixed_address
nios_host_record:
deprecation:
removal_version: 5.0.0
warning_text: The community.general.nios_host_record module has been deprecated.
Please use infoblox.nios_modules.nios_host_record instead.
redirect: infoblox.nios_modules.nios_host_record
nios_member:
deprecation:
removal_version: 5.0.0
warning_text: The community.general.nios_member module has been deprecated.
Please use infoblox.nios_modules.nios_member instead.
redirect: infoblox.nios_modules.nios_member
nios_mx_record:
deprecation:
removal_version: 5.0.0
warning_text: The community.general.nios_mx_record module has been deprecated.
Please use infoblox.nios_modules.nios_mx_record instead.
redirect: infoblox.nios_modules.nios_mx_record
nios_naptr_record:
deprecation:
removal_version: 5.0.0
warning_text: The community.general.nios_naptr_record module has been deprecated.
Please use infoblox.nios_modules.nios_naptr_record instead.
redirect: infoblox.nios_modules.nios_naptr_record
nios_network:
deprecation:
removal_version: 5.0.0
warning_text: The community.general.nios_network module has been deprecated.
Please use infoblox.nios_modules.nios_network instead.
redirect: infoblox.nios_modules.nios_network
nios_network_view:
deprecation:
removal_version: 5.0.0
warning_text: The community.general.nios_network_view module has been deprecated.
Please use infoblox.nios_modules.nios_network_view instead.
redirect: infoblox.nios_modules.nios_network_view
nios_nsgroup:
deprecation:
removal_version: 5.0.0
warning_text: The community.general.nios_nsgroup module has been deprecated.
Please use infoblox.nios_modules.nios_nsgroup instead.
redirect: infoblox.nios_modules.nios_nsgroup
nios_ptr_record:
deprecation:
removal_version: 5.0.0
warning_text: The community.general.nios_ptr_record module has been deprecated.
Please use infoblox.nios_modules.nios_ptr_record instead.
redirect: infoblox.nios_modules.nios_ptr_record
nios_srv_record:
deprecation:
removal_version: 5.0.0
warning_text: The community.general.nios_srv_record module has been deprecated.
Please use infoblox.nios_modules.nios_srv_record instead.
redirect: infoblox.nios_modules.nios_srv_record
nios_txt_record:
deprecation:
removal_version: 5.0.0
warning_text: The community.general.nios_txt_record module has been deprecated.
Please use infoblox.nios_modules.nios_txt_record instead.
redirect: infoblox.nios_modules.nios_txt_record
nios_zone:
deprecation:
removal_version: 5.0.0
warning_text: The community.general.nios_zone module has been deprecated.
Please use infoblox.nios_modules.nios_zone instead.
redirect: infoblox.nios_modules.nios_zone
ome_device_info:
redirect: dellemc.openmanage.ome_device_info
one_image_facts:
@@ -628,10 +571,7 @@ plugin_routing:
kubevirt_vm_options:
redirect: community.kubevirt.kubevirt_vm_options
nios:
deprecation:
removal_version: 5.0.0
warning_text: The community.general.nios document fragment has been deprecated.
Please use infoblox.nios_modules.nios instead.
redirect: infoblox.nios_modules.nios
postgresql:
redirect: community.postgresql.postgresql
module_utils:
@@ -650,10 +590,7 @@ plugin_routing:
kubevirt:
redirect: community.kubevirt.kubevirt
net_tools.nios.api:
deprecation:
removal_version: 5.0.0
warning_text: The community.general.net_tools.nios.api module_utils has been
deprecated. Please use infoblox.nios_modules.api instead.
redirect: infoblox.nios_modules.api
postgresql:
redirect: community.postgresql.postgresql
remote_management.dellemc.dellemc_idrac:

View File

@@ -45,6 +45,8 @@ class CallbackModule(CallbackBase):
_task_total = 0
_host_counter = 1
_host_total = 0
_current_batch_total = 0
_previous_batch_total = 0
def __init__(self):
super(CallbackModule, self).__init__()
@@ -76,8 +78,11 @@ class CallbackModule(CallbackBase):
self._display.banner(msg)
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._task_total = len(self._play.get_tasks()[0])
self._task_counter = 1
def v2_playbook_on_stats(self, stats):
self._display.banner("PLAY RECAP")
@@ -145,7 +150,7 @@ class CallbackModule(CallbackBase):
path = task.get_path()
if path:
self._display.display("task path: %s" % path, color=C.COLOR_DEBUG)
self._host_counter = 0
self._host_counter = self._previous_batch_total
self._task_counter += 1
def v2_runner_on_ok(self, result):

423
plugins/callback/elastic.py Normal file
View File

@@ -0,0 +1,423 @@
# (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

@@ -94,6 +94,7 @@ ansible.cfg: |
import os
import json
from ansible import context
import socket
import uuid
import logging
@@ -152,11 +153,11 @@ class CallbackModule(CallbackBase):
self.base_data['ansible_pre_command_output'] = os.popen(
self.ls_pre_command).read()
if self._options is not None:
self.base_data['ansible_checkmode'] = self._options.check
self.base_data['ansible_tags'] = self._options.tags
self.base_data['ansible_skip_tags'] = self._options.skip_tags
self.base_data['inventory'] = self._options.inventory
if context.CLIARGS is not None:
self.base_data['ansible_checkmode'] = context.CLIARGS.get('check')
self.base_data['ansible_tags'] = context.CLIARGS.get('tags')
self.base_data['ansible_skip_tags'] = context.CLIARGS.get('skip_tags')
self.base_data['inventory'] = context.CLIARGS.get('inventory')
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)

View File

@@ -70,6 +70,7 @@ import os
import json
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.plugins.callback import CallbackBase
@@ -143,7 +144,7 @@ class CallbackModule(CallbackBase):
body = {
'cmd': 'submitcheck',
'token': self.token,
'XMLDATA': bytes(xmldata)
'XMLDATA': to_bytes(xmldata)
}
try:

View File

@@ -1,3 +1,4 @@
# -*- 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)
@@ -23,6 +24,17 @@ DOCUMENTATION = '''
- 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
@@ -38,9 +50,9 @@ DOCUMENTATION = '''
env:
- name: TRACEPARENT
requirements:
- opentelemetry-api (python lib)
- opentelemetry-exporter-otlp (python lib)
- opentelemetry-sdk (python lib)
- opentelemetry-api (Python library)
- opentelemetry-exporter-otlp (Python library)
- opentelemetry-sdk (Python library)
'''
@@ -63,10 +75,12 @@ 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:
@@ -78,8 +92,6 @@ try:
from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import (
ConsoleSpanExporter,
SimpleSpanProcessor,
BatchSpanProcessor
)
from opentelemetry.util._time import _time_ns
@@ -88,18 +100,6 @@ except ImportError as imp_exc:
else:
OTEL_LIBRARY_IMPORT_ERROR = None
try:
from collections import OrderedDict
except ImportError:
try:
from ordereddict import OrderedDict
except ImportError as imp_exc:
ORDER_LIBRARY_IMPORT_ERROR = imp_exc
else:
ORDER_LIBRARY_IMPORT_ERROR = None
else:
ORDER_LIBRARY_IMPORT_ERROR = None
class TaskData:
"""
@@ -179,7 +179,7 @@ class OpenTelemetrySource(object):
args = None
if not task.no_log and not hide_task_arguments:
args = ', '.join(('%s=%s' % a for a in task.args.items()))
args = task.args
tasks_data[uuid] = TaskData(uuid, name, path, play_name, action, args)
@@ -246,37 +246,45 @@ class OpenTelemetrySource(object):
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':
rc = 0
else:
res = host_data.result._result
rc = res.get('rc', 0)
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':
if 'exception' in res:
message = res['exception'].strip().split('\n')[-1]
elif 'msg' in res:
message = res['msg']
else:
message = 'failed'
status = Status(status_code=StatusCode.ERROR, description=message)
# Record an exception with the task message
span.record_exception(BaseException(message))
span.record_exception(BaseException(enriched_error_message))
elif host_data.status == 'skipped':
if 'skip_reason' in res:
message = res['skip_reason']
else:
message = '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)
self.set_span_attribute(span, "ansible.task.args", task_data.args)
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):
@@ -288,6 +296,84 @@ class OpenTelemetrySource(object):
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")
for arg in url_args:
if 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):
"""
@@ -315,12 +401,7 @@ class CallbackModule(CallbackBase):
AnsibleError('The `opentelemetry-api`, `opentelemetry-exporter-otlp` or `opentelemetry-sdk` must be installed to use this plugin'),
OTEL_LIBRARY_IMPORT_ERROR)
if ORDER_LIBRARY_IMPORT_ERROR:
raise_from(
AnsibleError('The `ordereddict` must be installed to use this plugin'),
ORDER_LIBRARY_IMPORT_ERROR)
else:
self.tasks_data = OrderedDict()
self.tasks_data = OrderedDict()
self.opentelemetry = OpenTelemetrySource(display=self._display)
@@ -329,6 +410,12 @@ class CallbackModule(CallbackBase):
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')
@@ -378,10 +465,15 @@ class CallbackModule(CallbackBase):
)
def v2_runner_on_failed(self, result, ignore_errors=False):
self.errors += 1
if ignore_errors:
status = 'ignored'
else:
status = 'failed'
self.errors += 1
self.opentelemetry.finish_task(
self.tasks_data,
'failed',
status,
result
)

View File

@@ -21,11 +21,11 @@ DOCUMENTATION = '''
- In 2.8, this callback has been renamed from C(osx_say) into M(community.general.say).
'''
import distutils.spawn
import platform
import subprocess
import os
from ansible.module_utils.common.process import get_bin_path
from ansible.plugins.callback import CallbackBase
@@ -47,21 +47,24 @@ class CallbackModule(CallbackBase):
self.HAPPY_VOICE = None
self.LASER_VOICE = None
self.synthesizer = distutils.spawn.find_executable('say')
if not self.synthesizer:
self.synthesizer = distutils.spawn.find_executable('espeak')
if self.synthesizer:
try:
self.synthesizer = get_bin_path('say')
if platform.system() != 'Darwin':
# 'say' binary available, it might be GNUstep tool which doesn't support 'voice' parameter
self._display.warning("'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.HAPPY_VOICE = 'f5'
self.LASER_VOICE = 'whisper'
elif platform.system() != 'Darwin':
# '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'
except ValueError:
self.synthesizer = None
# plugin disable itself if say is not present
# ansible will not call any callback if disabled is set to True

View File

@@ -42,28 +42,29 @@ def should_use_block(value):
return False
def my_represent_scalar(self, tag, value, style=None):
"""Uses block style for multi-line strings"""
if style is None:
if should_use_block(value):
style = '|'
# we care more about readable than accuracy, so...
# ...no trailing space
value = value.rstrip()
# ...and non-printable characters
value = ''.join(x for x in value if x in string.printable or ord(x) >= 0xA0)
# ...tabs prevent blocks from expanding
value = value.expandtabs()
# ...and odd bits of whitespace
value = re.sub(r'[\x0b\x0c\r]', '', value)
# ...as does trailing space
value = re.sub(r' +\n', '\n', value)
else:
style = self.default_style
node = yaml.representer.ScalarNode(tag, value, style=style)
if self.alias_key is not None:
self.represented_objects[self.alias_key] = node
return node
class MyDumper(AnsibleDumper):
def represent_scalar(self, tag, value, style=None):
"""Uses block style for multi-line strings"""
if style is None:
if should_use_block(value):
style = '|'
# we care more about readable than accuracy, so...
# ...no trailing space
value = value.rstrip()
# ...and non-printable characters
value = ''.join(x for x in value if x in string.printable or ord(x) >= 0xA0)
# ...tabs prevent blocks from expanding
value = value.expandtabs()
# ...and odd bits of whitespace
value = re.sub(r'[\x0b\x0c\r]', '', value)
# ...as does trailing space
value = re.sub(r' +\n', '\n', value)
else:
style = self.default_style
node = yaml.representer.ScalarNode(tag, value, style=style)
if self.alias_key is not None:
self.represented_objects[self.alias_key] = node
return node
class CallbackModule(Default):
@@ -79,7 +80,6 @@ class CallbackModule(Default):
def __init__(self):
super(CallbackModule, self).__init__()
yaml.representer.BaseRepresenter.represent_scalar = my_represent_scalar
def _dump_results(self, result, indent=None, sort_keys=True, keep_invocation=False):
if result.get('_ansible_no_log', False):
@@ -121,7 +121,7 @@ class CallbackModule(Default):
if abridged_result:
dumped += '\n'
dumped += to_text(yaml.dump(abridged_result, allow_unicode=True, width=1000, Dumper=AnsibleDumper, default_flow_style=False))
dumped += to_text(yaml.dump(abridged_result, allow_unicode=True, width=1000, Dumper=MyDumper, default_flow_style=False))
# indent by a couple of spaces
dumped = '\n '.join(dumped.split('\n')).rstrip()

View File

@@ -31,7 +31,6 @@ DOCUMENTATION = '''
- name: ansible_jail_user
'''
import distutils.spawn
import os
import os.path
import subprocess
@@ -39,6 +38,7 @@ import traceback
from ansible.errors import AnsibleError
from ansible.module_utils.six.moves import shlex_quote
from ansible.module_utils.common.process import get_bin_path
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
from ansible.plugins.connection import ConnectionBase, BUFSIZE
from ansible.utils.display import Display
@@ -75,10 +75,10 @@ class Connection(ConnectionBase):
@staticmethod
def _search_executable(executable):
cmd = distutils.spawn.find_executable(executable)
if not cmd:
try:
return get_bin_path(executable)
except ValueError:
raise AnsibleError("%s command not found in PATH" % executable)
return cmd
def list_jails(self):
p = subprocess.Popen([self.jls_cmd, '-q', 'name'],

View File

@@ -43,10 +43,10 @@ DOCUMENTATION = '''
'''
import os
from distutils.spawn import find_executable
from subprocess import Popen, PIPE
from ansible.errors import AnsibleError, AnsibleConnectionFailure, AnsibleFileNotFound
from ansible.module_utils.common.process import get_bin_path
from ansible.module_utils.common.text.converters import to_bytes, to_text
from ansible.plugins.connection import ConnectionBase
@@ -62,9 +62,9 @@ class Connection(ConnectionBase):
super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
self._host = self._play_context.remote_addr
self._lxc_cmd = find_executable("lxc")
if not self._lxc_cmd:
try:
self._lxc_cmd = get_bin_path("lxc")
except ValueError:
raise AnsibleError("lxc command not found in PATH")
if self._play_context.remote_user is not None and self._play_context.remote_user != 'root':
@@ -89,9 +89,9 @@ class Connection(ConnectionBase):
local_cmd.extend(["--project", self.get_option("project")])
local_cmd.extend([
"exec",
"%s:%s" % (self.get_option("remote"), self._host),
"%s:%s" % (self.get_option("remote"), self.get_option("remote_addr")),
"--",
self._play_context.executable, "-c", cmd
self.get_option("executable"), "-c", cmd
])
local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
@@ -126,7 +126,7 @@ class Connection(ConnectionBase):
local_cmd.extend([
"file", "push",
in_path,
"%s:%s/%s" % (self.get_option("remote"), self._host, out_path)
"%s:%s/%s" % (self.get_option("remote"), self.get_option("remote_addr"), out_path)
])
local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
@@ -145,7 +145,7 @@ class Connection(ConnectionBase):
local_cmd.extend(["--project", self.get_option("project")])
local_cmd.extend([
"file", "pull",
"%s:%s/%s" % (self.get_option("remote"), self._host, in_path),
"%s:%s/%s" % (self.get_option("remote"), self.get_option("remote_addr"), in_path),
out_path
])

View File

@@ -26,7 +26,6 @@ DOCUMENTATION = '''
- name: ansible_zone_host
'''
import distutils.spawn
import os
import os.path
import subprocess
@@ -34,6 +33,7 @@ import traceback
from ansible.errors import AnsibleError
from ansible.module_utils.six.moves import shlex_quote
from ansible.module_utils.common.process import get_bin_path
from ansible.module_utils.common.text.converters import to_bytes
from ansible.plugins.connection import ConnectionBase, BUFSIZE
from ansible.utils.display import Display
@@ -64,10 +64,10 @@ class Connection(ConnectionBase):
@staticmethod
def _search_executable(executable):
cmd = distutils.spawn.find_executable(executable)
if not cmd:
try:
return get_bin_path(executable)
except ValueError:
raise AnsibleError("%s command not found in PATH" % executable)
return cmd
def list_zones(self):
process = subprocess.Popen([self.zoneadm_cmd, 'list', '-ip'],

View File

@@ -1,138 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2018, Sumit Kumar <sumit4@netapp.com>, chris Archibald <carchi@netapp.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
class ModuleDocFragment(object):
DOCUMENTATION = r'''
options:
- See respective platform section for more details
requirements:
- See respective platform section for more details
notes:
- Ansible modules are available for the following NetApp Storage Platforms: E-Series, ONTAP, SolidFire
'''
# Documentation fragment for ONTAP (na_cdot)
ONTAP = r'''
options:
hostname:
required: true
description:
- The hostname or IP address of the ONTAP instance.
username:
required: true
description:
- This can be a Cluster-scoped or SVM-scoped account, depending on whether a Cluster-level or SVM-level API is required.
For more information, please read the documentation U(https://mysupport.netapp.com/NOW/download/software/nmsdk/9.4/).
aliases: ['user']
password:
required: true
description:
- Password for the specified user.
aliases: ['pass']
requirements:
- A physical or virtual clustered Data ONTAP system. The modules were developed with Clustered Data ONTAP 8.3
- Ansible 2.2
- netapp-lib (2015.9.25). Install using 'pip install netapp-lib'
notes:
- The modules prefixed with na\\_cdot are built to support the ONTAP storage platform.
'''
# Documentation fragment for SolidFire
SOLIDFIRE = r'''
options:
hostname:
required: true
description:
- The hostname or IP address of the SolidFire cluster.
username:
required: true
description:
- Please ensure that the user has the adequate permissions. For more information, please read the official documentation
U(https://mysupport.netapp.com/documentation/docweb/index.html?productID=62636&language=en-US).
aliases: ['user']
password:
required: true
description:
- Password for the specified user.
aliases: ['pass']
requirements:
- The modules were developed with SolidFire 10.1
- solidfire-sdk-python (1.1.0.92) or greater. Install using 'pip install solidfire-sdk-python'
notes:
- The modules prefixed with na\\_elementsw are built to support the SolidFire storage platform.
'''
# Documentation fragment for ONTAP (na_ontap)
NA_ONTAP = r'''
options:
hostname:
description:
- The hostname or IP address of the ONTAP instance.
type: str
required: true
username:
description:
- This can be a Cluster-scoped or SVM-scoped account, depending on whether a Cluster-level or SVM-level API is required.
For more information, please read the documentation U(https://mysupport.netapp.com/NOW/download/software/nmsdk/9.4/).
type: str
required: true
aliases: [ user ]
password:
description:
- Password for the specified user.
type: str
required: true
aliases: [ pass ]
https:
description:
- Enable and disable https
type: bool
default: no
validate_certs:
description:
- If set to C(no), the SSL certificates will not be validated.
- This should only set to C(False) used on personally controlled sites using self-signed certificates.
type: bool
default: yes
http_port:
description:
- Override the default port (80 or 443) with this port
type: int
ontapi:
description:
- The ontap api version to use
type: int
use_rest:
description:
- REST API if supported by the target system for all the resources and attributes the module requires. Otherwise will revert to ZAPI.
- Always -- will always use the REST API
- Never -- will always use the ZAPI
- Auto -- will try to use the REST Api
default: Auto
choices: ['Never', 'Always', 'Auto']
type: str
requirements:
- A physical or virtual clustered Data ONTAP system. The modules support Data ONTAP 9.1 and onward
- Ansible 2.6
- Python2 netapp-lib (2017.10.30) or later. Install using 'pip install netapp-lib'
- Python3 netapp-lib (2018.11.13) or later. Install using 'pip install netapp-lib'
- To enable http on the cluster you must run the following commands 'set -privilege advanced;' 'system services web modify -http-enabled true;'
notes:
- The modules prefixed with na\\_ontap are built to support the ONTAP storage platform.
'''

View File

@@ -0,0 +1,41 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2019, Evgeniy Krysanov <evgeniy.krysanov@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
class ModuleDocFragment(object):
# Standard documentation fragment
DOCUMENTATION = r'''
options:
client_id:
description:
- The OAuth consumer key.
- If not set the environment variable C(BITBUCKET_CLIENT_ID) will be used.
type: str
client_secret:
description:
- The OAuth consumer secret.
- If not set the environment variable C(BITBUCKET_CLIENT_SECRET) will be used.
type: str
user:
description:
- The username.
- If not set the environment variable C(BITBUCKET_USERNAME) will be used.
type: str
version_added: 4.0.0
password:
description:
- The App password.
- If not set the environment variable C(BITBUCKET_PASSWORD) will be used.
type: str
version_added: 4.0.0
notes:
- Bitbucket OAuth consumer key and secret can be obtained from Bitbucket profile -> Settings -> Access Management -> OAuth.
- Bitbucket App password can be created from Bitbucket profile -> Personal Settings -> App passwords.
- If both OAuth and Basic Auth credentials are passed, OAuth credentials take precedence.
'''

View File

@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# 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
class ModuleDocFragment(object):
# Standard files documentation fragment
DOCUMENTATION = r'''
requirements:
- requests (Python library U(https://pypi.org/project/requests/))
options:
api_token:
description:
- GitLab access token with API permissions.
type: str
api_oauth_token:
description:
- GitLab OAuth token for logging in.
type: str
version_added: 4.2.0
api_job_token:
description:
- GitLab CI job token for logging in.
type: str
version_added: 4.2.0
'''

View File

@@ -1,103 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2015, Peter Sprygada <psprygada@ansible.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
class ModuleDocFragment(object):
# Standard files documentation fragment
DOCUMENTATION = r'''
options:
provider:
description:
- A dict object containing connection details.
type: dict
suboptions:
host:
description:
- Specifies the DNS host name or address for connecting to the remote
instance of NIOS WAPI over REST
- Value can also be specified using C(INFOBLOX_HOST) environment
variable.
type: str
username:
description:
- Configures the username to use to authenticate the connection to
the remote instance of NIOS.
- Value can also be specified using C(INFOBLOX_USERNAME) environment
variable.
type: str
password:
description:
- Specifies the password to use to authenticate the connection to
the remote instance of NIOS.
- Value can also be specified using C(INFOBLOX_PASSWORD) environment
variable.
type: str
validate_certs:
description:
- Boolean value to enable or disable verifying SSL certificates
- Value can also be specified using C(INFOBLOX_SSL_VERIFY) environment
variable.
type: bool
default: no
aliases: [ ssl_verify ]
http_request_timeout:
description:
- The amount of time before to wait before receiving a response
- Value can also be specified using C(INFOBLOX_HTTP_REQUEST_TIMEOUT) environment
variable.
type: int
default: 10
max_retries:
description:
- Configures the number of attempted retries before the connection
is declared usable
- Value can also be specified using C(INFOBLOX_MAX_RETRIES) environment
variable.
type: int
default: 3
wapi_version:
description:
- Specifies the version of WAPI to use
- Value can also be specified using C(INFOBLOX_WAP_VERSION) environment
variable.
- Until ansible 2.8 the default WAPI was 1.4
type: str
default: '2.1'
max_results:
description:
- Specifies the maximum number of objects to be returned,
if set to a negative number the appliance will return an error when the
number of returned objects would exceed the setting.
- Value can also be specified using C(INFOBLOX_MAX_RESULTS) environment
variable.
type: int
default: 1000
http_pool_connections:
description:
- Number of pools to be used by the C(infoblox_client.Connector) object.
- This is passed as-is to the underlying C(requests.adapters.HTTPAdapter) class.
type: int
default: 10
http_pool_maxsize:
description:
- Maximum number of connections per pool to be used by the C(infoblox_client.Connector) object.
- This is passed as-is to the underlying C(requests.adapters.HTTPAdapter) class.
type: int
default: 10
silent_ssl_warnings:
description:
- Disable C(urllib3) SSL warnings in the C(infoblox_client.Connector) object.
- This is passed as-is to the underlying C(requests.adapters.HTTPAdapter) class.
type: bool
default: true
notes:
- "This module must be run locally, which can be achieved by specifying C(connection: local)."
- Please read the :ref:`nios_guide` for more detailed information on how to use Infoblox with Ansible.
'''

View File

@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2021, Phillipe Smith <phsmithcc@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
class ModuleDocFragment(object):
# Standard files documentation fragment
DOCUMENTATION = r'''
options:
url:
type: str
description:
- Rundeck instance URL.
required: true
api_version:
type: int
description:
- Rundeck API version to be used.
- API version must be at least 14.
default: 39
api_token:
type: str
description:
- Rundeck User API Token.
required: true
'''

36
plugins/filter/counter.py Normal file
View File

@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021, Remy Keil <remy.keil@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
from ansible.errors import AnsibleFilterError
from ansible.module_utils.common._collections_compat import Sequence
from collections import Counter
def counter(sequence):
''' Count elements in a sequence. Returns dict with count result. '''
if not isinstance(sequence, Sequence):
raise AnsibleFilterError('Argument for community.general.counter must be a sequence (string or list). %s is %s' %
(sequence, type(sequence)))
try:
result = dict(Counter(sequence))
except TypeError as e:
raise AnsibleFilterError(
"community.general.counter needs a sequence with hashable elements (int, float or str) - %s" % (e)
)
return result
class FilterModule(object):
''' Ansible counter jinja2 filters '''
def filters(self):
filters = {
'counter': counter,
}
return filters

View File

@@ -5,7 +5,7 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from distutils.version import LooseVersion
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
def version_sort(value, reverse=False):

View File

@@ -68,7 +68,6 @@ user: ansible-tester
password: secure
'''
from distutils.version import LooseVersion
import socket
from ansible.errors import AnsibleError

View File

@@ -35,13 +35,23 @@ DOCUMENTATION = '''
type: string
required: true
host_filter:
description: An Icinga2 API valid host filter.
description:
- An Icinga2 API valid host filter. Leave blank for no filtering
type: string
required: false
validate_certs:
description: Enables or disables SSL certificate verification.
type: boolean
default: true
inventory_attr:
description:
- Allows the override of the inventory name based on different attributes.
- This allows for changing the way limits are used.
- The current default, C(address), is sometimes not unique or present. We recommend to use C(name) instead.
type: string
default: address
choices: ['name', 'display_name', 'address']
version_added: 4.2.0
'''
EXAMPLES = r'''
@@ -52,6 +62,7 @@ user: ansible
password: secure
host_filter: \"linux-servers\" in host.groups
validate_certs: false
inventory_attr: name
'''
import json
@@ -59,6 +70,7 @@ import json
from ansible.errors import AnsibleParserError
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable
from ansible.module_utils.urls import open_url
from ansible.module_utils.six.moves.urllib.error import HTTPError
class InventoryModule(BaseInventoryPlugin, Constructable):
@@ -76,6 +88,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
self.icinga2_password = None
self.ssl_verify = None
self.host_filter = None
self.inventory_attr = None
self.cache_key = None
self.use_cache = None
@@ -114,9 +127,21 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
if data is not None:
request_args['data'] = json.dumps(data)
self.display.vvv("Request Args: %s" % request_args)
response = open_url(request_url, **request_args)
try:
response = open_url(request_url, **request_args)
except HTTPError as e:
try:
error_body = json.loads(e.read().decode())
self.display.vvv("Error returned: {0}".format(error_body))
except Exception:
error_body = {"status": None}
if e.code == 404 and error_body.get('status') == "No objects found.":
raise AnsibleParserError("Host filter returned no data. Please confirm your host_filter value is valid")
raise AnsibleParserError("Unexpected data returned: {0} -- {1}".format(e, error_body))
response_body = response.read()
json_data = json.loads(response_body.decode('utf-8'))
self.display.vvv("Returned Data: %s" % json.dumps(json_data, indent=4, sort_keys=True))
if 200 <= response.status <= 299:
return json_data
if response.status == 404 and json_data['status'] == "No objects found.":
@@ -155,7 +180,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
"""Query for all hosts """
self.display.vvv("Querying Icinga2 for inventory")
query_args = {
"attrs": ["address", "state_type", "state", "groups"],
"attrs": ["address", "display_name", "state_type", "state", "groups"],
}
if self.host_filter is not None:
query_args['host_filter'] = self.host_filter
@@ -177,24 +202,35 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
"""Convert Icinga2 API data to JSON format for Ansible"""
groups_dict = {"_meta": {"hostvars": {}}}
for entry in json_data:
host_name = entry['name']
host_attrs = entry['attrs']
if self.inventory_attr == "name":
host_name = entry.get('name')
if self.inventory_attr == "address":
# When looking for address for inventory, if missing fallback to object name
if host_attrs.get('address', '') != '':
host_name = host_attrs.get('address')
else:
host_name = entry.get('name')
if self.inventory_attr == "display_name":
host_name = host_attrs.get('display_name')
if host_attrs['state'] == 0:
host_attrs['state'] = 'on'
else:
host_attrs['state'] = 'off'
host_groups = host_attrs['groups']
host_addr = host_attrs['address']
self.inventory.add_host(host_addr)
host_groups = host_attrs.get('groups')
self.inventory.add_host(host_name)
for group in host_groups:
if group not in self.inventory.groups.keys():
self.inventory.add_group(group)
self.inventory.add_child(group, host_addr)
self.inventory.set_variable(host_addr, 'address', host_addr)
self.inventory.set_variable(host_addr, 'hostname', host_name)
self.inventory.set_variable(host_addr, 'state',
self.inventory.add_child(group, host_name)
# If the address attribute is populated, override ansible_host with the value
if host_attrs.get('address') != '':
self.inventory.set_variable(host_name, 'ansible_host', host_attrs.get('address'))
self.inventory.set_variable(host_name, 'hostname', entry.get('name'))
self.inventory.set_variable(host_name, 'display_name', host_attrs.get('display_name'))
self.inventory.set_variable(host_name, 'state',
host_attrs['state'])
self.inventory.set_variable(host_addr, 'state_type',
self.inventory.set_variable(host_name, 'state_type',
host_attrs['state_type'])
return groups_dict
@@ -211,6 +247,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
self.icinga2_password = self.get_option('password')
self.ssl_verify = self.get_option('validate_certs')
self.host_filter = self.get_option('host_filter')
self.inventory_attr = self.get_option('inventory_attr')
# Not currently enabled
# self.cache_key = self.get_cache_key(path)
# self.use_cache = cache and self.get_option('cache')

View File

@@ -13,6 +13,9 @@ DOCUMENTATION = r'''
- Uses a YAML configuration file that ends with 'lxd.(yml|yaml)'.
version_added: "3.0.0"
author: "Frank Dornheim (@conloos)"
requirements:
- ipaddress
- lxd >= 4.0
options:
plugin:
description: Token that ensures this is a source file for the 'lxd' plugin.
@@ -47,26 +50,38 @@ DOCUMENTATION = r'''
- If I(trust_password) is set, this module send a request for authentication before sending any requests.
type: str
state:
description: Filter the container according to the current status.
description: Filter the instance according to the current status.
type: str
default: none
choices: [ 'STOPPED', 'STARTING', 'RUNNING', 'none' ]
prefered_container_network_interface:
type_filter:
description:
- If a container has multiple network interfaces, select which one is the prefered as pattern.
- Filter the instances by type C(virtual-machine), C(container) or C(both).
- The first version of the inventory only supported containers.
type: str
default: container
choices: [ 'virtual-machine', 'container', 'both' ]
version_added: 4.2.0
prefered_instance_network_interface:
description:
- If an instance has multiple network interfaces, select which one is the prefered as pattern.
- Combined with the first number that can be found e.g. 'eth' + 0.
- The option has been renamed from I(prefered_container_network_interface) to I(prefered_instance_network_interface) in community.general 3.8.0.
The old name still works as an alias.
type: str
default: eth
prefered_container_network_family:
aliases:
- prefered_container_network_interface
prefered_instance_network_family:
description:
- If a container has multiple network interfaces, which one is the prefered by family.
- If an instance has multiple network interfaces, which one is the prefered by family.
- Specify C(inet) for IPv4 and C(inet6) for IPv6.
type: str
default: inet
choices: [ 'inet', 'inet6' ]
groupby:
description:
- Create groups by the following keywords C(location), C(pattern), C(network_range), C(os), C(release), C(profile), C(vlanid).
- Create groups by the following keywords C(location), C(network_range), C(os), C(pattern), C(profile), C(release), C(type), C(vlanid).
- See example for syntax.
type: dict
'''
@@ -81,38 +96,49 @@ plugin: community.general.lxd
url: unix:/var/snap/lxd/common/lxd/unix.socket
state: RUNNING
# simple lxd.yml including virtual machines and containers
plugin: community.general.lxd
url: unix:/var/snap/lxd/common/lxd/unix.socket
type_filter: both
# grouping lxd.yml
groupby:
testpattern:
type: pattern
attribute: test
vlan666:
type: vlanid
attribute: 666
locationBerlin:
type: location
attribute: Berlin
osUbuntu:
type: os
attribute: ubuntu
releaseFocal:
type: release
attribute: focal
releaseBionic:
type: release
attribute: bionic
profileDefault:
type: profile
attribute: default
profileX11:
type: profile
attribute: x11
netRangeIPv4:
type: network_range
attribute: 10.98.143.0/24
netRangeIPv6:
type: network_range
attribute: fd42:bd00:7b11:2167:216:3eff::/24
osUbuntu:
type: os
attribute: ubuntu
testpattern:
type: pattern
attribute: test
profileDefault:
type: profile
attribute: default
profileX11:
type: profile
attribute: x11
releaseFocal:
type: release
attribute: focal
releaseBionic:
type: release
attribute: bionic
typeVM:
type: type
attribute: virtual-machine
typeContainer:
type: type
attribute: container
vlan666:
type: vlanid
attribute: 666
'''
import binascii
@@ -124,10 +150,17 @@ import socket
from ansible.plugins.inventory import BaseInventoryPlugin
from ansible.module_utils.common.text.converters import to_native, to_text
from ansible.module_utils.common.dict_transformations import dict_merge
from ansible.module_utils.six import raise_from
from ansible.errors import AnsibleError, AnsibleParserError
from ansible_collections.community.general.plugins.module_utils.compat import ipaddress
from ansible_collections.community.general.plugins.module_utils.lxd import LXDClient, LXDClientException
try:
import ipaddress
except ImportError as exc:
IPADDRESS_IMPORT_ERROR = exc
else:
IPADDRESS_IMPORT_ERROR = None
class InventoryModule(BaseInventoryPlugin):
DEBUG = 4
@@ -274,10 +307,10 @@ class InventoryModule(BaseInventoryPlugin):
network_configs = self.socket.do('GET', '/1.0/networks')
return [m.split('/')[3] for m in network_configs['metadata']]
def _get_containers(self):
"""Get Containernames
def _get_instances(self):
"""Get instancenames
Returns all containernames
Returns all instancenames
Args:
None
@@ -286,25 +319,27 @@ class InventoryModule(BaseInventoryPlugin):
Raises:
None
Returns:
list(names): names of all containers"""
# e.g. {'type': 'sync',
# 'status': 'Success',
# 'status_code': 200,
# 'operation': '',
# 'error_code': 0,
# 'error': '',
# 'metadata': ['/1.0/containers/udemy-ansible-ubuntu-2004']}
containers = self.socket.do('GET', '/1.0/containers')
return [m.split('/')[3] for m in containers['metadata']]
list(names): names of all instances"""
# e.g. {
# "metadata": [
# "/1.0/instances/foo",
# "/1.0/instances/bar"
# ],
# "status": "Success",
# "status_code": 200,
# "type": "sync"
# }
instances = self.socket.do('GET', '/1.0/instances')
return [m.split('/')[3] for m in instances['metadata']]
def _get_config(self, branch, name):
"""Get inventory of container
"""Get inventory of instance
Get config of container
Get config of instance
Args:
str(branch): Name oft the API-Branch
str(name): Name of Container
str(name): Name of instance
Kwargs:
None
Source:
@@ -312,7 +347,7 @@ class InventoryModule(BaseInventoryPlugin):
Raises:
None
Returns:
dict(config): Config of the container"""
dict(config): Config of the instance"""
config = {}
if isinstance(branch, (tuple, list)):
config[name] = {branch[1]: self.socket.do('GET', '/1.0/{0}/{1}/{2}'.format(to_native(branch[0]), to_native(name), to_native(branch[1])))}
@@ -320,13 +355,13 @@ class InventoryModule(BaseInventoryPlugin):
config[name] = {branch: self.socket.do('GET', '/1.0/{0}/{1}'.format(to_native(branch), to_native(name)))}
return config
def get_container_data(self, names):
"""Create Inventory of the container
def get_instance_data(self, names):
"""Create Inventory of the instance
Iterate through the different branches of the containers and collect Informations.
Iterate through the different branches of the instances and collect Informations.
Args:
list(names): List of container names
list(names): List of instance names
Kwargs:
None
Raises:
@@ -335,20 +370,20 @@ class InventoryModule(BaseInventoryPlugin):
None"""
# tuple(('instances','metadata/templates')) to get section in branch
# e.g. /1.0/instances/<name>/metadata/templates
branches = ['containers', ('instances', 'state')]
container_config = {}
branches = ['instances', ('instances', 'state')]
instance_config = {}
for branch in branches:
for name in names:
container_config['containers'] = self._get_config(branch, name)
self.data = dict_merge(container_config, self.data)
instance_config['instances'] = self._get_config(branch, name)
self.data = dict_merge(instance_config, self.data)
def get_network_data(self, names):
"""Create Inventory of the container
"""Create Inventory of the instance
Iterate through the different branches of the containers and collect Informations.
Iterate through the different branches of the instances and collect Informations.
Args:
list(names): List of container names
list(names): List of instance names
Kwargs:
None
Raises:
@@ -367,26 +402,26 @@ class InventoryModule(BaseInventoryPlugin):
network_config['networks'] = {name: None}
self.data = dict_merge(network_config, self.data)
def extract_network_information_from_container_config(self, container_name):
def extract_network_information_from_instance_config(self, instance_name):
"""Returns the network interface configuration
Returns the network ipv4 and ipv6 config of the container without local-link
Returns the network ipv4 and ipv6 config of the instance without local-link
Args:
str(container_name): Name oft he container
str(instance_name): Name oft he instance
Kwargs:
None
Raises:
None
Returns:
dict(network_configuration): network config"""
container_network_interfaces = self._get_data_entry('containers/{0}/state/metadata/network'.format(container_name))
instance_network_interfaces = self._get_data_entry('instances/{0}/state/metadata/network'.format(instance_name))
network_configuration = None
if container_network_interfaces:
if instance_network_interfaces:
network_configuration = {}
gen_interface_names = [interface_name for interface_name in container_network_interfaces if interface_name != 'lo']
gen_interface_names = [interface_name for interface_name in instance_network_interfaces if interface_name != 'lo']
for interface_name in gen_interface_names:
gen_address = [address for address in container_network_interfaces[interface_name]['addresses'] if address.get('scope') != 'link']
gen_address = [address for address in instance_network_interfaces[interface_name]['addresses'] if address.get('scope') != 'link']
network_configuration[interface_name] = []
for address in gen_address:
address_set = {}
@@ -397,24 +432,24 @@ class InventoryModule(BaseInventoryPlugin):
network_configuration[interface_name].append(address_set)
return network_configuration
def get_prefered_container_network_interface(self, container_name):
"""Helper to get the prefered interface of thr container
def get_prefered_instance_network_interface(self, instance_name):
"""Helper to get the prefered interface of thr instance
Helper to get the prefered interface provide by neme pattern from 'prefered_container_network_interface'.
Helper to get the prefered interface provide by neme pattern from 'prefered_instance_network_interface'.
Args:
str(containe_name): name of container
str(containe_name): name of instance
Kwargs:
None
Raises:
None
Returns:
str(prefered_interface): None or interface name"""
container_network_interfaces = self._get_data_entry('inventory/{0}/network_interfaces'.format(container_name))
instance_network_interfaces = self._get_data_entry('inventory/{0}/network_interfaces'.format(instance_name))
prefered_interface = None # init
if container_network_interfaces: # container have network interfaces
if instance_network_interfaces: # instance have network interfaces
# generator if interfaces which start with the desired pattern
net_generator = [interface for interface in container_network_interfaces if interface.startswith(self.prefered_container_network_interface)]
net_generator = [interface for interface in instance_network_interfaces if interface.startswith(self.prefered_instance_network_interface)]
selected_interfaces = [] # init
for interface in net_generator:
selected_interfaces.append(interface)
@@ -422,13 +457,13 @@ class InventoryModule(BaseInventoryPlugin):
prefered_interface = sorted(selected_interfaces)[0]
return prefered_interface
def get_container_vlans(self, container_name):
"""Get VLAN(s) from container
def get_instance_vlans(self, instance_name):
"""Get VLAN(s) from instance
Helper to get the VLAN_ID from the container
Helper to get the VLAN_ID from the instance
Args:
str(containe_name): name of container
str(containe_name): name of instance
Kwargs:
None
Raises:
@@ -441,13 +476,13 @@ class InventoryModule(BaseInventoryPlugin):
if self._get_data_entry('state/metadata/vlan/vid', data=self.data['networks'].get(network)):
network_vlans[network] = self._get_data_entry('state/metadata/vlan/vid', data=self.data['networks'].get(network))
# get networkdevices of container and return
# get networkdevices of instance and return
# e.g.
# "eth0":{ "name":"eth0",
# "network":"lxdbr0",
# "type":"nic"},
vlan_ids = {}
devices = self._get_data_entry('containers/{0}/containers/metadata/expanded_devices'.format(to_native(container_name)))
devices = self._get_data_entry('instances/{0}/instances/metadata/expanded_devices'.format(to_native(instance_name)))
for device in devices:
if 'network' in devices[device]:
if devices[device]['network'] in network_vlans:
@@ -483,14 +518,14 @@ class InventoryModule(BaseInventoryPlugin):
except KeyError:
return None
def _set_data_entry(self, container_name, key, value, path=None):
def _set_data_entry(self, instance_name, key, value, path=None):
"""Helper to save data
Helper to save the data in self.data
Detect if data is allready in branch and use dict_merge() to prevent that branch is overwritten.
Args:
str(container_name): name of container
str(instance_name): name of instance
str(key): same as dict
*(value): same as dict
Kwargs:
@@ -501,24 +536,24 @@ class InventoryModule(BaseInventoryPlugin):
None"""
if not path:
path = self.data['inventory']
if container_name not in path:
path[container_name] = {}
if instance_name not in path:
path[instance_name] = {}
try:
if isinstance(value, dict) and key in path[container_name]:
path[container_name] = dict_merge(value, path[container_name][key])
if isinstance(value, dict) and key in path[instance_name]:
path[instance_name] = dict_merge(value, path[instance_name][key])
else:
path[container_name][key] = value
path[instance_name][key] = value
except KeyError as err:
raise AnsibleParserError("Unable to store Informations: {0}".format(to_native(err)))
def extract_information_from_container_configs(self):
def extract_information_from_instance_configs(self):
"""Process configuration information
Preparation of the data
Args:
dict(configs): Container configurations
dict(configs): instance configurations
Kwargs:
None
Raises:
@@ -529,33 +564,35 @@ class InventoryModule(BaseInventoryPlugin):
if 'inventory' not in self.data:
self.data['inventory'] = {}
for container_name in self.data['containers']:
self._set_data_entry(container_name, 'os', self._get_data_entry(
'containers/{0}/containers/metadata/config/image.os'.format(container_name)))
self._set_data_entry(container_name, 'release', self._get_data_entry(
'containers/{0}/containers/metadata/config/image.release'.format(container_name)))
self._set_data_entry(container_name, 'version', self._get_data_entry(
'containers/{0}/containers/metadata/config/image.version'.format(container_name)))
self._set_data_entry(container_name, 'profile', self._get_data_entry(
'containers/{0}/containers/metadata/profiles'.format(container_name)))
self._set_data_entry(container_name, 'location', self._get_data_entry(
'containers/{0}/containers/metadata/location'.format(container_name)))
self._set_data_entry(container_name, 'state', self._get_data_entry(
'containers/{0}/containers/metadata/config/volatile.last_state.power'.format(container_name)))
self._set_data_entry(container_name, 'network_interfaces', self.extract_network_information_from_container_config(container_name))
self._set_data_entry(container_name, 'preferred_interface', self.get_prefered_container_network_interface(container_name))
self._set_data_entry(container_name, 'vlan_ids', self.get_container_vlans(container_name))
for instance_name in self.data['instances']:
self._set_data_entry(instance_name, 'os', self._get_data_entry(
'instances/{0}/instances/metadata/config/image.os'.format(instance_name)))
self._set_data_entry(instance_name, 'release', self._get_data_entry(
'instances/{0}/instances/metadata/config/image.release'.format(instance_name)))
self._set_data_entry(instance_name, 'version', self._get_data_entry(
'instances/{0}/instances/metadata/config/image.version'.format(instance_name)))
self._set_data_entry(instance_name, 'profile', self._get_data_entry(
'instances/{0}/instances/metadata/profiles'.format(instance_name)))
self._set_data_entry(instance_name, 'location', self._get_data_entry(
'instances/{0}/instances/metadata/location'.format(instance_name)))
self._set_data_entry(instance_name, 'state', self._get_data_entry(
'instances/{0}/instances/metadata/config/volatile.last_state.power'.format(instance_name)))
self._set_data_entry(instance_name, 'type', self._get_data_entry(
'instances/{0}/instances/metadata/type'.format(instance_name)))
self._set_data_entry(instance_name, 'network_interfaces', self.extract_network_information_from_instance_config(instance_name))
self._set_data_entry(instance_name, 'preferred_interface', self.get_prefered_instance_network_interface(instance_name))
self._set_data_entry(instance_name, 'vlan_ids', self.get_instance_vlans(instance_name))
def build_inventory_network(self, container_name):
"""Add the network interfaces of the container to the inventory
def build_inventory_network(self, instance_name):
"""Add the network interfaces of the instance to the inventory
Logic:
- if the container have no interface -> 'ansible_connection: local'
- get preferred_interface & prefered_container_network_family -> 'ansible_connection: ssh' & 'ansible_host: <IP>'
- first Interface from: network_interfaces prefered_container_network_family -> 'ansible_connection: ssh' & 'ansible_host: <IP>'
- if the instance have no interface -> 'ansible_connection: local'
- get preferred_interface & prefered_instance_network_family -> 'ansible_connection: ssh' & 'ansible_host: <IP>'
- first Interface from: network_interfaces prefered_instance_network_family -> 'ansible_connection: ssh' & 'ansible_host: <IP>'
Args:
str(container_name): name of container
str(instance_name): name of instance
Kwargs:
None
Raises:
@@ -563,45 +600,45 @@ class InventoryModule(BaseInventoryPlugin):
Returns:
None"""
def interface_selection(container_name):
"""Select container Interface for inventory
def interface_selection(instance_name):
"""Select instance Interface for inventory
Logic:
- get preferred_interface & prefered_container_network_family -> str(IP)
- first Interface from: network_interfaces prefered_container_network_family -> str(IP)
- get preferred_interface & prefered_instance_network_family -> str(IP)
- first Interface from: network_interfaces prefered_instance_network_family -> str(IP)
Args:
str(container_name): name of container
str(instance_name): name of instance
Kwargs:
None
Raises:
None
Returns:
dict(interface_name: ip)"""
prefered_interface = self._get_data_entry('inventory/{0}/preferred_interface'.format(container_name)) # name or None
prefered_container_network_family = self.prefered_container_network_family
prefered_interface = self._get_data_entry('inventory/{0}/preferred_interface'.format(instance_name)) # name or None
prefered_instance_network_family = self.prefered_instance_network_family
ip_address = ''
if prefered_interface:
interface = self._get_data_entry('inventory/{0}/network_interfaces/{1}'.format(container_name, prefered_interface))
interface = self._get_data_entry('inventory/{0}/network_interfaces/{1}'.format(instance_name, prefered_interface))
for config in interface:
if config['family'] == prefered_container_network_family:
if config['family'] == prefered_instance_network_family:
ip_address = config['address']
break
else:
interface = self._get_data_entry('inventory/{0}/network_interfaces'.format(container_name))
for config in interface:
if config['family'] == prefered_container_network_family:
ip_address = config['address']
break
interfaces = self._get_data_entry('inventory/{0}/network_interfaces'.format(instance_name))
for interface in interfaces.values():
for config in interface:
if config['family'] == prefered_instance_network_family:
ip_address = config['address']
break
return ip_address
if self._get_data_entry('inventory/{0}/network_interfaces'.format(container_name)): # container have network interfaces
if self._get_data_entry('inventory/{0}/preferred_interface'.format(container_name)): # container have a preferred interface
self.inventory.set_variable(container_name, 'ansible_connection', 'ssh')
self.inventory.set_variable(container_name, 'ansible_host', interface_selection(container_name))
if self._get_data_entry('inventory/{0}/network_interfaces'.format(instance_name)): # instance have network interfaces
self.inventory.set_variable(instance_name, 'ansible_connection', 'ssh')
self.inventory.set_variable(instance_name, 'ansible_host', interface_selection(instance_name))
else:
self.inventory.set_variable(container_name, 'ansible_connection', 'local')
self.inventory.set_variable(instance_name, 'ansible_connection', 'local')
def build_inventory_hosts(self):
"""Build host-part dynamic inventory
@@ -617,29 +654,33 @@ class InventoryModule(BaseInventoryPlugin):
None
Returns:
None"""
for container_name in self.data['inventory']:
# Only consider containers that match the "state" filter, if self.state is not None
for instance_name in self.data['inventory']:
instance_state = str(self._get_data_entry('inventory/{0}/state'.format(instance_name)) or "STOPPED").lower()
# Only consider instances that match the "state" filter, if self.state is not None
if self.filter:
if self.filter.lower() != self._get_data_entry('inventory/{0}/state'.format(container_name)).lower():
if self.filter.lower() != instance_state:
continue
# add container
self.inventory.add_host(container_name)
# add instance
self.inventory.add_host(instance_name)
# add network informations
self.build_inventory_network(container_name)
self.build_inventory_network(instance_name)
# add os
self.inventory.set_variable(container_name, 'ansible_lxd_os', self._get_data_entry('inventory/{0}/os'.format(container_name)).lower())
self.inventory.set_variable(instance_name, 'ansible_lxd_os', self._get_data_entry('inventory/{0}/os'.format(instance_name)).lower())
# add release
self.inventory.set_variable(container_name, 'ansible_lxd_release', self._get_data_entry('inventory/{0}/release'.format(container_name)).lower())
self.inventory.set_variable(instance_name, 'ansible_lxd_release', self._get_data_entry('inventory/{0}/release'.format(instance_name)).lower())
# add profile
self.inventory.set_variable(container_name, 'ansible_lxd_profile', self._get_data_entry('inventory/{0}/profile'.format(container_name)))
self.inventory.set_variable(instance_name, 'ansible_lxd_profile', self._get_data_entry('inventory/{0}/profile'.format(instance_name)))
# add state
self.inventory.set_variable(container_name, 'ansible_lxd_state', self._get_data_entry('inventory/{0}/state'.format(container_name)).lower())
self.inventory.set_variable(instance_name, 'ansible_lxd_state', instance_state)
# add type
self.inventory.set_variable(instance_name, 'ansible_lxd_type', self._get_data_entry('inventory/{0}/type'.format(instance_name)))
# add location information
if self._get_data_entry('inventory/{0}/location'.format(container_name)) != "none": # wrong type by lxd 'none' != 'None'
self.inventory.set_variable(container_name, 'ansible_lxd_location', self._get_data_entry('inventory/{0}/location'.format(container_name)))
if self._get_data_entry('inventory/{0}/location'.format(instance_name)) != "none": # wrong type by lxd 'none' != 'None'
self.inventory.set_variable(instance_name, 'ansible_lxd_location', self._get_data_entry('inventory/{0}/location'.format(instance_name)))
# add VLAN_ID information
if self._get_data_entry('inventory/{0}/vlan_ids'.format(container_name)):
self.inventory.set_variable(container_name, 'ansible_lxd_vlan_ids', self._get_data_entry('inventory/{0}/vlan_ids'.format(container_name)))
if self._get_data_entry('inventory/{0}/vlan_ids'.format(instance_name)):
self.inventory.set_variable(instance_name, 'ansible_lxd_vlan_ids', self._get_data_entry('inventory/{0}/vlan_ids'.format(instance_name)))
def build_inventory_groups_location(self, group_name):
"""create group by attribute: location
@@ -656,9 +697,9 @@ class InventoryModule(BaseInventoryPlugin):
if group_name not in self.inventory.groups:
self.inventory.add_group(group_name)
for container_name in self.inventory.hosts:
if 'ansible_lxd_location' in self.inventory.get_host(container_name).get_vars():
self.inventory.add_child(group_name, container_name)
for instance_name in self.inventory.hosts:
if 'ansible_lxd_location' in self.inventory.get_host(instance_name).get_vars():
self.inventory.add_child(group_name, instance_name)
def build_inventory_groups_pattern(self, group_name):
"""create group by name pattern
@@ -677,10 +718,10 @@ class InventoryModule(BaseInventoryPlugin):
regex_pattern = self.groupby[group_name].get('attribute')
for container_name in self.inventory.hosts:
result = re.search(regex_pattern, container_name)
for instance_name in self.inventory.hosts:
result = re.search(regex_pattern, instance_name)
if result:
self.inventory.add_child(group_name, container_name)
self.inventory.add_child(group_name, instance_name)
def build_inventory_groups_network_range(self, group_name):
"""check if IP is in network-class
@@ -703,14 +744,14 @@ class InventoryModule(BaseInventoryPlugin):
raise AnsibleParserError(
'Error while parsing network range {0}: {1}'.format(self.groupby[group_name].get('attribute'), to_native(err)))
for container_name in self.inventory.hosts:
if self.data['inventory'][container_name].get('network_interfaces') is not None:
for interface in self.data['inventory'][container_name].get('network_interfaces'):
for interface_family in self.data['inventory'][container_name].get('network_interfaces')[interface]:
for instance_name in self.inventory.hosts:
if self.data['inventory'][instance_name].get('network_interfaces') is not None:
for interface in self.data['inventory'][instance_name].get('network_interfaces'):
for interface_family in self.data['inventory'][instance_name].get('network_interfaces')[interface]:
try:
address = ipaddress.ip_address(to_text(interface_family['address']))
if address.version == network.version and address in network:
self.inventory.add_child(group_name, container_name)
self.inventory.add_child(group_name, instance_name)
except ValueError:
# Ignore invalid IP addresses returned by lxd
pass
@@ -721,7 +762,7 @@ class InventoryModule(BaseInventoryPlugin):
Args:
str(group_name): Group name
Kwargs:
Noneself.data['inventory'][container_name][interface]
None
Raises:
None
Returns:
@@ -730,12 +771,12 @@ class InventoryModule(BaseInventoryPlugin):
if group_name not in self.inventory.groups:
self.inventory.add_group(group_name)
gen_containers = [
container_name for container_name in self.inventory.hosts
if 'ansible_lxd_os' in self.inventory.get_host(container_name).get_vars()]
for container_name in gen_containers:
if self.groupby[group_name].get('attribute').lower() == self.inventory.get_host(container_name).get_vars().get('ansible_lxd_os'):
self.inventory.add_child(group_name, container_name)
gen_instances = [
instance_name for instance_name in self.inventory.hosts
if 'ansible_lxd_os' in self.inventory.get_host(instance_name).get_vars()]
for instance_name in gen_instances:
if self.groupby[group_name].get('attribute').lower() == self.inventory.get_host(instance_name).get_vars().get('ansible_lxd_os'):
self.inventory.add_child(group_name, instance_name)
def build_inventory_groups_release(self, group_name):
"""create group by attribute: release
@@ -752,12 +793,12 @@ class InventoryModule(BaseInventoryPlugin):
if group_name not in self.inventory.groups:
self.inventory.add_group(group_name)
gen_containers = [
container_name for container_name in self.inventory.hosts
if 'ansible_lxd_release' in self.inventory.get_host(container_name).get_vars()]
for container_name in gen_containers:
if self.groupby[group_name].get('attribute').lower() == self.inventory.get_host(container_name).get_vars().get('ansible_lxd_release'):
self.inventory.add_child(group_name, container_name)
gen_instances = [
instance_name for instance_name in self.inventory.hosts
if 'ansible_lxd_release' in self.inventory.get_host(instance_name).get_vars()]
for instance_name in gen_instances:
if self.groupby[group_name].get('attribute').lower() == self.inventory.get_host(instance_name).get_vars().get('ansible_lxd_release'):
self.inventory.add_child(group_name, instance_name)
def build_inventory_groups_profile(self, group_name):
"""create group by attribute: profile
@@ -774,12 +815,12 @@ class InventoryModule(BaseInventoryPlugin):
if group_name not in self.inventory.groups:
self.inventory.add_group(group_name)
gen_containers = [
container_name for container_name in self.inventory.hosts.keys()
if 'ansible_lxd_profile' in self.inventory.get_host(container_name).get_vars().keys()]
for container_name in gen_containers:
if self.groupby[group_name].get('attribute').lower() in self.inventory.get_host(container_name).get_vars().get('ansible_lxd_profile'):
self.inventory.add_child(group_name, container_name)
gen_instances = [
instance_name for instance_name in self.inventory.hosts.keys()
if 'ansible_lxd_profile' in self.inventory.get_host(instance_name).get_vars().keys()]
for instance_name in gen_instances:
if self.groupby[group_name].get('attribute').lower() in self.inventory.get_host(instance_name).get_vars().get('ansible_lxd_profile'):
self.inventory.add_child(group_name, instance_name)
def build_inventory_groups_vlanid(self, group_name):
"""create group by attribute: vlanid
@@ -796,12 +837,34 @@ class InventoryModule(BaseInventoryPlugin):
if group_name not in self.inventory.groups:
self.inventory.add_group(group_name)
gen_containers = [
container_name for container_name in self.inventory.hosts.keys()
if 'ansible_lxd_vlan_ids' in self.inventory.get_host(container_name).get_vars().keys()]
for container_name in gen_containers:
if self.groupby[group_name].get('attribute') in self.inventory.get_host(container_name).get_vars().get('ansible_lxd_vlan_ids').values():
self.inventory.add_child(group_name, container_name)
gen_instances = [
instance_name for instance_name in self.inventory.hosts.keys()
if 'ansible_lxd_vlan_ids' in self.inventory.get_host(instance_name).get_vars().keys()]
for instance_name in gen_instances:
if self.groupby[group_name].get('attribute') in self.inventory.get_host(instance_name).get_vars().get('ansible_lxd_vlan_ids').values():
self.inventory.add_child(group_name, instance_name)
def build_inventory_groups_type(self, group_name):
"""create group by attribute: type
Args:
str(group_name): Group name
Kwargs:
None
Raises:
None
Returns:
None"""
# maybe we just want to expand one group
if group_name not in self.inventory.groups:
self.inventory.add_group(group_name)
gen_instances = [
instance_name for instance_name in self.inventory.hosts
if 'ansible_lxd_type' in self.inventory.get_host(instance_name).get_vars()]
for instance_name in gen_instances:
if self.groupby[group_name].get('attribute').lower() == self.inventory.get_host(instance_name).get_vars().get('ansible_lxd_type'):
self.inventory.add_child(group_name, instance_name)
def build_inventory_groups(self):
"""Build group-part dynamic inventory
@@ -830,6 +893,7 @@ class InventoryModule(BaseInventoryPlugin):
* 'release'
* 'profile'
* 'vlanid'
* 'type'
Args:
str(group_name): Group name
@@ -855,6 +919,8 @@ class InventoryModule(BaseInventoryPlugin):
self.build_inventory_groups_profile(group_name)
elif self.groupby[group_name].get('type') == 'vlanid':
self.build_inventory_groups_vlanid(group_name)
elif self.groupby[group_name].get('type') == 'type':
self.build_inventory_groups_type(group_name)
else:
raise AnsibleParserError('Unknown group type: {0}'.format(to_native(group_name)))
@@ -881,10 +947,30 @@ class InventoryModule(BaseInventoryPlugin):
self.build_inventory_hosts()
self.build_inventory_groups()
def cleandata(self):
"""Clean the dynamic inventory
The first version of the inventory only supported container.
This will change in the future.
The following function cleans up the data and remove the all items with the wrong type.
Args:
None
Kwargs:
None
Raises:
None
Returns:
None"""
iter_keys = list(self.data['instances'].keys())
for instance_name in iter_keys:
if self._get_data_entry('instances/{0}/instances/metadata/type'.format(instance_name)) != self.type_filter:
del self.data['instances'][instance_name]
def _populate(self):
"""Return the hosts and groups
Returns the processed container configurations from the lxd import
Returns the processed instance configurations from the lxd import
Args:
None
@@ -897,10 +983,16 @@ class InventoryModule(BaseInventoryPlugin):
if len(self.data) == 0: # If no data is injected by unittests open socket
self.socket = self._connect_to_socket()
self.get_container_data(self._get_containers())
self.get_instance_data(self._get_instances())
self.get_network_data(self._get_networks())
self.extract_information_from_container_configs()
# The first version of the inventory only supported containers.
# This will change in the future.
# The following function cleans up the data.
if self.type_filter != 'both':
self.cleandata()
self.extract_information_from_instance_configs()
# self.display.vvv(self.save_json_data([os.path.abspath(__file__)]))
@@ -924,6 +1016,10 @@ class InventoryModule(BaseInventoryPlugin):
AnsibleParserError
Returns:
None"""
if IPADDRESS_IMPORT_ERROR:
raise_from(
AnsibleError('another_library must be installed to use this plugin'),
IPADDRESS_IMPORT_ERROR)
super(InventoryModule, self).parse(inventory, loader, path, cache=False)
# Read the inventory YAML file
@@ -935,8 +1031,9 @@ class InventoryModule(BaseInventoryPlugin):
self.data = {} # store for inventory-data
self.groupby = self.get_option('groupby')
self.plugin = self.get_option('plugin')
self.prefered_container_network_family = self.get_option('prefered_container_network_family')
self.prefered_container_network_interface = self.get_option('prefered_container_network_interface')
self.prefered_instance_network_family = self.get_option('prefered_instance_network_family')
self.prefered_instance_network_interface = self.get_option('prefered_instance_network_interface')
self.type_filter = self.get_option('type_filter')
if self.get_option('state').lower() == 'none': # none in config is str()
self.filter = None
else:

View File

@@ -8,7 +8,7 @@ __metaclass__ = type
DOCUMENTATION = r'''
name: online
author:
- Remy Leone (@sieben)
- Remy Leone (@remyleone)
short_description: Scaleway (previously Online SAS or Online.net) inventory source
description:
- Get inventory hosts from Scaleway (previously Online SAS or Online.net).

View File

@@ -0,0 +1,239 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020, FELDSAM s.r.o. - FeldHost™ <support@feldhost.cz>
# 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 = r'''
name: opennebula
author:
- Kristian Feldsam (@feldsam)
short_description: OpenNebula inventory source
version_added: "3.8.0"
extends_documentation_fragment:
- constructed
description:
- Get inventory hosts from OpenNebula cloud.
- Uses an YAML configuration file ending with either I(opennebula.yml) or I(opennebula.yaml)
to set parameter values.
- Uses I(api_authfile), C(~/.one/one_auth), or C(ONE_AUTH) pointing to a OpenNebula credentials file.
options:
plugin:
description: Token that ensures this is a source file for the 'opennebula' plugin.
type: string
required: true
choices: [ community.general.opennebula ]
api_url:
description:
- URL of the OpenNebula RPC server.
- It is recommended to use HTTPS so that the username/password are not
transferred over the network unencrypted.
- If not set then the value of the C(ONE_URL) environment variable is used.
env:
- name: ONE_URL
required: True
type: string
api_username:
description:
- Name of the user to login into the OpenNebula RPC server. If not set
then the value of the C(ONE_USERNAME) environment variable is used.
env:
- name: ONE_USERNAME
type: string
api_password:
description:
- Password or a token of the user to login into OpenNebula RPC server.
- If not set, the value of the C(ONE_PASSWORD) environment variable is used.
env:
- name: ONE_PASSWORD
required: False
type: string
api_authfile:
description:
- If both I(api_username) or I(api_password) are not set, then it will try
authenticate with ONE auth file. Default path is C(~/.one/one_auth).
- Set environment variable C(ONE_AUTH) to override this path.
env:
- name: ONE_AUTH
required: False
type: string
hostname:
description: Field to match the hostname. Note C(v4_first_ip) corresponds to the first IPv4 found on VM.
type: string
default: v4_first_ip
choices:
- v4_first_ip
- v6_first_ip
- name
filter_by_label:
description: Only return servers filtered by this label.
type: string
group_by_labels:
description: Create host groups by vm labels
type: bool
default: True
'''
EXAMPLES = r'''
# inventory_opennebula.yml file in YAML format
# Example command line: ansible-inventory --list -i inventory_opennebula.yml
# Pass a label filter to the API
plugin: community.general.opennebula
api_url: https://opennebula:2633/RPC2
filter_by_label: Cache
'''
try:
import pyone
HAS_PYONE = True
except ImportError:
HAS_PYONE = False
from ansible.errors import AnsibleError
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable
from ansible.module_utils._text import to_native
from collections import namedtuple
import os
class InventoryModule(BaseInventoryPlugin, Constructable):
NAME = 'community.general.opennebula'
def verify_file(self, path):
valid = False
if super(InventoryModule, self).verify_file(path):
if path.endswith(('opennebula.yaml', 'opennebula.yml')):
valid = True
return valid
def _get_connection_info(self):
url = self.get_option('api_url')
username = self.get_option('api_username')
password = self.get_option('api_password')
authfile = self.get_option('api_authfile')
if not username and not password:
if authfile is None:
authfile = os.path.join(os.environ.get("HOME"), ".one", "one_auth")
try:
with open(authfile, "r") as fp:
authstring = fp.read().rstrip()
username, password = authstring.split(":")
except (OSError, IOError):
raise AnsibleError("Could not find or read ONE_AUTH file at '{e}'".format(e=authfile))
except Exception:
raise AnsibleError("Error occurs when reading ONE_AUTH file at '{e}'".format(e=authfile))
auth_params = namedtuple('auth', ('url', 'username', 'password'))
return auth_params(url=url, username=username, password=password)
def _get_vm_ipv4(self, vm):
nic = vm.TEMPLATE.get('NIC')
if isinstance(nic, dict):
nic = [nic]
for net in nic:
return net['IP']
return False
def _get_vm_ipv6(self, vm):
nic = vm.TEMPLATE.get('NIC')
if isinstance(nic, dict):
nic = [nic]
for net in nic:
if net.get('IP6_GLOBAL'):
return net['IP6_GLOBAL']
return False
def _get_vm_pool(self):
auth = self._get_connection_info()
if not (auth.username and auth.password):
raise AnsibleError('API Credentials missing. Check OpenNebula inventory file.')
else:
one_client = pyone.OneServer(auth.url, session=auth.username + ':' + auth.password)
# get hosts (VMs)
try:
vm_pool = one_client.vmpool.infoextended(-2, -1, -1, 3)
except Exception as e:
raise AnsibleError("Something happened during XML-RPC call: {e}".format(e=to_native(e)))
return vm_pool
def _retrieve_servers(self, label_filter=None):
vm_pool = self._get_vm_pool()
result = []
# iterate over hosts
for vm in vm_pool.VM:
server = vm.USER_TEMPLATE
labels = []
if vm.USER_TEMPLATE.get('LABELS'):
labels = [s for s in vm.USER_TEMPLATE.get('LABELS') if s == ',' or s == '-' or s.isalnum() or s.isspace()]
labels = ''.join(labels)
labels = labels.replace(' ', '_')
labels = labels.replace('-', '_')
labels = labels.split(',')
# filter by label
if label_filter is not None:
if label_filter not in labels:
continue
server['name'] = vm.NAME
server['LABELS'] = labels
server['v4_first_ip'] = self._get_vm_ipv4(vm)
server['v6_first_ip'] = self._get_vm_ipv6(vm)
result.append(server)
return result
def _populate(self):
hostname_preference = self.get_option('hostname')
group_by_labels = self.get_option('group_by_labels')
# Add a top group 'one'
self.inventory.add_group(group='all')
filter_by_label = self.get_option('filter_by_label')
for server in self._retrieve_servers(filter_by_label):
# check for labels
if group_by_labels and server['LABELS']:
for label in server['LABELS']:
self.inventory.add_group(group=label)
self.inventory.add_host(host=server['name'], group=label)
self.inventory.add_host(host=server['name'], group='all')
for attribute, value in server.items():
self.inventory.set_variable(server['name'], attribute, value)
if hostname_preference != 'name':
self.inventory.set_variable(server['name'], 'ansible_host', server[hostname_preference])
if server.get('SSH_PORT'):
self.inventory.set_variable(server['name'], 'ansible_port', server['SSH_PORT'])
def parse(self, inventory, loader, path, cache=True):
if not HAS_PYONE:
raise AnsibleError('OpenNebula Inventory plugin requires pyone to work!')
super(InventoryModule, self).parse(inventory, loader, path)
self._read_config_data(path=path)
self._populate()

View File

@@ -119,12 +119,13 @@ compose:
import re
from ansible.module_utils.common._collections_compat import MutableMapping
from distutils.version import LooseVersion
from ansible.errors import AnsibleError
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable, Cacheable
from ansible.module_utils.six.moves.urllib.parse import urlencode
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
# 3rd party imports
try:
import requests

View File

@@ -9,7 +9,7 @@ __metaclass__ = type
DOCUMENTATION = r'''
name: scaleway
author:
- Remy Leone (@sieben)
- Remy Leone (@remyleone)
short_description: Scaleway inventory source
description:
- Get inventory hosts from Scaleway.

View File

@@ -0,0 +1,328 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
name: xen_orchestra
short_description: Xen Orchestra inventory source
version_added: 4.1.0
author:
- Dom Del Nano (@ddelnano) <ddelnano@gmail.com>
- Samori Gorse (@shinuza) <samorigorse@gmail.com>
requirements:
- websocket-client >= 1.0.0
description:
- Get inventory hosts from a Xen Orchestra deployment.
- 'Uses a configuration file as an inventory source, it must end in C(.xen_orchestra.yml) or C(.xen_orchestra.yaml).'
extends_documentation_fragment:
- constructed
- inventory_cache
options:
plugin:
description: The name of this plugin, it should always be set to C(community.general.xen_orchestra) for this plugin to recognize it as its own.
required: yes
choices: ['community.general.xen_orchestra']
type: str
api_host:
description:
- API host to XOA API.
- If the value is not specified in the inventory configuration, the value of environment variable C(ANSIBLE_XO_HOST) will be used instead.
type: str
env:
- name: ANSIBLE_XO_HOST
user:
description:
- Xen Orchestra user.
- If the value is not specified in the inventory configuration, the value of environment variable C(ANSIBLE_XO_USER) will be used instead.
required: yes
type: str
env:
- name: ANSIBLE_XO_USER
password:
description:
- Xen Orchestra password.
- If the value is not specified in the inventory configuration, the value of environment variable C(ANSIBLE_XO_PASSWORD) will be used instead.
required: yes
type: str
env:
- name: ANSIBLE_XO_PASSWORD
validate_certs:
description: Verify TLS certificate if using HTTPS.
type: boolean
default: true
use_ssl:
description: Use wss when connecting to the Xen Orchestra API
type: boolean
default: true
'''
EXAMPLES = '''
# file must be named xen_orchestra.yaml or xen_orchestra.yml
simple_config_file:
plugin: community.general.xen_orchestra
api_host: 192.168.1.255
user: xo
password: xo_pwd
validate_certs: true
use_ssl: true
groups:
kube_nodes: "'kube_node' in tags"
compose:
ansible_port: 2222
'''
import json
import ssl
from ansible.errors import AnsibleError
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable, Cacheable
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
# 3rd party imports
try:
HAS_WEBSOCKET = True
import websocket
from websocket import create_connection
if LooseVersion(websocket.__version__) <= LooseVersion('1.0.0'):
raise ImportError
except ImportError as e:
HAS_WEBSOCKET = False
HALTED = 'Halted'
PAUSED = 'Paused'
RUNNING = 'Running'
SUSPENDED = 'Suspended'
POWER_STATES = [RUNNING, HALTED, SUSPENDED, PAUSED]
HOST_GROUP = 'xo_hosts'
POOL_GROUP = 'xo_pools'
def clean_group_name(label):
return label.lower().replace(' ', '-').replace('-', '_')
class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
''' Host inventory parser for ansible using XenOrchestra as source. '''
NAME = 'community.general.xen_orchestra'
def __init__(self):
super(InventoryModule, self).__init__()
# from config
self.counter = -1
self.session = None
self.cache_key = None
self.use_cache = None
@property
def pointer(self):
self.counter += 1
return self.counter
def create_connection(self, xoa_api_host):
validate_certs = self.get_option('validate_certs')
use_ssl = self.get_option('use_ssl')
proto = 'wss' if use_ssl else 'ws'
sslopt = None if validate_certs else {'cert_reqs': ssl.CERT_NONE}
self.conn = create_connection(
'{0}://{1}/api/'.format(proto, xoa_api_host), sslopt=sslopt)
def login(self, user, password):
payload = {'id': self.pointer, 'jsonrpc': '2.0', 'method': 'session.signIn', 'params': {
'username': user, 'password': password}}
self.conn.send(json.dumps(payload))
result = json.loads(self.conn.recv())
if 'error' in result:
raise AnsibleError(
'Could not connect: {0}'.format(result['error']))
def get_object(self, name):
payload = {'id': self.pointer, 'jsonrpc': '2.0',
'method': 'xo.getAllObjects', 'params': {'filter': {'type': name}}}
self.conn.send(json.dumps(payload))
answer = json.loads(self.conn.recv())
if 'error' in answer:
raise AnsibleError(
'Could not request: {0}'.format(answer['error']))
return answer['result']
def _get_objects(self):
self.create_connection(self.xoa_api_host)
self.login(self.xoa_user, self.xoa_password)
return {
'vms': self.get_object('VM'),
'pools': self.get_object('pool'),
'hosts': self.get_object('host'),
}
def _apply_constructable(self, name, variables):
strict = self.get_option('strict')
self._add_host_to_composed_groups(self.get_option('groups'), variables, name, strict=strict)
self._add_host_to_keyed_groups(self.get_option('keyed_groups'), variables, name, strict=strict)
self._set_composite_vars(self.get_option('compose'), variables, name, strict=strict)
def _add_vms(self, vms, hosts, pools):
for uuid, vm in vms.items():
group = 'with_ip'
ip = vm.get('mainIpAddress')
entry_name = uuid
power_state = vm['power_state'].lower()
pool_name = self._pool_group_name_for_uuid(pools, vm['$poolId'])
host_name = self._host_group_name_for_uuid(hosts, vm['$container'])
self.inventory.add_host(entry_name)
# Grouping by power state
self.inventory.add_child(power_state, entry_name)
# Grouping by host
if host_name:
self.inventory.add_child(host_name, entry_name)
# Grouping by pool
if pool_name:
self.inventory.add_child(pool_name, entry_name)
# Grouping VMs with an IP together
if ip is None:
group = 'without_ip'
self.inventory.add_group(group)
self.inventory.add_child(group, entry_name)
# Adding meta
self.inventory.set_variable(entry_name, 'uuid', uuid)
self.inventory.set_variable(entry_name, 'ip', ip)
self.inventory.set_variable(entry_name, 'ansible_host', ip)
self.inventory.set_variable(entry_name, 'power_state', power_state)
self.inventory.set_variable(
entry_name, 'name_label', vm['name_label'])
self.inventory.set_variable(entry_name, 'type', vm['type'])
self.inventory.set_variable(
entry_name, 'cpus', vm['CPUs']['number'])
self.inventory.set_variable(entry_name, 'tags', vm['tags'])
self.inventory.set_variable(
entry_name, 'memory', vm['memory']['size'])
self.inventory.set_variable(
entry_name, 'has_ip', group == 'with_ip')
self.inventory.set_variable(
entry_name, 'is_managed', vm.get('managementAgentDetected', False))
self.inventory.set_variable(
entry_name, 'os_version', vm['os_version'])
self._apply_constructable(entry_name, self.inventory.get_host(entry_name).get_vars())
def _add_hosts(self, hosts, pools):
for host in hosts.values():
entry_name = host['uuid']
group_name = 'xo_host_{0}'.format(
clean_group_name(host['name_label']))
pool_name = self._pool_group_name_for_uuid(pools, host['$poolId'])
self.inventory.add_group(group_name)
self.inventory.add_host(entry_name)
self.inventory.add_child(HOST_GROUP, entry_name)
self.inventory.add_child(pool_name, entry_name)
self.inventory.set_variable(entry_name, 'enabled', host['enabled'])
self.inventory.set_variable(
entry_name, 'hostname', host['hostname'])
self.inventory.set_variable(entry_name, 'memory', host['memory'])
self.inventory.set_variable(entry_name, 'address', host['address'])
self.inventory.set_variable(entry_name, 'cpus', host['cpus'])
self.inventory.set_variable(entry_name, 'type', 'host')
self.inventory.set_variable(entry_name, 'tags', host['tags'])
self.inventory.set_variable(entry_name, 'version', host['version'])
self.inventory.set_variable(
entry_name, 'power_state', host['power_state'].lower())
self.inventory.set_variable(
entry_name, 'product_brand', host['productBrand'])
for pool in pools.values():
group_name = 'xo_pool_{0}'.format(
clean_group_name(pool['name_label']))
self.inventory.add_group(group_name)
def _add_pools(self, pools):
for pool in pools.values():
group_name = 'xo_pool_{0}'.format(
clean_group_name(pool['name_label']))
self.inventory.add_group(group_name)
# TODO: Refactor
def _pool_group_name_for_uuid(self, pools, pool_uuid):
for pool in pools:
if pool == pool_uuid:
return 'xo_pool_{0}'.format(
clean_group_name(pools[pool_uuid]['name_label']))
# TODO: Refactor
def _host_group_name_for_uuid(self, hosts, host_uuid):
for host in hosts:
if host == host_uuid:
return 'xo_host_{0}'.format(
clean_group_name(hosts[host_uuid]['name_label']
))
def _populate(self, objects):
# Prepare general groups
self.inventory.add_group(HOST_GROUP)
self.inventory.add_group(POOL_GROUP)
for group in POWER_STATES:
self.inventory.add_group(group.lower())
self._add_pools(objects['pools'])
self._add_hosts(objects['hosts'], objects['pools'])
self._add_vms(objects['vms'], objects['hosts'], objects['pools'])
def verify_file(self, path):
valid = False
if super(InventoryModule, self).verify_file(path):
if path.endswith(('xen_orchestra.yaml', 'xen_orchestra.yml')):
valid = True
else:
self.display.vvv(
'Skipping due to inventory source not ending in "xen_orchestra.yaml" nor "xen_orchestra.yml"')
return valid
def parse(self, inventory, loader, path, cache=True):
if not HAS_WEBSOCKET:
raise AnsibleError('This plugin requires websocket-client 1.0.0 or higher: '
'https://github.com/websocket-client/websocket-client.')
super(InventoryModule, self).parse(inventory, loader, path)
# read config from file, this sets 'options'
self._read_config_data(path)
self.inventory = inventory
self.protocol = 'wss'
self.xoa_api_host = self.get_option('api_host')
self.xoa_user = self.get_option('user')
self.xoa_password = self.get_option('password')
self.cache_key = self.get_cache_key(path)
self.use_cache = cache and self.get_option('cache')
self.validate_certs = self.get_option('validate_certs')
if not self.get_option('use_ssl'):
self.protocol = 'ws'
objects = self._get_objects()
self._populate(objects)

View File

@@ -0,0 +1,138 @@
# (c) 2021, Felix Fontein <felix@fontein.de>
# 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 = """
name: collection_version
author: Felix Fontein (@felixfontein)
version_added: "4.0.0"
short_description: Retrieves the version of an installed collection
description:
- This lookup allows to query the version of an installed collection, and to determine whether a
collection is installed at all.
- By default it returns C(none) for non-existing collections and C(*) for collections without a
version number. The latter should only happen in development environments, or when installing
a collection from git which has no version in its C(galaxy.yml). This behavior can be adjusted
by providing other values with I(result_not_found) and I(result_no_version).
options:
_terms:
description:
- The collections to look for.
- For example C(community.general).
type: list
elements: str
required: true
result_not_found:
description:
- The value to return when the collection could not be found.
- By default, C(none) is returned.
type: string
default: ~
result_no_version:
description:
- The value to return when the collection has no version number.
- This can happen for collections installed from git which do not have a version number
in C(galaxy.yml).
- By default, C(*) is returned.
type: string
default: '*'
"""
EXAMPLES = """
- name: Check version of community.general
ansible.builtin.debug:
msg: "community.general version {{ lookup('community.general.collection_version', 'community.general') }}"
"""
RETURN = """
_raw:
description:
- The version number of the collections listed as input.
- If a collection can not be found, it will return the value provided in I(result_not_found).
By default, this is C(none).
- If a collection can be found, but the version not identified, it will return the value provided in
I(result_no_version). By default, this is C(*). This can happen for collections installed
from git which do not have a version number in C(galaxy.yml).
type: list
elements: str
"""
import json
import os
import re
import yaml
from ansible.errors import AnsibleLookupError
from ansible.module_utils.compat.importlib import import_module
from ansible.plugins.lookup import LookupBase
FQCN_RE = re.compile(r'^[A-Za-z0-9_]+\.[A-Za-z0-9_]+$')
def load_collection_meta_manifest(manifest_path):
with open(manifest_path, 'rb') as f:
meta = json.load(f)
return {
'version': meta['collection_info']['version'],
}
def load_collection_meta_galaxy(galaxy_path, no_version='*'):
with open(galaxy_path, 'rb') as f:
meta = yaml.safe_load(f)
return {
'version': meta.get('version') or no_version,
}
def load_collection_meta(collection_pkg, no_version='*'):
path = os.path.dirname(collection_pkg.__file__)
# Try to load MANIFEST.json
manifest_path = os.path.join(path, 'MANIFEST.json')
if os.path.exists(manifest_path):
return load_collection_meta_manifest(manifest_path)
# Try to load galaxy.y(a)ml
galaxy_path = os.path.join(path, 'galaxy.yml')
galaxy_alt_path = os.path.join(path, 'galaxy.yaml')
# galaxy.yaml was only supported in ansible-base 2.10 and ansible-core 2.11. Support was removed
# in https://github.com/ansible/ansible/commit/595413d11346b6f26bb3d9df2d8e05f2747508a3 for
# ansible-core 2.12.
for path in (galaxy_path, galaxy_alt_path):
if os.path.exists(path):
return load_collection_meta_galaxy(path, no_version=no_version)
return {}
class LookupModule(LookupBase):
def run(self, terms, variables=None, **kwargs):
result = []
self.set_options(var_options=variables, direct=kwargs)
not_found = self.get_option('result_not_found')
no_version = self.get_option('result_no_version')
for term in terms:
if not FQCN_RE.match(term):
raise AnsibleLookupError('"{term}" is not a FQCN'.format(term=term))
try:
collection_pkg = import_module('ansible_collections.{fqcn}'.format(fqcn=term))
except ImportError:
# Collection not found
result.append(not_found)
continue
try:
data = load_collection_meta(collection_pkg, no_version=no_version)
except Exception as exc:
raise AnsibleLookupError('Error while loading metadata for {fqcn}: {error}'.format(fqcn=term, error=exc))
result.append(data.get('version', no_version))
return result

View File

@@ -93,7 +93,7 @@ DOCUMENTATION = '''
environment variable and keep I(endpoints), I(host), and I(port) unused.
seealso:
- module: community.general.etcd3
- ref: etcd_lookup
- ref: ansible_collections.community.general.etcd_lookup
description: The etcd v2 lookup.
requirements:

View File

@@ -23,7 +23,7 @@ DOCUMENTATION = '''
EXAMPLES = """
- name: "'unnest' all elements into single list"
ansible.builtin.debug:
msg: "all in one list {{lookup('community.general.flattened', [1,2,3,[5,6]], [a,b,c], [[5,6,1,3], [34,a,b,c]])}}"
msg: "all in one list {{lookup('community.general.flattened', [1,2,3,[5,6]], ['a','b','c'], [[5,6,1,3], [34,'a','b','c']])}}"
"""
RETURN = """

View File

@@ -1,126 +0,0 @@
# -*- coding: utf-8 -*-
#
# Copyright 2018 Red Hat | Ansible
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
---
author: Unknown (!UNKNOWN)
name: nios
short_description: Query Infoblox NIOS objects
deprecated:
why: Please install the infoblox.nios_modules collection and use the corresponding lookup from it.
alternative: infoblox.nios_modules.nios_lookup
removed_in: 5.0.0
description:
- Uses the Infoblox WAPI API to fetch NIOS specified objects. This lookup
supports adding additional keywords to filter the return data and specify
the desired set of returned fields.
requirements:
- infoblox-client
extends_documentation_fragment:
- community.general.nios
options:
_terms:
description: The name of the object to return from NIOS
required: True
return_fields:
description: The list of field names to return for the specified object.
filter:
description: a dict object that is used to filter the return objects
extattrs:
description: a dict object that is used to filter on extattrs
'''
EXAMPLES = """
- name: fetch all networkview objects
ansible.builtin.set_fact:
networkviews: "{{ lookup('community.general.nios', 'networkview',
provider={'host': 'nios01', 'username': 'admin', 'password': 'password'}) }}"
- name: fetch the default dns view
ansible.builtin.set_fact:
dns_views: "{{ lookup('community.general.nios', 'view', filter={'name': 'default'},
provider={'host': 'nios01', 'username': 'admin', 'password': 'password'}) }}"
# all of the examples below use credentials that are set using env variables
# export INFOBLOX_HOST=nios01
# export INFOBLOX_USERNAME=admin
# export INFOBLOX_PASSWORD=admin
- name: fetch all host records and include extended attributes
ansible.builtin.set_fact:
host_records: "{{ lookup('community.general.nios', 'record:host', return_fields=['extattrs', 'name', 'view', 'comment']}) }}"
- name: use env variables to pass credentials
ansible.builtin.set_fact:
networkviews: "{{ lookup('community.general.nios', 'networkview') }}"
- name: get a host record
ansible.builtin.set_fact:
host: "{{ lookup('community.general.nios', 'record:host', filter={'name': 'hostname.ansible.com'}) }}"
- name: get the authoritative zone from a non default dns view
ansible.builtin.set_fact:
host: "{{ lookup('community.general.nios', 'zone_auth', filter={'fqdn': 'ansible.com', 'view': 'ansible-dns'}) }}"
"""
RETURN = """
obj_type:
description:
- The object type specified in the terms argument
type: dictionary
contains:
obj_field:
description:
- One or more obj_type fields as specified by return_fields argument or
the default set of fields as per the object type
"""
from ansible.plugins.lookup import LookupBase
from ansible_collections.community.general.plugins.module_utils.net_tools.nios.api import WapiLookup
from ansible_collections.community.general.plugins.module_utils.net_tools.nios.api import normalize_extattrs, flatten_extattrs
from ansible.errors import AnsibleError
class LookupModule(LookupBase):
def run(self, terms, variables=None, **kwargs):
try:
obj_type = terms[0]
except IndexError:
raise AnsibleError('the object_type must be specified')
return_fields = kwargs.pop('return_fields', None)
filter_data = kwargs.pop('filter', {})
extattrs = normalize_extattrs(kwargs.pop('extattrs', {}))
provider = kwargs.pop('provider', {})
wapi = WapiLookup(provider)
res = wapi.get_object(obj_type, filter_data, return_fields=return_fields, extattrs=extattrs)
if res is not None:
for obj in res:
if 'extattrs' in obj:
obj['extattrs'] = flatten_extattrs(obj['extattrs'])
else:
res = []
return res

View File

@@ -1,105 +0,0 @@
# -*- coding: utf-8 -*-
#
# Copyright 2018 Red Hat | Ansible
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
---
author: Unknown (!UNKNOWN)
name: nios_next_ip
short_description: Return the next available IP address for a network
deprecated:
why: Please install the infoblox.nios_modules collection and use the corresponding lookup from it.
alternative: infoblox.nios_modules.nios_next_ip
removed_in: 5.0.0
description:
- Uses the Infoblox WAPI API to return the next available IP addresses
for a given network CIDR
requirements:
- infoblox-client
extends_documentation_fragment:
- community.general.nios
options:
_terms:
description: The CIDR network to retrieve the next addresses from
required: True
num:
description: The number of IP addresses to return
required: false
default: 1
exclude:
description: List of IP's that need to be excluded from returned IP addresses
required: false
'''
EXAMPLES = """
- name: return next available IP address for network 192.168.10.0/24
ansible.builtin.set_fact:
ipaddr: "{{ lookup('community.general.nios_next_ip', '192.168.10.0/24', provider={'host': 'nios01', 'username': 'admin', 'password': 'password'}) }}"
- name: return the next 3 available IP addresses for network 192.168.10.0/24
ansible.builtin.set_fact:
ipaddr: "{{ lookup('community.general.nios_next_ip', '192.168.10.0/24', num=3, provider={'host': 'nios01', 'username': 'admin', 'password': 'password'}) }}"
- name: return the next 3 available IP addresses for network 192.168.10.0/24 excluding ip addresses - ['192.168.10.1', '192.168.10.2']
ansible.builtin.set_fact:
ipaddr: "{{ lookup('community.general.nios_next_ip', '192.168.10.0/24', num=3, exclude=['192.168.10.1', '192.168.10.2'],
provider={'host': 'nios01', 'username': 'admin', 'password': 'password'}) }}"
"""
RETURN = """
_list:
description:
- The list of next IP addresses available
type: list
"""
from ansible.plugins.lookup import LookupBase
from ansible_collections.community.general.plugins.module_utils.net_tools.nios.api import WapiLookup
from ansible.module_utils.common.text.converters import to_text
from ansible.errors import AnsibleError
class LookupModule(LookupBase):
def run(self, terms, variables=None, **kwargs):
try:
network = terms[0]
except IndexError:
raise AnsibleError('missing argument in the form of A.B.C.D/E')
provider = kwargs.pop('provider', {})
wapi = WapiLookup(provider)
network_obj = wapi.get_object('network', {'network': network})
if network_obj is None:
raise AnsibleError('unable to find network object %s' % network)
num = kwargs.get('num', 1)
exclude_ip = kwargs.get('exclude', [])
try:
ref = network_obj[0]['_ref']
avail_ips = wapi.call_func('next_available_ip', ref, {'num': num, 'exclude': exclude_ip})
return [avail_ips['ips']]
except Exception as exc:
raise AnsibleError(to_text(exc))

View File

@@ -1,118 +0,0 @@
# -*- coding: utf-8 -*-
#
# Copyright 2018 Red Hat | Ansible
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
---
author: Unknown (!UNKNOWN)
name: nios_next_network
short_description: Return the next available network range for a network-container
deprecated:
why: Please install the infoblox.nios_modules collection and use the corresponding lookup from it.
alternative: infoblox.nios_modules.nios_next_network
removed_in: 5.0.0
description:
- Uses the Infoblox WAPI API to return the next available network addresses for
a given network CIDR
requirements:
- infoblox_client
extends_documentation_fragment:
- community.general.nios
options:
_terms:
description: The CIDR network to retrieve the next network from next available network within the specified
container.
required: True
cidr:
description:
- The CIDR of the network to retrieve the next network from next available network within the
specified container. Also, Requested CIDR must be specified and greater than the parent CIDR.
required: True
default: 24
num:
description: The number of network addresses to return from network-container
required: false
default: 1
exclude:
description: Network addresses returned from network-container excluding list of user's input network range
required: false
default: ''
'''
EXAMPLES = """
- name: return next available network for network-container 192.168.10.0/24
ansible.builtin.set_fact:
networkaddr: "{{ lookup('community.general.nios_next_network', '192.168.10.0/24', cidr=25,
provider={'host': 'nios01', 'username': 'admin', 'password': 'password'}) }}"
- name: return the next 2 available network addresses for network-container 192.168.10.0/24
ansible.builtin.set_fact:
networkaddr: "{{ lookup('community.general.nios_next_network', '192.168.10.0/24', cidr=25, num=2,
provider={'host': 'nios01', 'username': 'admin', 'password': 'password'}) }}"
- name: return the available network addresses for network-container 192.168.10.0/24 excluding network range '192.168.10.0/25'
ansible.builtin.set_fact:
networkaddr: "{{ lookup('community.general.nios_next_network', '192.168.10.0/24', cidr=25, exclude=['192.168.10.0/25'],
provider={'host': 'nios01', 'username': 'admin', 'password': 'password'}) }}"
"""
RETURN = """
_list:
description:
- The list of next network addresses available
type: list
"""
from ansible.plugins.lookup import LookupBase
from ansible_collections.community.general.plugins.module_utils.net_tools.nios.api import WapiLookup
from ansible.module_utils.common.text.converters import to_text
from ansible.errors import AnsibleError
class LookupModule(LookupBase):
def run(self, terms, variables=None, **kwargs):
try:
network = terms[0]
except IndexError:
raise AnsibleError('missing network argument in the form of A.B.C.D/E')
try:
cidr = kwargs.get('cidr', 24)
except IndexError:
raise AnsibleError('missing CIDR argument in the form of xx')
provider = kwargs.pop('provider', {})
wapi = WapiLookup(provider)
network_obj = wapi.get_object('networkcontainer', {'network': network})
if network_obj is None:
raise AnsibleError('unable to find network-container object %s' % network)
num = kwargs.get('num', 1)
exclude_ip = kwargs.get('exclude', [])
try:
ref = network_obj[0]['_ref']
avail_nets = wapi.call_func('next_available_network', ref, {'cidr': cidr, 'num': num, 'exclude': exclude_ip})
return [avail_nets['networks']]
except Exception as exc:
raise AnsibleError(to_text(exc))

View File

@@ -141,9 +141,9 @@ import time
import yaml
from distutils import util
from ansible.errors import AnsibleError, AnsibleAssertionError
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
from ansible.module_utils.parsing.convert_bool import boolean
from ansible.utils.display import Display
from ansible.utils.encrypt import random_password
from ansible.plugins.lookup import LookupBase
@@ -211,7 +211,7 @@ class LookupModule(LookupBase):
try:
for key in ['create', 'returnall', 'overwrite', 'backup', 'nosymbols']:
if not isinstance(self.paramvals[key], bool):
self.paramvals[key] = util.strtobool(self.paramvals[key])
self.paramvals[key] = boolean(self.paramvals[key])
except (ValueError, AssertionError) as e:
raise AnsibleError(e)
if self.paramvals['missing'] not in ['error', 'warn', 'create', 'empty']:

View File

@@ -0,0 +1,119 @@
# -*- coding: utf-8 -*-
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
"""The community.general.random_words Ansible lookup plugin."""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = r"""
name: random_words
author:
- Thomas Sjögren (@konstruktoid)
short_description: Return a number of random words
version_added: "4.0.0"
requirements:
- xkcdpass U(https://github.com/redacted/XKCD-password-generator)
description:
- Returns a number of random words. The output can for example be used for
passwords.
- See U(https://xkcd.com/936/) for background.
options:
numwords:
description:
- The number of words.
default: 6
type: int
min_length:
description:
- Minimum length of words to make password.
default: 5
type: int
max_length:
description:
- Maximum length of words to make password.
default: 9
type: int
delimiter:
description:
- The delimiter character between words.
default: " "
type: str
case:
description:
- The method for setting the case of each word in the passphrase.
choices: ["alternating", "upper", "lower", "random", "capitalize"]
default: "lower"
type: str
"""
EXAMPLES = r"""
- name: Generate password with default settings
ansible.builtin.debug:
var: lookup('community.general.random_words')
# Example result: 'traitor gigabyte cesarean unless aspect clear'
- name: Generate password with six, five character, words
ansible.builtin.debug:
var: lookup('community.general.random_words', min_length=5, max_length=5)
# Example result: 'brink banjo getup staff trump comfy'
- name: Generate password with three capitalized words and the '-' delimiter
ansible.builtin.debug:
var: lookup('community.general.random_words', numwords=3, delimiter='-', case='capitalize')
# Example result: 'Overlabor-Faucet-Coastline'
- name: Generate password with three words without any delimiter
ansible.builtin.debug:
var: lookup('community.general.random_words', numwords=3, delimiter='')
# Example result: 'deskworkmonopolystriking'
# https://www.ncsc.gov.uk/blog-post/the-logic-behind-three-random-words
"""
RETURN = r"""
_raw:
description: A single-element list containing random words.
type: list
elements: str
"""
from ansible.errors import AnsibleLookupError
from ansible.plugins.lookup import LookupBase
try:
from xkcdpass import xkcd_password as xp
HAS_XKCDPASS = True
except ImportError:
HAS_XKCDPASS = False
class LookupModule(LookupBase):
"""The random_words Ansible lookup class."""
def run(self, terms, variables=None, **kwargs):
if not HAS_XKCDPASS:
raise AnsibleLookupError(
"Python xkcdpass library is required. "
'Please install using "pip install xkcdpass"'
)
self.set_options(var_options=variables, direct=kwargs)
method = self.get_option("case")
delimiter = self.get_option("delimiter")
max_length = self.get_option("max_length")
min_length = self.get_option("min_length")
numwords = self.get_option("numwords")
words = xp.locate_wordfile()
wordlist = xp.generate_wordlist(
max_length=max_length, min_length=min_length, wordfile=words
)
values = xp.generate_xkcdpassword(
wordlist, case=method, delimiter=delimiter, numwords=numwords
)
return [values]

View File

@@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2021, RevBits <info@revbits.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 = r"""
name: revbitspss
author: RevBits (@RevBits) <info@revbits.com>
short_description: Get secrets from RevBits PAM server
version_added: 4.1.0
description:
- Uses the revbits_ansible Python SDK to get Secrets from RevBits PAM
Server using API key authentication with the REST API.
requirements:
- revbits_ansible - U(https://pypi.org/project/revbits_ansible/)
options:
_terms:
description:
- This will be an array of keys for secrets which you want to fetch from RevBits PAM.
required: true
type: list
elements: string
base_url:
description:
- This will be the base URL of the server, for example C(https://server-url-here).
required: true
type: string
api_key:
description:
- This will be the API key for authentication. You can get it from the RevBits PAM secret manager module.
required: true
type: string
"""
RETURN = r"""
_list:
description:
- The JSON responses which you can access with defined keys.
- If you are fetching secrets named as UUID, PASSWORD it will gives you the dict of all secrets.
type: list
elements: dict
"""
EXAMPLES = r"""
- hosts: localhost
vars:
secret: >-
{{
lookup(
'community.general.revbitspss',
'UUIDPAM', 'DB_PASS',
base_url='https://server-url-here',
api_key='API_KEY_GOES_HERE'
)
}}
tasks:
- ansible.builtin.debug:
msg: >
UUIDPAM is {{ (secret['UUIDPAM']) }} and DB_PASS is {{ (secret['DB_PASS']) }}
"""
from ansible.plugins.lookup import LookupBase
from ansible.utils.display import Display
from ansible.errors import AnsibleError
from ansible.module_utils.six import raise_from
try:
from pam.revbits_ansible.server import SecretServer
except ImportError as imp_exc:
ANOTHER_LIBRARY_IMPORT_ERROR = imp_exc
else:
ANOTHER_LIBRARY_IMPORT_ERROR = None
display = Display()
class LookupModule(LookupBase):
@staticmethod
def Client(server_parameters):
return SecretServer(**server_parameters)
def run(self, terms, variables, **kwargs):
if ANOTHER_LIBRARY_IMPORT_ERROR:
raise_from(
AnsibleError('revbits_ansible must be installed to use this plugin'),
ANOTHER_LIBRARY_IMPORT_ERROR
)
self.set_options(var_options=variables, direct=kwargs)
secret_server = LookupModule.Client(
{
"base_url": self.get_option('base_url'),
"api_key": self.get_option('api_key'),
}
)
result = []
for term in terms:
try:
display.vvv(u"Secret Server lookup of Secret with ID %s" % term)
result.append({term: secret_server.get_pam_secret(term)})
except Exception as error:
raise AnsibleError("Secret Server lookup failure: %s" % error.message)
return result

View File

@@ -1,748 +0,0 @@
# -*- coding: utf-8 -*-
# This code is part of Ansible, but is an independent component.
# This particular file snippet, and this file snippet only, is BSD licensed.
# Modules you write using this snippet, which is embedded dynamically by Ansible
# still belong to the author of the module, and may assign their own license
# to the complete work.
#
# Copyright (c) 2017, Sumit Kumar <sumit4@netapp.com>
# Copyright (c) 2017, Michael Price <michael.price@netapp.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import json
import os
import random
import mimetypes
from pprint import pformat
from ansible.module_utils import six
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
from ansible.module_utils.six.moves.urllib.error import HTTPError, URLError
from ansible.module_utils.urls import open_url
from ansible.module_utils.api import basic_auth_argument_spec
from ansible.module_utils.common.text.converters import to_native
try:
from ansible.module_utils.ansible_release import __version__ as ansible_version
except ImportError:
ansible_version = 'unknown'
try:
from netapp_lib.api.zapi import zapi
HAS_NETAPP_LIB = True
except ImportError:
HAS_NETAPP_LIB = False
try:
import requests
HAS_REQUESTS = True
except ImportError:
HAS_REQUESTS = False
import ssl
try:
from urlparse import urlparse, urlunparse
except ImportError:
from urllib.parse import urlparse, urlunparse
HAS_SF_SDK = False
SF_BYTE_MAP = dict(
# Management GUI displays 1024 ** 3 as 1.1 GB, thus use 1000.
bytes=1,
b=1,
kb=1000,
mb=1000 ** 2,
gb=1000 ** 3,
tb=1000 ** 4,
pb=1000 ** 5,
eb=1000 ** 6,
zb=1000 ** 7,
yb=1000 ** 8
)
POW2_BYTE_MAP = dict(
# Here, 1 kb = 1024
bytes=1,
b=1,
kb=1024,
mb=1024 ** 2,
gb=1024 ** 3,
tb=1024 ** 4,
pb=1024 ** 5,
eb=1024 ** 6,
zb=1024 ** 7,
yb=1024 ** 8
)
try:
from solidfire.factory import ElementFactory
from solidfire.custom.models import TimeIntervalFrequency
from solidfire.models import Schedule, ScheduleInfo
HAS_SF_SDK = True
except Exception:
HAS_SF_SDK = False
def has_netapp_lib():
return HAS_NETAPP_LIB
def has_sf_sdk():
return HAS_SF_SDK
def na_ontap_host_argument_spec():
return dict(
hostname=dict(required=True, type='str'),
username=dict(required=True, type='str', aliases=['user']),
password=dict(required=True, type='str', aliases=['pass'], no_log=True),
https=dict(required=False, type='bool', default=False),
validate_certs=dict(required=False, type='bool', default=True),
http_port=dict(required=False, type='int'),
ontapi=dict(required=False, type='int'),
use_rest=dict(required=False, type='str', default='Auto', choices=['Never', 'Always', 'Auto'])
)
def ontap_sf_host_argument_spec():
return dict(
hostname=dict(required=True, type='str'),
username=dict(required=True, type='str', aliases=['user']),
password=dict(required=True, type='str', aliases=['pass'], no_log=True)
)
def aws_cvs_host_argument_spec():
return dict(
api_url=dict(required=True, type='str'),
validate_certs=dict(required=False, type='bool', default=True),
api_key=dict(required=True, type='str', no_log=True),
secret_key=dict(required=True, type='str', no_log=True)
)
def create_sf_connection(module, port=None):
hostname = module.params['hostname']
username = module.params['username']
password = module.params['password']
if HAS_SF_SDK and hostname and username and password:
try:
return_val = ElementFactory.create(hostname, username, password, port=port)
return return_val
except Exception:
raise Exception("Unable to create SF connection")
else:
module.fail_json(msg="the python SolidFire SDK module is required")
def setup_na_ontap_zapi(module, vserver=None):
hostname = module.params['hostname']
username = module.params['username']
password = module.params['password']
https = module.params['https']
validate_certs = module.params['validate_certs']
port = module.params['http_port']
version = module.params['ontapi']
if HAS_NETAPP_LIB:
# set up zapi
server = zapi.NaServer(hostname)
server.set_username(username)
server.set_password(password)
if vserver:
server.set_vserver(vserver)
if version:
minor = version
else:
minor = 110
server.set_api_version(major=1, minor=minor)
# default is HTTP
if https:
if port is None:
port = 443
transport_type = 'HTTPS'
# HACK to bypass certificate verification
if validate_certs is False:
if not os.environ.get('PYTHONHTTPSVERIFY', '') and getattr(ssl, '_create_unverified_context', None):
ssl._create_default_https_context = ssl._create_unverified_context
else:
if port is None:
port = 80
transport_type = 'HTTP'
server.set_transport_type(transport_type)
server.set_port(port)
server.set_server_type('FILER')
return server
else:
module.fail_json(msg="the python NetApp-Lib module is required")
def setup_ontap_zapi(module, vserver=None):
hostname = module.params['hostname']
username = module.params['username']
password = module.params['password']
if HAS_NETAPP_LIB:
# set up zapi
server = zapi.NaServer(hostname)
server.set_username(username)
server.set_password(password)
if vserver:
server.set_vserver(vserver)
# Todo : Replace hard-coded values with configurable parameters.
server.set_api_version(major=1, minor=110)
server.set_port(80)
server.set_server_type('FILER')
server.set_transport_type('HTTP')
return server
else:
module.fail_json(msg="the python NetApp-Lib module is required")
def eseries_host_argument_spec():
"""Retrieve a base argument specification common to all NetApp E-Series modules"""
argument_spec = basic_auth_argument_spec()
argument_spec.update(dict(
api_username=dict(type='str', required=True),
api_password=dict(type='str', required=True, no_log=True),
api_url=dict(type='str', required=True),
ssid=dict(type='str', required=False, default='1'),
validate_certs=dict(type='bool', required=False, default=True)
))
return argument_spec
class NetAppESeriesModule(object):
"""Base class for all NetApp E-Series modules.
Provides a set of common methods for NetApp E-Series modules, including version checking, mode (proxy, embedded)
verification, http requests, secure http redirection for embedded web services, and logging setup.
Be sure to add the following lines in the module's documentation section:
extends_documentation_fragment:
- netapp.eseries
:param dict(dict) ansible_options: dictionary of ansible option definitions
:param str web_services_version: minimally required web services rest api version (default value: "02.00.0000.0000")
:param bool supports_check_mode: whether the module will support the check_mode capabilities (default=False)
:param list(list) mutually_exclusive: list containing list(s) of mutually exclusive options (optional)
:param list(list) required_if: list containing list(s) containing the option, the option value, and then
a list of required options. (optional)
:param list(list) required_one_of: list containing list(s) of options for which at least one is required. (optional)
:param list(list) required_together: list containing list(s) of options that are required together. (optional)
:param bool log_requests: controls whether to log each request (default: True)
"""
DEFAULT_TIMEOUT = 60
DEFAULT_SECURE_PORT = "8443"
DEFAULT_REST_API_PATH = "devmgr/v2/"
DEFAULT_REST_API_ABOUT_PATH = "devmgr/utils/about"
DEFAULT_HEADERS = {"Content-Type": "application/json", "Accept": "application/json",
"netapp-client-type": "Ansible-%s" % ansible_version}
HTTP_AGENT = "Ansible / %s" % ansible_version
SIZE_UNIT_MAP = dict(bytes=1, b=1, kb=1024, mb=1024**2, gb=1024**3, tb=1024**4,
pb=1024**5, eb=1024**6, zb=1024**7, yb=1024**8)
def __init__(self, ansible_options, web_services_version=None, supports_check_mode=False,
mutually_exclusive=None, required_if=None, required_one_of=None, required_together=None,
log_requests=True):
argument_spec = eseries_host_argument_spec()
argument_spec.update(ansible_options)
self.module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=supports_check_mode,
mutually_exclusive=mutually_exclusive, required_if=required_if,
required_one_of=required_one_of, required_together=required_together)
args = self.module.params
self.web_services_version = web_services_version if web_services_version else "02.00.0000.0000"
self.ssid = args["ssid"]
self.url = args["api_url"]
self.log_requests = log_requests
self.creds = dict(url_username=args["api_username"],
url_password=args["api_password"],
validate_certs=args["validate_certs"])
if not self.url.endswith("/"):
self.url += "/"
self.is_embedded_mode = None
self.is_web_services_valid_cache = None
def _check_web_services_version(self):
"""Verify proxy or embedded web services meets minimum version required for module.
The minimum required web services version is evaluated against version supplied through the web services rest
api. AnsibleFailJson exception will be raised when the minimum is not met or exceeded.
This helper function will update the supplied api url if secure http is not used for embedded web services
:raise AnsibleFailJson: raised when the contacted api service does not meet the minimum required version.
"""
if not self.is_web_services_valid_cache:
url_parts = urlparse(self.url)
if not url_parts.scheme or not url_parts.netloc:
self.module.fail_json(msg="Failed to provide valid API URL. Example: https://192.168.1.100:8443/devmgr/v2. URL [%s]." % self.url)
if url_parts.scheme not in ["http", "https"]:
self.module.fail_json(msg="Protocol must be http or https. URL [%s]." % self.url)
self.url = "%s://%s/" % (url_parts.scheme, url_parts.netloc)
about_url = self.url + self.DEFAULT_REST_API_ABOUT_PATH
rc, data = request(about_url, timeout=self.DEFAULT_TIMEOUT, headers=self.DEFAULT_HEADERS, ignore_errors=True, **self.creds)
if rc != 200:
self.module.warn("Failed to retrieve web services about information! Retrying with secure ports. Array Id [%s]." % self.ssid)
self.url = "https://%s:8443/" % url_parts.netloc.split(":")[0]
about_url = self.url + self.DEFAULT_REST_API_ABOUT_PATH
try:
rc, data = request(about_url, timeout=self.DEFAULT_TIMEOUT, headers=self.DEFAULT_HEADERS, **self.creds)
except Exception as error:
self.module.fail_json(msg="Failed to retrieve the webservices about information! Array Id [%s]. Error [%s]."
% (self.ssid, to_native(error)))
major, minor, other, revision = data["version"].split(".")
minimum_major, minimum_minor, other, minimum_revision = self.web_services_version.split(".")
if not (major > minimum_major or
(major == minimum_major and minor > minimum_minor) or
(major == minimum_major and minor == minimum_minor and revision >= minimum_revision)):
self.module.fail_json(msg="Web services version does not meet minimum version required. Current version: [%s]."
" Version required: [%s]." % (data["version"], self.web_services_version))
self.module.log("Web services rest api version met the minimum required version.")
self.is_web_services_valid_cache = True
def is_embedded(self):
"""Determine whether web services server is the embedded web services.
If web services about endpoint fails based on an URLError then the request will be attempted again using
secure http.
:raise AnsibleFailJson: raised when web services about endpoint failed to be contacted.
:return bool: whether contacted web services is running from storage array (embedded) or from a proxy.
"""
self._check_web_services_version()
if self.is_embedded_mode is None:
about_url = self.url + self.DEFAULT_REST_API_ABOUT_PATH
try:
rc, data = request(about_url, timeout=self.DEFAULT_TIMEOUT, headers=self.DEFAULT_HEADERS, **self.creds)
self.is_embedded_mode = not data["runningAsProxy"]
except Exception as error:
self.module.fail_json(msg="Failed to retrieve the webservices about information! Array Id [%s]. Error [%s]."
% (self.ssid, to_native(error)))
return self.is_embedded_mode
def request(self, path, data=None, method='GET', headers=None, ignore_errors=False):
"""Issue an HTTP request to a url, retrieving an optional JSON response.
:param str path: web services rest api endpoint path (Example: storage-systems/1/graph). Note that when the
full url path is specified then that will be used without supplying the protocol, hostname, port and rest path.
:param data: data required for the request (data may be json or any python structured data)
:param str method: request method such as GET, POST, DELETE.
:param dict headers: dictionary containing request headers.
:param bool ignore_errors: forces the request to ignore any raised exceptions.
"""
self._check_web_services_version()
if headers is None:
headers = self.DEFAULT_HEADERS
if not isinstance(data, str) and headers["Content-Type"] == "application/json":
data = json.dumps(data)
if path.startswith("/"):
path = path[1:]
request_url = self.url + self.DEFAULT_REST_API_PATH + path
# if self.log_requests:
self.module.log(pformat(dict(url=request_url, data=data, method=method)))
return request(url=request_url, data=data, method=method, headers=headers, use_proxy=True, force=False, last_mod_time=None,
timeout=self.DEFAULT_TIMEOUT, http_agent=self.HTTP_AGENT, force_basic_auth=True, ignore_errors=ignore_errors, **self.creds)
def create_multipart_formdata(files, fields=None, send_8kb=False):
"""Create the data for a multipart/form request.
:param list(list) files: list of lists each containing (name, filename, path).
:param list(list) fields: list of lists each containing (key, value).
:param bool send_8kb: only sends the first 8kb of the files (default: False).
"""
boundary = "---------------------------" + "".join([str(random.randint(0, 9)) for x in range(27)])
data_parts = list()
data = None
if six.PY2: # Generate payload for Python 2
newline = "\r\n"
if fields is not None:
for key, value in fields:
data_parts.extend(["--%s" % boundary,
'Content-Disposition: form-data; name="%s"' % key,
"",
value])
for name, filename, path in files:
with open(path, "rb") as fh:
value = fh.read(8192) if send_8kb else fh.read()
data_parts.extend(["--%s" % boundary,
'Content-Disposition: form-data; name="%s"; filename="%s"' % (name, filename),
"Content-Type: %s" % (mimetypes.guess_type(path)[0] or "application/octet-stream"),
"",
value])
data_parts.extend(["--%s--" % boundary, ""])
data = newline.join(data_parts)
else:
newline = six.b("\r\n")
if fields is not None:
for key, value in fields:
data_parts.extend([six.b("--%s" % boundary),
six.b('Content-Disposition: form-data; name="%s"' % key),
six.b(""),
six.b(value)])
for name, filename, path in files:
with open(path, "rb") as fh:
value = fh.read(8192) if send_8kb else fh.read()
data_parts.extend([six.b("--%s" % boundary),
six.b('Content-Disposition: form-data; name="%s"; filename="%s"' % (name, filename)),
six.b("Content-Type: %s" % (mimetypes.guess_type(path)[0] or "application/octet-stream")),
six.b(""),
value])
data_parts.extend([six.b("--%s--" % boundary), b""])
data = newline.join(data_parts)
headers = {
"Content-Type": "multipart/form-data; boundary=%s" % boundary,
"Content-Length": str(len(data))}
return headers, data
def request(url, data=None, headers=None, method='GET', use_proxy=True,
force=False, last_mod_time=None, timeout=10, validate_certs=True,
url_username=None, url_password=None, http_agent=None, force_basic_auth=True, ignore_errors=False):
"""Issue an HTTP request to a url, retrieving an optional JSON response."""
if headers is None:
headers = {"Content-Type": "application/json", "Accept": "application/json"}
headers.update({"netapp-client-type": "Ansible-%s" % ansible_version})
if not http_agent:
http_agent = "Ansible / %s" % ansible_version
try:
r = open_url(url=url, data=data, headers=headers, method=method, use_proxy=use_proxy,
force=force, last_mod_time=last_mod_time, timeout=timeout, validate_certs=validate_certs,
url_username=url_username, url_password=url_password, http_agent=http_agent,
force_basic_auth=force_basic_auth)
except HTTPError as err:
r = err.fp
try:
raw_data = r.read()
if raw_data:
data = json.loads(raw_data)
else:
raw_data = None
except Exception:
if ignore_errors:
pass
else:
raise Exception(raw_data)
resp_code = r.getcode()
if resp_code >= 400 and not ignore_errors:
raise Exception(resp_code, data)
else:
return resp_code, data
def ems_log_event(source, server, name="Ansible", id="12345", version=ansible_version,
category="Information", event="setup", autosupport="false"):
ems_log = zapi.NaElement('ems-autosupport-log')
# Host name invoking the API.
ems_log.add_new_child("computer-name", name)
# ID of event. A user defined event-id, range [0..2^32-2].
ems_log.add_new_child("event-id", id)
# Name of the application invoking the API.
ems_log.add_new_child("event-source", source)
# Version of application invoking the API.
ems_log.add_new_child("app-version", version)
# Application defined category of the event.
ems_log.add_new_child("category", category)
# Description of event to log. An application defined message to log.
ems_log.add_new_child("event-description", event)
ems_log.add_new_child("log-level", "6")
ems_log.add_new_child("auto-support", autosupport)
server.invoke_successfully(ems_log, True)
def get_cserver_zapi(server):
vserver_info = zapi.NaElement('vserver-get-iter')
query_details = zapi.NaElement.create_node_with_children('vserver-info', **{'vserver-type': 'admin'})
query = zapi.NaElement('query')
query.add_child_elem(query_details)
vserver_info.add_child_elem(query)
result = server.invoke_successfully(vserver_info,
enable_tunneling=False)
attribute_list = result.get_child_by_name('attributes-list')
vserver_list = attribute_list.get_child_by_name('vserver-info')
return vserver_list.get_child_content('vserver-name')
def get_cserver(connection, is_rest=False):
if not is_rest:
return get_cserver_zapi(connection)
params = {'fields': 'type'}
api = "private/cli/vserver"
json, error = connection.get(api, params)
if json is None or error is not None:
# exit if there is an error or no data
return None
vservers = json.get('records')
if vservers is not None:
for vserver in vservers:
if vserver['type'] == 'admin': # cluster admin
return vserver['vserver']
if len(vservers) == 1: # assume vserver admin
return vservers[0]['vserver']
return None
class OntapRestAPI(object):
def __init__(self, module, timeout=60):
self.module = module
self.username = self.module.params['username']
self.password = self.module.params['password']
self.hostname = self.module.params['hostname']
self.use_rest = self.module.params['use_rest']
self.verify = self.module.params['validate_certs']
self.timeout = timeout
self.url = 'https://' + self.hostname + '/api/'
self.errors = list()
self.debug_logs = list()
self.check_required_library()
def check_required_library(self):
if not HAS_REQUESTS:
self.module.fail_json(msg=missing_required_lib('requests'))
def send_request(self, method, api, params, json=None, return_status_code=False):
''' send http request and process reponse, including error conditions '''
url = self.url + api
status_code = None
content = None
json_dict = None
json_error = None
error_details = None
def get_json(response):
''' extract json, and error message if present '''
try:
json = response.json()
except ValueError:
return None, None
error = json.get('error')
return json, error
try:
response = requests.request(method, url, verify=self.verify, auth=(self.username, self.password), params=params, timeout=self.timeout, json=json)
content = response.content # for debug purposes
status_code = response.status_code
# If the response was successful, no Exception will be raised
response.raise_for_status()
json_dict, json_error = get_json(response)
except requests.exceptions.HTTPError as err:
__, json_error = get_json(response)
if json_error is None:
self.log_error(status_code, 'HTTP error: %s' % err)
error_details = str(err)
# If an error was reported in the json payload, it is handled below
except requests.exceptions.ConnectionError as err:
self.log_error(status_code, 'Connection error: %s' % err)
error_details = str(err)
except Exception as err:
self.log_error(status_code, 'Other error: %s' % err)
error_details = str(err)
if json_error is not None:
self.log_error(status_code, 'Endpoint error: %d: %s' % (status_code, json_error))
error_details = json_error
self.log_debug(status_code, content)
if return_status_code:
return status_code, error_details
return json_dict, error_details
def get(self, api, params):
method = 'GET'
return self.send_request(method, api, params)
def post(self, api, data, params=None):
method = 'POST'
return self.send_request(method, api, params, json=data)
def patch(self, api, data, params=None):
method = 'PATCH'
return self.send_request(method, api, params, json=data)
def delete(self, api, data, params=None):
method = 'DELETE'
return self.send_request(method, api, params, json=data)
def _is_rest(self, used_unsupported_rest_properties=None):
if self.use_rest == "Always":
if used_unsupported_rest_properties:
error = "REST API currently does not support '%s'" % \
', '.join(used_unsupported_rest_properties)
return True, error
else:
return True, None
if self.use_rest == 'Never' or used_unsupported_rest_properties:
# force ZAPI if requested or if some parameter requires it
return False, None
method = 'HEAD'
api = 'cluster/software'
status_code, __ = self.send_request(method, api, params=None, return_status_code=True)
if status_code == 200:
return True, None
return False, None
def is_rest(self, used_unsupported_rest_properties=None):
''' only return error if there is a reason to '''
use_rest, error = self._is_rest(used_unsupported_rest_properties)
if used_unsupported_rest_properties is None:
return use_rest
return use_rest, error
def log_error(self, status_code, message):
self.errors.append(message)
self.debug_logs.append((status_code, message))
def log_debug(self, status_code, content):
self.debug_logs.append((status_code, content))
class AwsCvsRestAPI(object):
def __init__(self, module, timeout=60):
self.module = module
self.api_key = self.module.params['api_key']
self.secret_key = self.module.params['secret_key']
self.api_url = self.module.params['api_url']
self.verify = self.module.params['validate_certs']
self.timeout = timeout
self.url = 'https://' + self.api_url + '/v1/'
self.check_required_library()
def check_required_library(self):
if not HAS_REQUESTS:
self.module.fail_json(msg=missing_required_lib('requests'))
def send_request(self, method, api, params, json=None):
''' send http request and process reponse, including error conditions '''
url = self.url + api
status_code = None
content = None
json_dict = None
json_error = None
error_details = None
headers = {
'Content-type': "application/json",
'api-key': self.api_key,
'secret-key': self.secret_key,
'Cache-Control': "no-cache",
}
def get_json(response):
''' extract json, and error message if present '''
try:
json = response.json()
except ValueError:
return None, None
success_code = [200, 201, 202]
if response.status_code not in success_code:
error = json.get('message')
else:
error = None
return json, error
try:
response = requests.request(method, url, headers=headers, timeout=self.timeout, json=json)
status_code = response.status_code
# If the response was successful, no Exception will be raised
json_dict, json_error = get_json(response)
except requests.exceptions.HTTPError as err:
__, json_error = get_json(response)
if json_error is None:
error_details = str(err)
except requests.exceptions.ConnectionError as err:
error_details = str(err)
except Exception as err:
error_details = str(err)
if json_error is not None:
error_details = json_error
return json_dict, error_details
# If an error was reported in the json payload, it is handled below
def get(self, api, params=None):
method = 'GET'
return self.send_request(method, api, params)
def post(self, api, data, params=None):
method = 'POST'
return self.send_request(method, api, params, json=data)
def patch(self, api, data, params=None):
method = 'PATCH'
return self.send_request(method, api, params, json=data)
def put(self, api, data, params=None):
method = 'PUT'
return self.send_request(method, api, params, json=data)
def delete(self, api, data, params=None):
method = 'DELETE'
return self.send_request(method, api, params, json=data)
def get_state(self, jobId):
""" Method to get the state of the job """
method = 'GET'
response, status_code = self.get('Jobs/%s' % jobId)
while str(response['state']) not in 'done':
response, status_code = self.get('Jobs/%s' % jobId)
return 'done'

View File

@@ -0,0 +1,343 @@
# Vendored copy of distutils/version.py from CPython 3.9.5
#
# Implements multiple version numbering conventions for the
# Python Module Distribution Utilities.
#
# PSF License (see licenses/PSF-license.txt or https://opensource.org/licenses/Python-2.0)
#
"""Provides classes to represent module version numbers (one class for
each style of version numbering). There are currently two such classes
implemented: StrictVersion and LooseVersion.
Every version number class implements the following interface:
* the 'parse' method takes a string and parses it to some internal
representation; if the string is an invalid version number,
'parse' raises a ValueError exception
* the class constructor takes an optional string argument which,
if supplied, is passed to 'parse'
* __str__ reconstructs the string that was passed to 'parse' (or
an equivalent string -- ie. one that will generate an equivalent
version number instance)
* __repr__ generates Python code to recreate the version number instance
* _cmp compares the current instance with either another instance
of the same class or a string (which will be parsed to an instance
of the same class, thus must follow the same rules)
"""
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import re
try:
RE_FLAGS = re.VERBOSE | re.ASCII
except AttributeError:
RE_FLAGS = re.VERBOSE
class Version:
"""Abstract base class for version numbering classes. Just provides
constructor (__init__) and reproducer (__repr__), because those
seem to be the same for all version numbering classes; and route
rich comparisons to _cmp.
"""
def __init__(self, vstring=None):
if vstring:
self.parse(vstring)
def __repr__(self):
return "%s ('%s')" % (self.__class__.__name__, str(self))
def __eq__(self, other):
c = self._cmp(other)
if c is NotImplemented:
return c
return c == 0
def __lt__(self, other):
c = self._cmp(other)
if c is NotImplemented:
return c
return c < 0
def __le__(self, other):
c = self._cmp(other)
if c is NotImplemented:
return c
return c <= 0
def __gt__(self, other):
c = self._cmp(other)
if c is NotImplemented:
return c
return c > 0
def __ge__(self, other):
c = self._cmp(other)
if c is NotImplemented:
return c
return c >= 0
# Interface for version-number classes -- must be implemented
# by the following classes (the concrete ones -- Version should
# be treated as an abstract class).
# __init__ (string) - create and take same action as 'parse'
# (string parameter is optional)
# parse (string) - convert a string representation to whatever
# internal representation is appropriate for
# this style of version numbering
# __str__ (self) - convert back to a string; should be very similar
# (if not identical to) the string supplied to parse
# __repr__ (self) - generate Python code to recreate
# the instance
# _cmp (self, other) - compare two version numbers ('other' may
# be an unparsed version string, or another
# instance of your version class)
class StrictVersion(Version):
"""Version numbering for anal retentives and software idealists.
Implements the standard interface for version number classes as
described above. A version number consists of two or three
dot-separated numeric components, with an optional "pre-release" tag
on the end. The pre-release tag consists of the letter 'a' or 'b'
followed by a number. If the numeric components of two version
numbers are equal, then one with a pre-release tag will always
be deemed earlier (lesser) than one without.
The following are valid version numbers (shown in the order that
would be obtained by sorting according to the supplied cmp function):
0.4 0.4.0 (these two are equivalent)
0.4.1
0.5a1
0.5b3
0.5
0.9.6
1.0
1.0.4a3
1.0.4b1
1.0.4
The following are examples of invalid version numbers:
1
2.7.2.2
1.3.a4
1.3pl1
1.3c4
The rationale for this version numbering system will be explained
in the distutils documentation.
"""
version_re = re.compile(r'^(\d+) \. (\d+) (\. (\d+))? ([ab](\d+))?$',
RE_FLAGS)
def parse(self, vstring):
match = self.version_re.match(vstring)
if not match:
raise ValueError("invalid version number '%s'" % vstring)
(major, minor, patch, prerelease, prerelease_num) = \
match.group(1, 2, 4, 5, 6)
if patch:
self.version = tuple(map(int, [major, minor, patch]))
else:
self.version = tuple(map(int, [major, minor])) + (0,)
if prerelease:
self.prerelease = (prerelease[0], int(prerelease_num))
else:
self.prerelease = None
def __str__(self):
if self.version[2] == 0:
vstring = '.'.join(map(str, self.version[0:2]))
else:
vstring = '.'.join(map(str, self.version))
if self.prerelease:
vstring = vstring + self.prerelease[0] + str(self.prerelease[1])
return vstring
def _cmp(self, other):
if isinstance(other, str):
other = StrictVersion(other)
elif not isinstance(other, StrictVersion):
return NotImplemented
if self.version != other.version:
# numeric versions don't match
# prerelease stuff doesn't matter
if self.version < other.version:
return -1
else:
return 1
# have to compare prerelease
# case 1: neither has prerelease; they're equal
# case 2: self has prerelease, other doesn't; other is greater
# case 3: self doesn't have prerelease, other does: self is greater
# case 4: both have prerelease: must compare them!
if (not self.prerelease and not other.prerelease):
return 0
elif (self.prerelease and not other.prerelease):
return -1
elif (not self.prerelease and other.prerelease):
return 1
elif (self.prerelease and other.prerelease):
if self.prerelease == other.prerelease:
return 0
elif self.prerelease < other.prerelease:
return -1
else:
return 1
else:
raise AssertionError("never get here")
# end class StrictVersion
# The rules according to Greg Stein:
# 1) a version number has 1 or more numbers separated by a period or by
# sequences of letters. If only periods, then these are compared
# left-to-right to determine an ordering.
# 2) sequences of letters are part of the tuple for comparison and are
# compared lexicographically
# 3) recognize the numeric components may have leading zeroes
#
# The LooseVersion class below implements these rules: a version number
# string is split up into a tuple of integer and string components, and
# comparison is a simple tuple comparison. This means that version
# numbers behave in a predictable and obvious way, but a way that might
# not necessarily be how people *want* version numbers to behave. There
# wouldn't be a problem if people could stick to purely numeric version
# numbers: just split on period and compare the numbers as tuples.
# However, people insist on putting letters into their version numbers;
# the most common purpose seems to be:
# - indicating a "pre-release" version
# ('alpha', 'beta', 'a', 'b', 'pre', 'p')
# - indicating a post-release patch ('p', 'pl', 'patch')
# but of course this can't cover all version number schemes, and there's
# no way to know what a programmer means without asking him.
#
# The problem is what to do with letters (and other non-numeric
# characters) in a version number. The current implementation does the
# obvious and predictable thing: keep them as strings and compare
# lexically within a tuple comparison. This has the desired effect if
# an appended letter sequence implies something "post-release":
# eg. "0.99" < "0.99pl14" < "1.0", and "5.001" < "5.001m" < "5.002".
#
# However, if letters in a version number imply a pre-release version,
# the "obvious" thing isn't correct. Eg. you would expect that
# "1.5.1" < "1.5.2a2" < "1.5.2", but under the tuple/lexical comparison
# implemented here, this just isn't so.
#
# Two possible solutions come to mind. The first is to tie the
# comparison algorithm to a particular set of semantic rules, as has
# been done in the StrictVersion class above. This works great as long
# as everyone can go along with bondage and discipline. Hopefully a
# (large) subset of Python module programmers will agree that the
# particular flavour of bondage and discipline provided by StrictVersion
# provides enough benefit to be worth using, and will submit their
# version numbering scheme to its domination. The free-thinking
# anarchists in the lot will never give in, though, and something needs
# to be done to accommodate them.
#
# Perhaps a "moderately strict" version class could be implemented that
# lets almost anything slide (syntactically), and makes some heuristic
# assumptions about non-digits in version number strings. This could
# sink into special-case-hell, though; if I was as talented and
# idiosyncratic as Larry Wall, I'd go ahead and implement a class that
# somehow knows that "1.2.1" < "1.2.2a2" < "1.2.2" < "1.2.2pl3", and is
# just as happy dealing with things like "2g6" and "1.13++". I don't
# think I'm smart enough to do it right though.
#
# In any case, I've coded the test suite for this module (see
# ../test/test_version.py) specifically to fail on things like comparing
# "1.2a2" and "1.2". That's not because the *code* is doing anything
# wrong, it's because the simple, obvious design doesn't match my
# complicated, hairy expectations for real-world version numbers. It
# would be a snap to fix the test suite to say, "Yep, LooseVersion does
# the Right Thing" (ie. the code matches the conception). But I'd rather
# have a conception that matches common notions about version numbers.
class LooseVersion(Version):
"""Version numbering for anarchists and software realists.
Implements the standard interface for version number classes as
described above. A version number consists of a series of numbers,
separated by either periods or strings of letters. When comparing
version numbers, the numeric components will be compared
numerically, and the alphabetic components lexically. The following
are all valid version numbers, in no particular order:
1.5.1
1.5.2b2
161
3.10a
8.02
3.4j
1996.07.12
3.2.pl0
3.1.1.6
2g6
11g
0.960923
2.2beta29
1.13++
5.5.kw
2.0b1pl0
In fact, there is no such thing as an invalid version number under
this scheme; the rules for comparison are simple and predictable,
but may not always give the results you want (for some definition
of "want").
"""
component_re = re.compile(r'(\d+ | [a-z]+ | \.)', re.VERBOSE)
def __init__(self, vstring=None):
if vstring:
self.parse(vstring)
def parse(self, vstring):
# I've given up on thinking I can reconstruct the version string
# from the parsed tuple -- so I just store the string here for
# use by __str__
self.vstring = vstring
components = [x for x in self.component_re.split(vstring) if x and x != '.']
for i, obj in enumerate(components):
try:
components[i] = int(obj)
except ValueError:
pass
self.version = components
def __str__(self):
return self.vstring
def __repr__(self):
return "LooseVersion ('%s')" % str(self)
def _cmp(self, other):
if isinstance(other, str):
other = LooseVersion(other)
elif not isinstance(other, LooseVersion):
return NotImplemented
if self.version == other.version:
return 0
if self.version < other.version:
return -1
if self.version > other.version:
return 1
# end class LooseVersion

File diff suppressed because it is too large Load Diff

View File

@@ -7,54 +7,41 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import json
from distutils.version import StrictVersion
from ansible.module_utils.basic import missing_required_lib
from ansible.module_utils.urls import fetch_url
from ansible.module_utils.common.text.converters import to_native
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
try:
from urllib import quote_plus # Python 2.X
from urlparse import urljoin
except ImportError:
from urllib.parse import quote_plus # Python 3+
from urllib.parse import quote_plus, urljoin # Python 3+
import traceback
GITLAB_IMP_ERR = None
try:
import gitlab
import requests
HAS_GITLAB_PACKAGE = True
except Exception:
GITLAB_IMP_ERR = traceback.format_exc()
HAS_GITLAB_PACKAGE = False
def request(module, api_url, project, path, access_token, private_token, rawdata='', method='GET'):
url = "%s/v4/projects/%s%s" % (api_url, quote_plus(project), path)
headers = {}
if access_token:
headers['Authorization'] = "Bearer %s" % access_token
else:
headers['Private-Token'] = private_token
headers['Accept'] = "application/json"
headers['Content-Type'] = "application/json"
response, info = fetch_url(module=module, url=url, headers=headers, data=rawdata, method=method)
status = info['status']
content = ""
if response:
content = response.read()
if status == 204:
return True, content
elif status == 200 or status == 201:
return True, json.loads(content)
else:
return False, str(status) + ": " + content
def auth_argument_spec(spec=None):
arg_spec = (dict(
api_token=dict(type='str', no_log=True),
api_oauth_token=dict(type='str', no_log=True),
api_job_token=dict(type='str', no_log=True),
))
if spec:
arg_spec.update(spec)
return arg_spec
def findProject(gitlab_instance, identifier):
def find_project(gitlab_instance, identifier):
try:
project = gitlab_instance.projects.get(identifier)
except Exception as e:
@@ -67,7 +54,7 @@ def findProject(gitlab_instance, identifier):
return project
def findGroup(gitlab_instance, identifier):
def find_group(gitlab_instance, identifier):
try:
project = gitlab_instance.groups.get(identifier)
except Exception as e:
@@ -76,12 +63,14 @@ def findGroup(gitlab_instance, identifier):
return project
def gitlabAuthentication(module):
def gitlab_authentication(module):
gitlab_url = module.params['api_url']
validate_certs = module.params['validate_certs']
gitlab_user = module.params['api_username']
gitlab_password = module.params['api_password']
gitlab_token = module.params['api_token']
gitlab_oauth_token = module.params['api_oauth_token']
gitlab_job_token = module.params['api_job_token']
if not HAS_GITLAB_PACKAGE:
module.fail_json(msg=missing_required_lib("python-gitlab"), exception=GITLAB_IMP_ERR)
@@ -90,11 +79,20 @@ def gitlabAuthentication(module):
# python-gitlab library remove support for username/password authentication since 1.13.0
# Changelog : https://github.com/python-gitlab/python-gitlab/releases/tag/v1.13.0
# This condition allow to still support older version of the python-gitlab library
if StrictVersion(gitlab.__version__) < StrictVersion("1.13.0"):
if LooseVersion(gitlab.__version__) < LooseVersion("1.13.0"):
gitlab_instance = gitlab.Gitlab(url=gitlab_url, ssl_verify=validate_certs, email=gitlab_user, password=gitlab_password,
private_token=gitlab_token, api_version=4)
else:
gitlab_instance = gitlab.Gitlab(url=gitlab_url, ssl_verify=validate_certs, private_token=gitlab_token, api_version=4)
# We can create an oauth_token using a username and password
# https://docs.gitlab.com/ee/api/oauth2.html#authorization-code-flow
if gitlab_user:
data = {'grant_type': 'password', 'username': gitlab_user, 'password': gitlab_password}
resp = requests.post(urljoin(gitlab_url, "oauth/token"), data=data, verify=validate_certs)
resp_data = resp.json()
gitlab_oauth_token = resp_data["access_token"]
gitlab_instance = gitlab.Gitlab(url=gitlab_url, ssl_verify=validate_certs, private_token=gitlab_token,
oauth_token=gitlab_oauth_token, job_token=gitlab_job_token, api_version=4)
gitlab_instance.auth()
except (gitlab.exceptions.GitlabAuthenticationError, gitlab.exceptions.GitlabGetError) as e:

View File

@@ -38,6 +38,7 @@ from ansible.module_utils.six.moves.urllib.parse import urlencode, quote
from ansible.module_utils.six.moves.urllib.error import HTTPError
from ansible.module_utils.common.text.converters import to_native, to_text
URL_REALM_INFO = "{url}/realms/{realm}"
URL_REALMS = "{url}/admin/realms"
URL_REALM = "{url}/admin/realms/{realm}"
@@ -230,6 +231,31 @@ class KeycloakAPI(object):
self.validate_certs = self.module.params.get('validate_certs')
self.restheaders = connection_header
def get_realm_info_by_id(self, realm='master'):
""" Obtain realm public info by id
:param realm: realm id
:return: dict of real, representation or None if none matching exist
"""
realm_info_url = URL_REALM_INFO.format(url=self.baseurl, realm=realm)
try:
return json.loads(to_native(open_url(realm_info_url, method='GET', headers=self.restheaders,
validate_certs=self.validate_certs).read()))
except HTTPError as e:
if e.code == 404:
return None
else:
self.module.fail_json(msg='Could not obtain realm %s: %s' % (realm, str(e)),
exception=traceback.format_exc())
except ValueError as e:
self.module.fail_json(msg='API returned incorrect JSON when trying to obtain realm %s: %s' % (realm, str(e)),
exception=traceback.format_exc())
except Exception as e:
self.module.fail_json(msg='Could not obtain realm %s: %s' % (realm, str(e)),
exception=traceback.format_exc())
def get_realm_by_id(self, realm='master'):
""" Obtain realm representation by id
@@ -1031,7 +1057,7 @@ class KeycloakAPI(object):
:param name: Name of the role to fetch.
:param realm: Realm in which the role resides; default 'master'.
"""
role_url = URL_REALM_ROLE.format(url=self.baseurl, realm=realm, name=name)
role_url = URL_REALM_ROLE.format(url=self.baseurl, realm=realm, name=quote(name))
try:
return json.loads(to_native(open_url(role_url, method="GET", headers=self.restheaders,
validate_certs=self.validate_certs).read()))
@@ -1065,7 +1091,7 @@ class KeycloakAPI(object):
:param rolerep: A RoleRepresentation of the updated role.
:return HTTPResponse object on success
"""
role_url = URL_REALM_ROLE.format(url=self.baseurl, realm=realm, name=rolerep['name'])
role_url = URL_REALM_ROLE.format(url=self.baseurl, realm=realm, name=quote(rolerep['name']))
try:
return open_url(role_url, method='PUT', headers=self.restheaders,
data=json.dumps(rolerep), validate_certs=self.validate_certs)
@@ -1079,7 +1105,7 @@ class KeycloakAPI(object):
:param name: The name of the role.
:param realm: The realm in which this role resides, default "master".
"""
role_url = URL_REALM_ROLE.format(url=self.baseurl, realm=realm, name=name)
role_url = URL_REALM_ROLE.format(url=self.baseurl, realm=realm, name=quote(name))
try:
return open_url(role_url, method='DELETE', headers=self.restheaders,
validate_certs=self.validate_certs)
@@ -1122,7 +1148,7 @@ class KeycloakAPI(object):
if cid is None:
self.module.fail_json(msg='Could not find client %s in realm %s'
% (clientid, realm))
role_url = URL_CLIENT_ROLE.format(url=self.baseurl, realm=realm, id=cid, name=name)
role_url = URL_CLIENT_ROLE.format(url=self.baseurl, realm=realm, id=cid, name=quote(name))
try:
return json.loads(to_native(open_url(role_url, method="GET", headers=self.restheaders,
validate_certs=self.validate_certs).read()))
@@ -1168,7 +1194,7 @@ class KeycloakAPI(object):
if cid is None:
self.module.fail_json(msg='Could not find client %s in realm %s'
% (clientid, realm))
role_url = URL_CLIENT_ROLE.format(url=self.baseurl, realm=realm, id=cid, name=rolerep['name'])
role_url = URL_CLIENT_ROLE.format(url=self.baseurl, realm=realm, id=cid, name=quote(rolerep['name']))
try:
return open_url(role_url, method='PUT', headers=self.restheaders,
data=json.dumps(rolerep), validate_certs=self.validate_certs)
@@ -1187,7 +1213,7 @@ class KeycloakAPI(object):
if cid is None:
self.module.fail_json(msg='Could not find client %s in realm %s'
% (clientid, realm))
role_url = URL_CLIENT_ROLE.format(url=self.baseurl, realm=realm, id=cid, name=name)
role_url = URL_CLIENT_ROLE.format(url=self.baseurl, realm=realm, id=cid, name=quote(name))
try:
return open_url(role_url, method='DELETE', headers=self.restheaders,
validate_certs=self.validate_certs)

View File

@@ -0,0 +1,232 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021-2022 Hewlett Packard Enterprise, Inc. All rights reserved.
# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible_collections.community.general.plugins.module_utils.redfish_utils import RedfishUtils
class iLORedfishUtils(RedfishUtils):
def get_ilo_sessions(self):
result = {}
# listing all users has always been slower than other operations, why?
session_list = []
sessions_results = []
# Get these entries, but does not fail if not found
properties = ['Description', 'Id', 'Name', 'UserName']
# Changed self.sessions_uri to Hardcoded string.
response = self.get_request(
self.root_uri + self.service_root + "SessionService/Sessions/")
if not response['ret']:
return response
result['ret'] = True
data = response['data']
if 'Oem' in data:
if data["Oem"]["Hpe"]["Links"]["MySession"]["@odata.id"]:
current_session = data["Oem"]["Hpe"]["Links"]["MySession"]["@odata.id"]
for sessions in data[u'Members']:
# session_list[] are URIs
session_list.append(sessions[u'@odata.id'])
# for each session, get details
for uri in session_list:
session = {}
if uri != current_session:
response = self.get_request(self.root_uri + uri)
if not response['ret']:
return response
data = response['data']
for property in properties:
if property in data:
session[property] = data[property]
sessions_results.append(session)
result["msg"] = sessions_results
result["ret"] = True
return result
def set_ntp_server(self, mgr_attributes):
result = {}
setkey = mgr_attributes['mgr_attr_name']
nic_info = self.get_manager_ethernet_uri()
ethuri = nic_info["nic_addr"]
response = self.get_request(self.root_uri + ethuri)
if not response['ret']:
return response
result['ret'] = True
data = response['data']
payload = {"DHCPv4": {
"UseNTPServers": ""
}}
if data["DHCPv4"]["UseNTPServers"]:
payload["DHCPv4"]["UseNTPServers"] = False
res_dhv4 = self.patch_request(self.root_uri + ethuri, payload)
if not res_dhv4['ret']:
return res_dhv4
payload = {"DHCPv6": {
"UseNTPServers": ""
}}
if data["DHCPv6"]["UseNTPServers"]:
payload["DHCPv6"]["UseNTPServers"] = False
res_dhv6 = self.patch_request(self.root_uri + ethuri, payload)
if not res_dhv6['ret']:
return res_dhv6
datetime_uri = self.manager_uri + "DateTime"
response = self.get_request(self.root_uri + datetime_uri)
if not response['ret']:
return response
data = response['data']
ntp_list = data[setkey]
if(len(ntp_list) == 2):
ntp_list.pop(0)
ntp_list.append(mgr_attributes['mgr_attr_value'])
payload = {setkey: ntp_list}
response1 = self.patch_request(self.root_uri + datetime_uri, payload)
if not response1['ret']:
return response1
return {'ret': True, 'changed': True, 'msg': "Modified %s" % mgr_attributes['mgr_attr_name']}
def set_time_zone(self, attr):
key = attr['mgr_attr_name']
uri = self.manager_uri + "DateTime/"
response = self.get_request(self.root_uri + uri)
if not response['ret']:
return response
data = response["data"]
if key not in data:
return {'ret': False, 'changed': False, 'msg': "Key %s not found" % key}
timezones = data["TimeZoneList"]
index = ""
for tz in timezones:
if attr['mgr_attr_value'] in tz["Name"]:
index = tz["Index"]
break
payload = {key: {"Index": index}}
response = self.patch_request(self.root_uri + uri, payload)
if not response['ret']:
return response
return {'ret': True, 'changed': True, 'msg': "Modified %s" % attr['mgr_attr_name']}
def set_dns_server(self, attr):
key = attr['mgr_attr_name']
nic_info = self.get_manager_ethernet_uri()
uri = nic_info["nic_addr"]
response = self.get_request(self.root_uri + uri)
if not response['ret']:
return response
data = response['data']
dns_list = data["Oem"]["Hpe"]["IPv4"][key]
if len(dns_list) == 3:
dns_list.pop(0)
dns_list.append(attr['mgr_attr_value'])
payload = {
"Oem": {
"Hpe": {
"IPv4": {
key: dns_list
}
}
}
}
response = self.patch_request(self.root_uri + uri, payload)
if not response['ret']:
return response
return {'ret': True, 'changed': True, 'msg': "Modified %s" % attr['mgr_attr_name']}
def set_domain_name(self, attr):
key = attr['mgr_attr_name']
nic_info = self.get_manager_ethernet_uri()
ethuri = nic_info["nic_addr"]
response = self.get_request(self.root_uri + ethuri)
if not response['ret']:
return response
data = response['data']
payload = {"DHCPv4": {
"UseDomainName": ""
}}
if data["DHCPv4"]["UseDomainName"]:
payload["DHCPv4"]["UseDomainName"] = False
res_dhv4 = self.patch_request(self.root_uri + ethuri, payload)
if not res_dhv4['ret']:
return res_dhv4
payload = {"DHCPv6": {
"UseDomainName": ""
}}
if data["DHCPv6"]["UseDomainName"]:
payload["DHCPv6"]["UseDomainName"] = False
res_dhv6 = self.patch_request(self.root_uri + ethuri, payload)
if not res_dhv6['ret']:
return res_dhv6
domain_name = attr['mgr_attr_value']
payload = {"Oem": {
"Hpe": {
key: domain_name
}
}}
response = self.patch_request(self.root_uri + ethuri, payload)
if not response['ret']:
return response
return {'ret': True, 'changed': True, 'msg': "Modified %s" % attr['mgr_attr_name']}
def set_wins_registration(self, mgrattr):
Key = mgrattr['mgr_attr_name']
nic_info = self.get_manager_ethernet_uri()
ethuri = nic_info["nic_addr"]
payload = {
"Oem": {
"Hpe": {
"IPv4": {
Key: False
}
}
}
}
response = self.patch_request(self.root_uri + ethuri, payload)
if not response['ret']:
return response
return {'ret': True, 'changed': True, 'msg': "Modified %s" % mgrattr['mgr_attr_name']}

View File

@@ -9,7 +9,8 @@ __metaclass__ = type
import traceback
from ansible.module_utils.basic import missing_required_lib
from distutils.version import LooseVersion
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
REQUESTS_IMP_ERR = None
try:

View File

@@ -31,6 +31,7 @@ def _env_then_dns_fallback(*args, **kwargs):
result = env_fallback(*args, **kwargs)
if result == '':
raise AnsibleFallbackNotFound
return result
except AnsibleFallbackNotFound:
# If no host was given, we try to guess it from IPA.
# The ipa-ca entry is a standard entry that IPA will have set for
@@ -178,10 +179,10 @@ class IPAClient(object):
result.append(key)
return result
def modify_if_diff(self, name, ipa_list, module_list, add_method, remove_method, item=None):
def modify_if_diff(self, name, ipa_list, module_list, add_method, remove_method, item=None, append=None):
changed = False
diff = list(set(ipa_list) - set(module_list))
if len(diff) > 0:
if append is not True and len(diff) > 0:
changed = True
if not self.module.check_mode:
if item:

View File

@@ -52,3 +52,36 @@ def module_fails_on_exception(func):
self.module.fail_json(msg=msg, exception=traceback.format_exc(),
output=self.output, vars=self.vars.output(), **self.output)
return wrapper
def check_mode_skip(func):
@wraps(func)
def wrapper(self, *args, **kwargs):
if not self.module.check_mode:
return func(self, *args, **kwargs)
return wrapper
def check_mode_skip_returns(callable=None, value=None):
def deco(func):
if callable is not None:
@wraps(func)
def wrapper_callable(self, *args, **kwargs):
if self.module.check_mode:
return callable(self, *args, **kwargs)
return func(self, *args, **kwargs)
return wrapper_callable
if value is not None:
@wraps(func)
def wrapper_value(self, *args, **kwargs):
if self.module.check_mode:
return value
return func(self, *args, **kwargs)
return wrapper_value
if callable is None and value is None:
return check_mode_skip
return deco

View File

@@ -141,11 +141,7 @@ class CmdMixin(object):
fmt = find_format(param)
value = extra_params[param]
else:
self.module.deprecate("Cannot determine value for parameter: {0}. "
"From version 4.0.0 onwards this will generate an exception".format(param),
version="4.0.0", collection_name="community.general")
continue
raise self.ModuleHelperException('Cannot determine value for parameter: {0}'.format(param))
else:
raise self.ModuleHelperException("run_command parameter must be either a str or a dict: {0}".format(param))
cmd_args = add_arg_formatted_param(cmd_args, fmt, value)
@@ -162,8 +158,9 @@ class CmdMixin(object):
publish_rc=True,
publish_out=True,
publish_err=True,
publish_cmd=True,
*args, **kwargs):
self.vars.cmd_args = self._calculate_args(extra_params, params)
cmd_args = self._calculate_args(extra_params, params)
options = dict(self.run_command_fixed_options)
options['check_rc'] = options.get('check_rc', self.check_rc)
options.update(kwargs)
@@ -175,13 +172,15 @@ class CmdMixin(object):
})
self.update_output(force_lang=self.force_lang)
options['environ_update'] = env_update
rc, out, err = self.module.run_command(self.vars.cmd_args, *args, **options)
rc, out, err = self.module.run_command(cmd_args, *args, **options)
if publish_rc:
self.update_output(rc=rc)
if publish_out:
self.update_output(stdout=out)
if publish_err:
self.update_output(stderr=err)
if publish_cmd:
self.update_output(cmd_args=cmd_args)
if process_output is None:
_process = self.process_command_output
else:

View File

@@ -0,0 +1,61 @@
# -*- coding: utf-8 -*-
# (c) 2020, Alexei Znamensky <russoz@gmail.com>
# Copyright: (c) 2020, Ansible Project
# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible.module_utils.basic import AnsibleModule
class DeprecateAttrsMixin(object):
def _deprecate_setup(self, attr, target, module):
if target is None:
target = self
if not hasattr(target, attr):
raise ValueError("Target {0} has no attribute {1}".format(target, attr))
if module is None:
if isinstance(target, AnsibleModule):
module = target
elif hasattr(target, "module") and isinstance(target.module, AnsibleModule):
module = target.module
else:
raise ValueError("Failed to automatically discover the AnsibleModule instance. Pass 'module' parameter explicitly.")
# setup internal state dicts
value_attr = "__deprecated_attr_value"
trigger_attr = "__deprecated_attr_trigger"
if not hasattr(target, value_attr):
setattr(target, value_attr, {})
if not hasattr(target, trigger_attr):
setattr(target, trigger_attr, {})
value_dict = getattr(target, value_attr)
trigger_dict = getattr(target, trigger_attr)
return target, module, value_dict, trigger_dict
def _deprecate_attr(self, attr, msg, version=None, date=None, collection_name=None, target=None, value=None, module=None):
target, module, value_dict, trigger_dict = self._deprecate_setup(attr, target, module)
value_dict[attr] = getattr(target, attr, value)
trigger_dict[attr] = False
def _trigger():
if not trigger_dict[attr]:
module.deprecate(msg, version=version, date=date, collection_name=collection_name)
trigger_dict[attr] = True
def _getter(_self):
_trigger()
return value_dict[attr]
def _setter(_self, new_value):
_trigger()
value_dict[attr] = new_value
# override attribute
prop = property(_getter)
setattr(target, attr, prop)
setattr(target, "_{0}_setter".format(attr), prop.setter(_setter))

View File

@@ -13,9 +13,10 @@ from ansible_collections.community.general.plugins.module_utils.mh.mixins.cmd im
from ansible_collections.community.general.plugins.module_utils.mh.mixins.state import StateMixin
from ansible_collections.community.general.plugins.module_utils.mh.mixins.deps import DependencyMixin
from ansible_collections.community.general.plugins.module_utils.mh.mixins.vars import VarsMixin, VarDict as _VD
from ansible_collections.community.general.plugins.module_utils.mh.mixins.deprecate_attrs import DeprecateAttrsMixin
class ModuleHelper(VarsMixin, DependencyMixin, ModuleHelperBase):
class ModuleHelper(DeprecateAttrsMixin, VarsMixin, DependencyMixin, ModuleHelperBase):
_output_conflict_list = ('msg', 'exception', 'output', 'vars', 'changed')
facts_name = None
output_params = ()
@@ -36,6 +37,15 @@ class ModuleHelper(VarsMixin, DependencyMixin, ModuleHelperBase):
fact=name in self.facts_params,
)
self._deprecate_attr(
attr="VarDict",
msg="ModuleHelper.VarDict attribute is deprecated, use VarDict from "
"the ansible_collections.community.general.plugins.module_utils.mh.mixins.vars module instead",
version="6.0.0",
collection_name="community.general",
target=ModuleHelper,
module=self.module)
def update_output(self, **kwargs):
self.update_vars(meta={"output": True}, **kwargs)

View File

@@ -1,598 +0,0 @@
# -*- coding: utf-8 -*-
# This code is part of Ansible, but is an independent component.
# This particular file snippet, and this file snippet only, is BSD licensed.
# Modules you write using this snippet, which is embedded dynamically by Ansible
# still belong to the author of the module, and may assign their own license
# to the complete work.
#
# (c) 2018 Red Hat Inc.
#
# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
from functools import partial
from ansible.module_utils.common.text.converters import to_native
from ansible.module_utils.six import iteritems
from ansible.module_utils.common.text.converters import to_text
from ansible.module_utils.basic import env_fallback
from ansible.module_utils.common.validation import check_type_dict
try:
from infoblox_client.connector import Connector
from infoblox_client.exceptions import InfobloxException
HAS_INFOBLOX_CLIENT = True
except ImportError:
HAS_INFOBLOX_CLIENT = False
# defining nios constants
NIOS_DNS_VIEW = 'view'
NIOS_NETWORK_VIEW = 'networkview'
NIOS_HOST_RECORD = 'record:host'
NIOS_IPV4_NETWORK = 'network'
NIOS_IPV6_NETWORK = 'ipv6network'
NIOS_ZONE = 'zone_auth'
NIOS_PTR_RECORD = 'record:ptr'
NIOS_A_RECORD = 'record:a'
NIOS_AAAA_RECORD = 'record:aaaa'
NIOS_CNAME_RECORD = 'record:cname'
NIOS_MX_RECORD = 'record:mx'
NIOS_SRV_RECORD = 'record:srv'
NIOS_NAPTR_RECORD = 'record:naptr'
NIOS_TXT_RECORD = 'record:txt'
NIOS_NSGROUP = 'nsgroup'
NIOS_IPV4_FIXED_ADDRESS = 'fixedaddress'
NIOS_IPV6_FIXED_ADDRESS = 'ipv6fixedaddress'
NIOS_NEXT_AVAILABLE_IP = 'func:nextavailableip'
NIOS_IPV4_NETWORK_CONTAINER = 'networkcontainer'
NIOS_IPV6_NETWORK_CONTAINER = 'ipv6networkcontainer'
NIOS_MEMBER = 'member'
NIOS_PROVIDER_SPEC = {
'host': dict(fallback=(env_fallback, ['INFOBLOX_HOST'])),
'username': dict(fallback=(env_fallback, ['INFOBLOX_USERNAME'])),
'password': dict(fallback=(env_fallback, ['INFOBLOX_PASSWORD']), no_log=True),
'validate_certs': dict(type='bool', default=False, fallback=(env_fallback, ['INFOBLOX_SSL_VERIFY']), aliases=['ssl_verify']),
'silent_ssl_warnings': dict(type='bool', default=True),
'http_request_timeout': dict(type='int', default=10, fallback=(env_fallback, ['INFOBLOX_HTTP_REQUEST_TIMEOUT'])),
'http_pool_connections': dict(type='int', default=10),
'http_pool_maxsize': dict(type='int', default=10),
'max_retries': dict(type='int', default=3, fallback=(env_fallback, ['INFOBLOX_MAX_RETRIES'])),
'wapi_version': dict(default='2.1', fallback=(env_fallback, ['INFOBLOX_WAP_VERSION'])),
'max_results': dict(type='int', default=1000, fallback=(env_fallback, ['INFOBLOX_MAX_RETRIES']))
}
def get_connector(*args, **kwargs):
''' Returns an instance of infoblox_client.connector.Connector
:params args: positional arguments are silently ignored
:params kwargs: dict that is passed to Connector init
:returns: Connector
'''
if not HAS_INFOBLOX_CLIENT:
raise Exception('infoblox-client is required but does not appear '
'to be installed. It can be installed using the '
'command `pip install infoblox-client`')
if not set(kwargs.keys()).issubset(list(NIOS_PROVIDER_SPEC.keys()) + ['ssl_verify']):
raise Exception('invalid or unsupported keyword argument for connector')
for key, value in iteritems(NIOS_PROVIDER_SPEC):
if key not in kwargs:
# apply default values from NIOS_PROVIDER_SPEC since we cannot just
# assume the provider values are coming from AnsibleModule
if 'default' in value:
kwargs[key] = value['default']
# override any values with env variables unless they were
# explicitly set
env = ('INFOBLOX_%s' % key).upper()
if env in os.environ:
kwargs[key] = os.environ.get(env)
if 'validate_certs' in kwargs.keys():
kwargs['ssl_verify'] = kwargs['validate_certs']
kwargs.pop('validate_certs', None)
return Connector(kwargs)
def normalize_extattrs(value):
''' Normalize extattrs field to expected format
The module accepts extattrs as key/value pairs. This method will
transform the key/value pairs into a structure suitable for
sending across WAPI in the format of:
extattrs: {
key: {
value: <value>
}
}
'''
return dict([(k, {'value': v}) for k, v in iteritems(value)])
def flatten_extattrs(value):
''' Flatten the key/value struct for extattrs
WAPI returns extattrs field as a dict in form of:
extattrs: {
key: {
value: <value>
}
}
This method will flatten the structure to:
extattrs: {
key: value
}
'''
return dict([(k, v['value']) for k, v in iteritems(value)])
def member_normalize(member_spec):
''' Transforms the member module arguments into a valid WAPI struct
This function will transform the arguments into a structure that
is a valid WAPI structure in the format of:
{
key: <value>,
}
It will remove any arguments that are set to None since WAPI will error on
that condition.
The remainder of the value validation is performed by WAPI
Some parameters in ib_spec are passed as a list in order to pass the validation for elements.
In this function, they are converted to dictionary.
'''
member_elements = ['vip_setting', 'ipv6_setting', 'lan2_port_setting', 'mgmt_port_setting',
'pre_provisioning', 'network_setting', 'v6_network_setting',
'ha_port_setting', 'lan_port_setting', 'lan2_physical_setting',
'lan_ha_port_setting', 'mgmt_network_setting', 'v6_mgmt_network_setting']
for key in list(member_spec.keys()):
if key in member_elements and member_spec[key] is not None:
member_spec[key] = member_spec[key][0]
if isinstance(member_spec[key], dict):
member_spec[key] = member_normalize(member_spec[key])
elif isinstance(member_spec[key], list):
for x in member_spec[key]:
if isinstance(x, dict):
x = member_normalize(x)
elif member_spec[key] is None:
del member_spec[key]
return member_spec
def normalize_ib_spec(ib_spec):
result = {}
for arg in ib_spec:
result[arg] = dict([(k, v)
for k, v in iteritems(ib_spec[arg])
if k not in ('ib_req', 'transform', 'update')])
return result
class WapiBase(object):
''' Base class for implementing Infoblox WAPI API '''
provider_spec = {'provider': dict(type='dict', options=NIOS_PROVIDER_SPEC)}
def __init__(self, provider):
self.connector = get_connector(**provider)
def __getattr__(self, name):
try:
return self.__dict__[name]
except KeyError:
if name.startswith('_'):
raise AttributeError("'%s' object has no attribute '%s'" % (self.__class__.__name__, name))
return partial(self._invoke_method, name)
def _invoke_method(self, name, *args, **kwargs):
try:
method = getattr(self.connector, name)
return method(*args, **kwargs)
except InfobloxException as exc:
if hasattr(self, 'handle_exception'):
self.handle_exception(name, exc)
else:
raise
class WapiLookup(WapiBase):
''' Implements WapiBase for lookup plugins '''
def handle_exception(self, method_name, exc):
if ('text' in exc.response):
raise Exception(exc.response['text'])
else:
raise Exception(exc)
class WapiInventory(WapiBase):
''' Implements WapiBase for dynamic inventory script '''
pass
class WapiModule(WapiBase):
''' Implements WapiBase for executing a NIOS module '''
def __init__(self, module):
self.module = module
provider = module.params['provider']
try:
super(WapiModule, self).__init__(provider)
except Exception as exc:
self.module.fail_json(msg=to_text(exc))
def handle_exception(self, method_name, exc):
''' Handles any exceptions raised
This method will be called if an InfobloxException is raised for
any call to the instance of Connector and also, in case of generic
exception. This method will then gracefully fail the module.
:args exc: instance of InfobloxException
'''
if ('text' in exc.response):
self.module.fail_json(
msg=exc.response['text'],
type=exc.response['Error'].split(':')[0],
code=exc.response.get('code'),
operation=method_name
)
else:
self.module.fail_json(msg=to_native(exc))
def run(self, ib_obj_type, ib_spec):
''' Runs the module and performans configuration tasks
:args ib_obj_type: the WAPI object type to operate against
:args ib_spec: the specification for the WAPI object as a dict
:returns: a results dict
'''
update = new_name = None
state = self.module.params['state']
if state not in ('present', 'absent'):
self.module.fail_json(msg='state must be one of `present`, `absent`, got `%s`' % state)
result = {'changed': False}
obj_filter = dict([(k, self.module.params[k]) for k, v in iteritems(ib_spec) if v.get('ib_req')])
# get object reference
ib_obj_ref, update, new_name = self.get_object_ref(self.module, ib_obj_type, obj_filter, ib_spec)
proposed_object = {}
for key, value in iteritems(ib_spec):
if self.module.params[key] is not None:
if 'transform' in value:
proposed_object[key] = value['transform'](self.module)
else:
proposed_object[key] = self.module.params[key]
# If configure_by_dns is set to False and view is 'default', then delete the default dns
if not proposed_object.get('configure_for_dns') and proposed_object.get('view') == 'default'\
and ib_obj_type == NIOS_HOST_RECORD:
del proposed_object['view']
if ib_obj_ref:
if len(ib_obj_ref) > 1:
for each in ib_obj_ref:
# To check for existing A_record with same name with input A_record by IP
if each.get('ipv4addr') and each.get('ipv4addr') == proposed_object.get('ipv4addr'):
current_object = each
# To check for existing Host_record with same name with input Host_record by IP
elif each.get('ipv4addrs')[0].get('ipv4addr') and each.get('ipv4addrs')[0].get('ipv4addr')\
== proposed_object.get('ipv4addrs')[0].get('ipv4addr'):
current_object = each
# Else set the current_object with input value
else:
current_object = obj_filter
ref = None
else:
current_object = ib_obj_ref[0]
if 'extattrs' in current_object:
current_object['extattrs'] = flatten_extattrs(current_object['extattrs'])
if current_object.get('_ref'):
ref = current_object.pop('_ref')
else:
current_object = obj_filter
ref = None
# checks if the object type is member to normalize the attributes being passed
if (ib_obj_type == NIOS_MEMBER):
proposed_object = member_normalize(proposed_object)
# checks if the name's field has been updated
if update and new_name:
proposed_object['name'] = new_name
check_remove = []
if (ib_obj_type == NIOS_HOST_RECORD):
# this check is for idempotency, as if the same ip address shall be passed
# add param will be removed, and same exists true for remove case as well.
if 'ipv4addrs' in [current_object and proposed_object]:
for each in current_object['ipv4addrs']:
if each['ipv4addr'] == proposed_object['ipv4addrs'][0]['ipv4addr']:
if 'add' in proposed_object['ipv4addrs'][0]:
del proposed_object['ipv4addrs'][0]['add']
break
check_remove += each.values()
if proposed_object['ipv4addrs'][0]['ipv4addr'] not in check_remove:
if 'remove' in proposed_object['ipv4addrs'][0]:
del proposed_object['ipv4addrs'][0]['remove']
res = None
modified = not self.compare_objects(current_object, proposed_object)
if 'extattrs' in proposed_object:
proposed_object['extattrs'] = normalize_extattrs(proposed_object['extattrs'])
# Checks if nios_next_ip param is passed in ipv4addrs/ipv4addr args
proposed_object = self.check_if_nios_next_ip_exists(proposed_object)
if state == 'present':
if ref is None:
if not self.module.check_mode:
self.create_object(ib_obj_type, proposed_object)
result['changed'] = True
# Check if NIOS_MEMBER and the flag to call function create_token is set
elif (ib_obj_type == NIOS_MEMBER) and (proposed_object['create_token']):
proposed_object = None
# the function creates a token that can be used by a pre-provisioned member to join the grid
result['api_results'] = self.call_func('create_token', ref, proposed_object)
result['changed'] = True
elif modified:
if 'ipv4addrs' in proposed_object:
if ('add' not in proposed_object['ipv4addrs'][0]) and ('remove' not in proposed_object['ipv4addrs'][0]):
self.check_if_recordname_exists(obj_filter, ib_obj_ref, ib_obj_type, current_object, proposed_object)
if (ib_obj_type in (NIOS_HOST_RECORD, NIOS_NETWORK_VIEW, NIOS_DNS_VIEW)):
run_update = True
proposed_object = self.on_update(proposed_object, ib_spec)
if 'ipv4addrs' in proposed_object:
if ('add' or 'remove') in proposed_object['ipv4addrs'][0]:
run_update, proposed_object = self.check_if_add_remove_ip_arg_exists(proposed_object)
if run_update:
res = self.update_object(ref, proposed_object)
result['changed'] = True
else:
res = ref
if (ib_obj_type in (NIOS_A_RECORD, NIOS_AAAA_RECORD, NIOS_PTR_RECORD, NIOS_SRV_RECORD)):
# popping 'view' key as update of 'view' is not supported with respect to a:record/aaaa:record/srv:record/ptr:record
proposed_object = self.on_update(proposed_object, ib_spec)
del proposed_object['view']
if not self.module.check_mode:
res = self.update_object(ref, proposed_object)
result['changed'] = True
elif 'network_view' in proposed_object:
proposed_object.pop('network_view')
result['changed'] = True
if not self.module.check_mode and res is None:
proposed_object = self.on_update(proposed_object, ib_spec)
self.update_object(ref, proposed_object)
result['changed'] = True
elif state == 'absent':
if ref is not None:
if 'ipv4addrs' in proposed_object:
if 'remove' in proposed_object['ipv4addrs'][0]:
self.check_if_add_remove_ip_arg_exists(proposed_object)
self.update_object(ref, proposed_object)
result['changed'] = True
elif not self.module.check_mode:
self.delete_object(ref)
result['changed'] = True
return result
def check_if_recordname_exists(self, obj_filter, ib_obj_ref, ib_obj_type, current_object, proposed_object):
''' Send POST request if host record input name and retrieved ref name is same,
but input IP and retrieved IP is different'''
if 'name' in (obj_filter and ib_obj_ref[0]) and ib_obj_type == NIOS_HOST_RECORD:
obj_host_name = obj_filter['name']
ref_host_name = ib_obj_ref[0]['name']
if 'ipv4addrs' in (current_object and proposed_object):
current_ip_addr = current_object['ipv4addrs'][0]['ipv4addr']
proposed_ip_addr = proposed_object['ipv4addrs'][0]['ipv4addr']
elif 'ipv6addrs' in (current_object and proposed_object):
current_ip_addr = current_object['ipv6addrs'][0]['ipv6addr']
proposed_ip_addr = proposed_object['ipv6addrs'][0]['ipv6addr']
if obj_host_name == ref_host_name and current_ip_addr != proposed_ip_addr:
self.create_object(ib_obj_type, proposed_object)
def check_if_nios_next_ip_exists(self, proposed_object):
''' Check if nios_next_ip argument is passed in ipaddr while creating
host record, if yes then format proposed object ipv4addrs and pass
func:nextavailableip and ipaddr range to create hostrecord with next
available ip in one call to avoid any race condition '''
if 'ipv4addrs' in proposed_object:
if 'nios_next_ip' in proposed_object['ipv4addrs'][0]['ipv4addr']:
ip_range = check_type_dict(proposed_object['ipv4addrs'][0]['ipv4addr'])['nios_next_ip']
proposed_object['ipv4addrs'][0]['ipv4addr'] = NIOS_NEXT_AVAILABLE_IP + ':' + ip_range
elif 'ipv4addr' in proposed_object:
if 'nios_next_ip' in proposed_object['ipv4addr']:
ip_range = check_type_dict(proposed_object['ipv4addr'])['nios_next_ip']
proposed_object['ipv4addr'] = NIOS_NEXT_AVAILABLE_IP + ':' + ip_range
return proposed_object
def check_if_add_remove_ip_arg_exists(self, proposed_object):
'''
This function shall check if add/remove param is set to true and
is passed in the args, then we will update the proposed dictionary
to add/remove IP to existing host_record, if the user passes false
param with the argument nothing shall be done.
:returns: True if param is changed based on add/remove, and also the
changed proposed_object.
'''
update = False
if 'add' in proposed_object['ipv4addrs'][0]:
if proposed_object['ipv4addrs'][0]['add']:
proposed_object['ipv4addrs+'] = proposed_object['ipv4addrs']
del proposed_object['ipv4addrs']
del proposed_object['ipv4addrs+'][0]['add']
update = True
else:
del proposed_object['ipv4addrs'][0]['add']
elif 'remove' in proposed_object['ipv4addrs'][0]:
if proposed_object['ipv4addrs'][0]['remove']:
proposed_object['ipv4addrs-'] = proposed_object['ipv4addrs']
del proposed_object['ipv4addrs']
del proposed_object['ipv4addrs-'][0]['remove']
update = True
else:
del proposed_object['ipv4addrs'][0]['remove']
return update, proposed_object
def issubset(self, item, objects):
''' Checks if item is a subset of objects
:args item: the subset item to validate
:args objects: superset list of objects to validate against
:returns: True if item is a subset of one entry in objects otherwise
this method will return None
'''
for obj in objects:
if isinstance(item, dict):
if all(entry in obj.items() for entry in item.items()):
return True
else:
if item in obj:
return True
def compare_objects(self, current_object, proposed_object):
for key, proposed_item in iteritems(proposed_object):
current_item = current_object.get(key)
# if proposed has a key that current doesn't then the objects are
# not equal and False will be immediately returned
if current_item is None:
return False
elif isinstance(proposed_item, list):
if key == 'aliases':
if set(current_item) != set(proposed_item):
return False
for subitem in proposed_item:
if not self.issubset(subitem, current_item):
return False
elif isinstance(proposed_item, dict):
return self.compare_objects(current_item, proposed_item)
else:
if current_item != proposed_item:
return False
return True
def get_object_ref(self, module, ib_obj_type, obj_filter, ib_spec):
''' this function gets the reference object of pre-existing nios objects '''
update = False
old_name = new_name = None
if ('name' in obj_filter):
# gets and returns the current object based on name/old_name passed
try:
name_obj = check_type_dict(obj_filter['name'])
old_name = name_obj['old_name']
new_name = name_obj['new_name']
except TypeError:
name = obj_filter['name']
if old_name and new_name:
if (ib_obj_type == NIOS_HOST_RECORD):
test_obj_filter = dict([('name', old_name), ('view', obj_filter['view'])])
elif (ib_obj_type in (NIOS_AAAA_RECORD, NIOS_A_RECORD)):
test_obj_filter = obj_filter
else:
test_obj_filter = dict([('name', old_name)])
# get the object reference
ib_obj = self.get_object(ib_obj_type, test_obj_filter, return_fields=list(ib_spec.keys()))
if ib_obj:
obj_filter['name'] = new_name
else:
test_obj_filter['name'] = new_name
ib_obj = self.get_object(ib_obj_type, test_obj_filter, return_fields=list(ib_spec.keys()))
update = True
return ib_obj, update, new_name
if (ib_obj_type == NIOS_HOST_RECORD):
# to check only by name if dns bypassing is set
if not obj_filter['configure_for_dns']:
test_obj_filter = dict([('name', name)])
else:
test_obj_filter = dict([('name', name), ('view', obj_filter['view'])])
elif (ib_obj_type == NIOS_IPV4_FIXED_ADDRESS or ib_obj_type == NIOS_IPV6_FIXED_ADDRESS and 'mac' in obj_filter):
test_obj_filter = dict([['mac', obj_filter['mac']]])
elif (ib_obj_type == NIOS_A_RECORD):
# resolves issue where a_record with uppercase name was returning null and was failing
test_obj_filter = obj_filter
test_obj_filter['name'] = test_obj_filter['name'].lower()
# resolves issue where multiple a_records with same name and different IP address
try:
ipaddr_obj = check_type_dict(obj_filter['ipv4addr'])
ipaddr = ipaddr_obj['old_ipv4addr']
except TypeError:
ipaddr = obj_filter['ipv4addr']
test_obj_filter['ipv4addr'] = ipaddr
elif (ib_obj_type == NIOS_TXT_RECORD):
# resolves issue where multiple txt_records with same name and different text
test_obj_filter = obj_filter
try:
text_obj = check_type_dict(obj_filter['text'])
txt = text_obj['old_text']
except TypeError:
txt = obj_filter['text']
test_obj_filter['text'] = txt
# check if test_obj_filter is empty copy passed obj_filter
else:
test_obj_filter = obj_filter
ib_obj = self.get_object(ib_obj_type, test_obj_filter.copy(), return_fields=list(ib_spec.keys()))
elif (ib_obj_type == NIOS_A_RECORD):
# resolves issue where multiple a_records with same name and different IP address
test_obj_filter = obj_filter
try:
ipaddr_obj = check_type_dict(obj_filter['ipv4addr'])
ipaddr = ipaddr_obj['old_ipv4addr']
except TypeError:
ipaddr = obj_filter['ipv4addr']
test_obj_filter['ipv4addr'] = ipaddr
ib_obj = self.get_object(ib_obj_type, test_obj_filter.copy(), return_fields=list(ib_spec.keys()))
elif (ib_obj_type == NIOS_TXT_RECORD):
# resolves issue where multiple txt_records with same name and different text
test_obj_filter = obj_filter
try:
text_obj = check_type_dict(obj_filter['text'])
txt = text_obj['old_text']
except TypeError:
txt = obj_filter['text']
test_obj_filter['text'] = txt
ib_obj = self.get_object(ib_obj_type, test_obj_filter.copy(), return_fields=list(ib_spec.keys()))
elif (ib_obj_type == NIOS_ZONE):
# del key 'restart_if_needed' as nios_zone get_object fails with the key present
temp = ib_spec['restart_if_needed']
del ib_spec['restart_if_needed']
ib_obj = self.get_object(ib_obj_type, obj_filter.copy(), return_fields=list(ib_spec.keys()))
# reinstate restart_if_needed if ib_obj is none, meaning there's no existing nios_zone ref
if not ib_obj:
ib_spec['restart_if_needed'] = temp
elif (ib_obj_type == NIOS_MEMBER):
# del key 'create_token' as nios_member get_object fails with the key present
temp = ib_spec['create_token']
del ib_spec['create_token']
ib_obj = self.get_object(ib_obj_type, obj_filter.copy(), return_fields=list(ib_spec.keys()))
if temp:
# reinstate 'create_token' key
ib_spec['create_token'] = temp
else:
ib_obj = self.get_object(ib_obj_type, obj_filter.copy(), return_fields=list(ib_spec.keys()))
return ib_obj, update, new_name
def on_update(self, proposed_object, ib_spec):
''' Event called before the update is sent to the API endpoing
This method will allow the final proposed object to be changed
and/or keys filtered before it is sent to the API endpoint to
be processed.
:args proposed_object: A dict item that will be encoded and sent
the API endpoint with the updated data structure
:returns: updated object to be sent to API endpoint
'''
keys = set()
for key, value in iteritems(proposed_object):
update = ib_spec[key].get('update', True)
if not update:
keys.add(key)
return dict([(k, v) for k, v in iteritems(proposed_object) if k not in keys])

View File

@@ -54,6 +54,17 @@ def proxmox_to_ansible_bool(value):
return True if value == 1 else False
def ansible_to_proxmox_bool(value):
'''Convert Ansible representation of a boolean to be proxmox-friendly'''
if value is None:
return None
if not isinstance(value, bool):
raise ValueError("%s must be of type bool not %s" % (value, type(value)))
return 1 if value else 0
class ProxmoxAnsible(object):
"""Base class for Proxmox modules"""
def __init__(self, module):

View File

@@ -1605,9 +1605,6 @@ class RedfishUtils(object):
cur_boot_next = boot.get('BootNext')
cur_override_mode = boot.get('BootSourceOverrideMode')
if not boot_override_mode:
boot_override_mode = cur_override_mode
if override_enabled == 'Disabled':
payload = {
'Boot': {
@@ -1643,16 +1640,18 @@ class RedfishUtils(object):
}
}
else:
if cur_enabled == override_enabled and target == bootdevice and cur_override_mode == boot_override_mode:
if (cur_enabled == override_enabled and target == bootdevice and
(cur_override_mode == boot_override_mode or not boot_override_mode)):
# If properties are already set, no changes needed
return {'ret': True, 'changed': False}
payload = {
'Boot': {
'BootSourceOverrideEnabled': override_enabled,
'BootSourceOverrideMode': boot_override_mode,
'BootSourceOverrideTarget': bootdevice
}
}
if boot_override_mode:
payload['Boot']['BootSourceOverrideMode'] = boot_override_mode
response = self.patch_request(self.root_uri + self.systems_uri, payload)
if response['ret'] is False:
@@ -1835,12 +1834,16 @@ class RedfishUtils(object):
result['ret'] = True
data = response['data']
for device in data[u'Fans']:
fan = {}
for property in properties:
if property in device:
fan[property] = device[property]
fan_results.append(fan)
# Checking if fans are present
if u'Fans' in data:
for device in data[u'Fans']:
fan = {}
for property in properties:
if property in device:
fan[property] = device[property]
fan_results.append(fan)
else:
return {'ret': False, 'msg': "No Fans present"}
result["entries"] = fan_results
return result
@@ -2030,15 +2033,28 @@ class RedfishUtils(object):
def get_multi_memory_inventory(self):
return self.aggregate_systems(self.get_memory_inventory)
def get_nic(self, resource_uri):
result = {}
properties = ['Name', 'Id', 'Description', 'FQDN', 'IPv4Addresses', 'IPv6Addresses',
'NameServers', 'MACAddress', 'PermanentMACAddress',
'SpeedMbps', 'MTUSize', 'AutoNeg', 'Status']
response = self.get_request(self.root_uri + resource_uri)
if response['ret'] is False:
return response
result['ret'] = True
data = response['data']
nic = {}
for property in properties:
if property in data:
nic[property] = data[property]
result['entries'] = nic
return(result)
def get_nic_inventory(self, resource_uri):
result = {}
nic_list = []
nic_results = []
key = "EthernetInterfaces"
# Get these entries, but does not fail if not found
properties = ['Name', 'Id', 'Description', 'FQDN', 'IPv4Addresses', 'IPv6Addresses',
'NameServers', 'MACAddress', 'PermanentMACAddress',
'SpeedMbps', 'MTUSize', 'AutoNeg', 'Status']
response = self.get_request(self.root_uri + resource_uri)
if response['ret'] is False:
@@ -2062,18 +2078,9 @@ class RedfishUtils(object):
nic_list.append(nic[u'@odata.id'])
for n in nic_list:
nic = {}
uri = self.root_uri + n
response = self.get_request(uri)
if response['ret'] is False:
return response
data = response['data']
for property in properties:
if property in data:
nic[property] = data[property]
nic_results.append(nic)
nic = self.get_nic(n)
if nic['ret']:
nic_results.append(nic['entries'])
result["entries"] = nic_results
return result
@@ -2698,39 +2705,14 @@ class RedfishUtils(object):
return self.aggregate_managers(self.get_manager_health_report)
def set_manager_nic(self, nic_addr, nic_config):
# Get EthernetInterface collection
response = self.get_request(self.root_uri + self.manager_uri)
if response['ret'] is False:
return response
data = response['data']
if 'EthernetInterfaces' not in data:
return {'ret': False, 'msg': "EthernetInterfaces resource not found"}
ethernetinterfaces_uri = data["EthernetInterfaces"]["@odata.id"]
response = self.get_request(self.root_uri + ethernetinterfaces_uri)
if response['ret'] is False:
return response
data = response['data']
uris = [a.get('@odata.id') for a in data.get('Members', []) if
a.get('@odata.id')]
# Get the manager ethernet interface uri
nic_info = self.get_manager_ethernet_uri(nic_addr)
# Find target EthernetInterface
target_ethernet_uri = None
target_ethernet_current_setting = None
if nic_addr == 'null':
# Find root_uri matched EthernetInterface when nic_addr is not specified
nic_addr = (self.root_uri).split('/')[-1]
nic_addr = nic_addr.split(':')[0] # split port if existing
for uri in uris:
response = self.get_request(self.root_uri + uri)
if response['ret'] is False:
return response
data = response['data']
if '"' + nic_addr.lower() + '"' in str(data).lower() or "'" + nic_addr.lower() + "'" in str(data).lower():
target_ethernet_uri = uri
target_ethernet_current_setting = data
break
if target_ethernet_uri is None:
return {'ret': False, 'msg': "No matched EthernetInterface found under Manager"}
if nic_info.get('nic_addr') is None:
return nic_info
else:
target_ethernet_uri = nic_info['nic_addr']
target_ethernet_current_setting = nic_info['ethernet_setting']
# Convert input to payload and check validity
payload = {}
@@ -2762,7 +2744,9 @@ class RedfishUtils(object):
if isinstance(set_value, dict):
for subprop in payload[property].keys():
if subprop not in target_ethernet_current_setting[property]:
return {'ret': False, 'msg': "Sub-property %s in nic_config is invalid" % subprop}
# Not configured already; need to apply the request
need_change = True
break
sub_set_value = payload[property][subprop]
sub_cur_value = target_ethernet_current_setting[property][subprop]
if sub_set_value != sub_cur_value:
@@ -2776,7 +2760,9 @@ class RedfishUtils(object):
for i in range(len(set_value)):
for subprop in payload[property][i].keys():
if subprop not in target_ethernet_current_setting[property][i]:
return {'ret': False, 'msg': "Sub-property %s in nic_config is invalid" % subprop}
# Not configured already; need to apply the request
need_change = True
break
sub_set_value = payload[property][i][subprop]
sub_cur_value = target_ethernet_current_setting[property][i][subprop]
if sub_set_value != sub_cur_value:
@@ -2789,3 +2775,208 @@ class RedfishUtils(object):
if response['ret'] is False:
return response
return {'ret': True, 'changed': True, 'msg': "Modified Manager NIC"}
# A helper function to get the EthernetInterface URI
def get_manager_ethernet_uri(self, nic_addr='null'):
# Get EthernetInterface collection
response = self.get_request(self.root_uri + self.manager_uri)
if not response['ret']:
return response
data = response['data']
if 'EthernetInterfaces' not in data:
return {'ret': False, 'msg': "EthernetInterfaces resource not found"}
ethernetinterfaces_uri = data["EthernetInterfaces"]["@odata.id"]
response = self.get_request(self.root_uri + ethernetinterfaces_uri)
if not response['ret']:
return response
data = response['data']
uris = [a.get('@odata.id') for a in data.get('Members', []) if
a.get('@odata.id')]
# Find target EthernetInterface
target_ethernet_uri = None
target_ethernet_current_setting = None
if nic_addr == 'null':
# Find root_uri matched EthernetInterface when nic_addr is not specified
nic_addr = (self.root_uri).split('/')[-1]
nic_addr = nic_addr.split(':')[0] # split port if existing
for uri in uris:
response = self.get_request(self.root_uri + uri)
if not response['ret']:
return response
data = response['data']
data_string = json.dumps(data)
if nic_addr.lower() in data_string.lower():
target_ethernet_uri = uri
target_ethernet_current_setting = data
break
nic_info = {}
nic_info['nic_addr'] = target_ethernet_uri
nic_info['ethernet_setting'] = target_ethernet_current_setting
if target_ethernet_uri is None:
return {}
else:
return nic_info
def set_hostinterface_attributes(self, hostinterface_config, hostinterface_id=None):
response = self.get_request(self.root_uri + self.manager_uri)
if response['ret'] is False:
return response
data = response['data']
if 'HostInterfaces' not in data:
return {'ret': False, 'msg': "HostInterfaces resource not found"}
hostinterfaces_uri = data["HostInterfaces"]["@odata.id"]
response = self.get_request(self.root_uri + hostinterfaces_uri)
if response['ret'] is False:
return response
data = response['data']
uris = [a.get('@odata.id') for a in data.get('Members', []) if a.get('@odata.id')]
# Capture list of URIs that match a specified HostInterface resource ID
if hostinterface_id:
matching_hostinterface_uris = [uri for uri in uris if hostinterface_id in uri.split('/')[-1]]
if hostinterface_id and matching_hostinterface_uris:
hostinterface_uri = list.pop(matching_hostinterface_uris)
elif hostinterface_id and not matching_hostinterface_uris:
return {'ret': False, 'msg': "HostInterface ID %s not present." % hostinterface_id}
elif len(uris) == 1:
hostinterface_uri = list.pop(uris)
else:
return {'ret': False, 'msg': "HostInterface ID not defined and multiple interfaces detected."}
response = self.get_request(self.root_uri + hostinterface_uri)
if response['ret'] is False:
return response
current_hostinterface_config = response['data']
payload = {}
for property in hostinterface_config.keys():
value = hostinterface_config[property]
if property not in current_hostinterface_config:
return {'ret': False, 'msg': "Property %s in hostinterface_config is invalid" % property}
if isinstance(value, dict):
if isinstance(current_hostinterface_config[property], dict):
payload[property] = value
elif isinstance(current_hostinterface_config[property], list):
payload[property] = list()
payload[property].append(value)
else:
return {'ret': False, 'msg': "Value of property %s in hostinterface_config is invalid" % property}
else:
payload[property] = value
need_change = False
for property in payload.keys():
set_value = payload[property]
cur_value = current_hostinterface_config[property]
if not isinstance(set_value, dict) and not isinstance(set_value, list):
if set_value != cur_value:
need_change = True
if isinstance(set_value, dict):
for subprop in payload[property].keys():
if subprop not in current_hostinterface_config[property]:
need_change = True
break
sub_set_value = payload[property][subprop]
sub_cur_value = current_hostinterface_config[property][subprop]
if sub_set_value != sub_cur_value:
need_change = True
if isinstance(set_value, list):
if len(set_value) != len(cur_value):
need_change = True
continue
for i in range(len(set_value)):
for subprop in payload[property][i].keys():
if subprop not in current_hostinterface_config[property][i]:
need_change = True
break
sub_set_value = payload[property][i][subprop]
sub_cur_value = current_hostinterface_config[property][i][subprop]
if sub_set_value != sub_cur_value:
need_change = True
if not need_change:
return {'ret': True, 'changed': False, 'msg': "Host Interface already configured"}
response = self.patch_request(self.root_uri + hostinterface_uri, payload)
if response['ret'] is False:
return response
return {'ret': True, 'changed': True, 'msg': "Modified Host Interface"}
def get_hostinterfaces(self):
result = {}
hostinterface_results = []
properties = ['Id', 'Name', 'Description', 'HostInterfaceType', 'Status',
'InterfaceEnabled', 'ExternallyAccessible', 'AuthenticationModes',
'AuthNoneRoleId', 'CredentialBootstrapping']
manager_uri_list = self.manager_uris
for manager_uri in manager_uri_list:
response = self.get_request(self.root_uri + manager_uri)
if response['ret'] is False:
return response
result['ret'] = True
data = response['data']
if 'HostInterfaces' in data:
hostinterfaces_uri = data[u'HostInterfaces'][u'@odata.id']
else:
continue
response = self.get_request(self.root_uri + hostinterfaces_uri)
data = response['data']
if 'Members' in data:
for hostinterface in data['Members']:
hostinterface_uri = hostinterface['@odata.id']
hostinterface_response = self.get_request(self.root_uri + hostinterface_uri)
# dictionary for capturing individual HostInterface properties
hostinterface_data_temp = {}
if hostinterface_response['ret'] is False:
return hostinterface_response
hostinterface_data = hostinterface_response['data']
for property in properties:
if property in hostinterface_data:
if hostinterface_data[property] is not None:
hostinterface_data_temp[property] = hostinterface_data[property]
# Check for the presence of a ManagerEthernetInterface
# object, a link to a _single_ EthernetInterface that the
# BMC uses to communicate with the host.
if 'ManagerEthernetInterface' in hostinterface_data:
interface_uri = hostinterface_data['ManagerEthernetInterface']['@odata.id']
interface_response = self.get_nic(interface_uri)
if interface_response['ret'] is False:
return interface_response
hostinterface_data_temp['ManagerEthernetInterface'] = interface_response['entries']
# Check for the presence of a HostEthernetInterfaces
# object, a link to a _collection_ of EthernetInterfaces
# that the host uses to communicate with the BMC.
if 'HostEthernetInterfaces' in hostinterface_data:
interfaces_uri = hostinterface_data['HostEthernetInterfaces']['@odata.id']
interfaces_response = self.get_request(self.root_uri + interfaces_uri)
if interfaces_response['ret'] is False:
return interfaces_response
interfaces_data = interfaces_response['data']
if 'Members' in interfaces_data:
for interface in interfaces_data['Members']:
interface_uri = interface['@odata.id']
interface_response = self.get_nic(interface_uri)
if interface_response['ret'] is False:
return interface_response
# Check if this is the first
# HostEthernetInterfaces item and create empty
# list if so.
if 'HostEthernetInterfaces' not in hostinterface_data_temp:
hostinterface_data_temp['HostEthernetInterfaces'] = []
hostinterface_data_temp['HostEthernetInterfaces'].append(interface_response['entries'])
hostinterface_results.append(hostinterface_data_temp)
else:
continue
result["entries"] = hostinterface_results
if not result["entries"]:
return {'ret': False, 'msg': "No HostInterface objects found"}
return result

View File

@@ -0,0 +1,94 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2021, Phillipe Smith <phsmithcc@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
import json
from ansible.module_utils.urls import fetch_url, url_argument_spec
from ansible.module_utils.common.text.converters import to_native
def api_argument_spec():
'''
Creates an argument spec that can be used with any module
that will be requesting content via Rundeck API
'''
api_argument_spec = url_argument_spec()
api_argument_spec.update(dict(
url=dict(required=True, type="str"),
api_version=dict(type="int", default=39),
api_token=dict(required=True, type="str", no_log=True)
))
return api_argument_spec
def api_request(module, endpoint, data=None, method="GET"):
"""Manages Rundeck API requests via HTTP(S)
:arg module: The AnsibleModule (used to get url, api_version, api_token, etc).
:arg endpoint: The API endpoint to be used.
:kwarg data: The data to be sent (in case of POST/PUT).
:kwarg method: "POST", "PUT", etc.
:returns: A tuple of (**response**, **info**). Use ``response.read()`` to read the data.
The **info** contains the 'status' and other meta data. When a HttpError (status >= 400)
occurred then ``info['body']`` contains the error response data::
Example::
data={...}
resp, info = fetch_url(module,
"http://rundeck.example.org",
data=module.jsonify(data),
method="POST")
status_code = info["status"]
body = resp.read()
if status_code >= 400 :
body = info['body']
"""
response, info = fetch_url(
module=module,
url="%s/api/%s/%s" % (
module.params["url"],
module.params["api_version"],
endpoint
),
data=json.dumps(data),
method=method,
headers={
"Content-Type": "application/json",
"Accept": "application/json",
"X-Rundeck-Auth-Token": module.params["api_token"]
}
)
if info["status"] == 403:
module.fail_json(msg="Token authorization failed",
execution_info=json.loads(info["body"]))
if info["status"] == 409:
module.fail_json(msg="Job executions limit reached",
execution_info=json.loads(info["body"]))
elif info["status"] >= 500:
module.fail_json(msg="Rundeck API error",
execution_info=json.loads(info["body"]))
try:
content = response.read()
json_response = json.loads(content)
return json_response, info
except AttributeError as error:
module.fail_json(msg="Rundeck API request error",
exception=to_native(error),
execution_info=info)
except ValueError as error:
module.fail_json(
msg="No valid JSON response",
exception=to_native(error),
execution_info=content
)

View File

@@ -15,13 +15,6 @@ from ansible.module_utils.urls import fetch_url, basic_auth_header
class BitbucketHelper:
BITBUCKET_API_URL = 'https://api.bitbucket.org'
error_messages = {
'required_client_id': '`client_id` must be specified as a parameter or '
'BITBUCKET_CLIENT_ID environment variable',
'required_client_secret': '`client_secret` must be specified as a parameter or '
'BITBUCKET_CLIENT_SECRET environment variable',
}
def __init__(self, module):
self.module = module
self.access_token = None
@@ -29,35 +22,40 @@ class BitbucketHelper:
@staticmethod
def bitbucket_argument_spec():
return dict(
client_id=dict(type='str', no_log=True, fallback=(env_fallback, ['BITBUCKET_CLIENT_ID'])),
client_id=dict(type='str', fallback=(env_fallback, ['BITBUCKET_CLIENT_ID'])),
client_secret=dict(type='str', no_log=True, fallback=(env_fallback, ['BITBUCKET_CLIENT_SECRET'])),
# TODO:
# - Rename user to username once current usage of username is removed
# - Alias user to username and deprecate it
user=dict(type='str', fallback=(env_fallback, ['BITBUCKET_USERNAME'])),
password=dict(type='str', no_log=True, fallback=(env_fallback, ['BITBUCKET_PASSWORD'])),
)
def check_arguments(self):
if self.module.params['client_id'] is None:
self.module.fail_json(msg=self.error_messages['required_client_id'])
@staticmethod
def bitbucket_required_one_of():
return [['client_id', 'client_secret', 'user', 'password']]
if self.module.params['client_secret'] is None:
self.module.fail_json(msg=self.error_messages['required_client_secret'])
@staticmethod
def bitbucket_required_together():
return [['client_id', 'client_secret'], ['user', 'password']]
def fetch_access_token(self):
self.check_arguments()
if self.module.params['client_id'] and self.module.params['client_secret']:
headers = {
'Authorization': basic_auth_header(self.module.params['client_id'], self.module.params['client_secret']),
}
headers = {
'Authorization': basic_auth_header(self.module.params['client_id'], self.module.params['client_secret'])
}
info, content = self.request(
api_url='https://bitbucket.org/site/oauth2/access_token',
method='POST',
data='grant_type=client_credentials',
headers=headers,
)
info, content = self.request(
api_url='https://bitbucket.org/site/oauth2/access_token',
method='POST',
data='grant_type=client_credentials',
headers=headers,
)
if info['status'] == 200:
self.access_token = content['access_token']
else:
self.module.fail_json(msg='Failed to retrieve access token: {0}'.format(info))
if info['status'] == 200:
self.access_token = content['access_token']
else:
self.module.fail_json(msg='Failed to retrieve access token: {0}'.format(info))
def request(self, api_url, method, data=None, headers=None):
headers = headers or {}
@@ -66,6 +64,10 @@ class BitbucketHelper:
headers.update({
'Authorization': 'Bearer {0}'.format(self.access_token),
})
elif self.module.params['user'] and self.module.params['password']:
headers.update({
'Authorization': basic_auth_header(self.module.params['user'], self.module.params['password']),
})
if isinstance(data, dict):
data = self.module.jsonify(data)

View File

@@ -0,0 +1,17 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2021, Felix Fontein <felix@fontein.de>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
"""Provide version object to compare version numbers."""
from __future__ import absolute_import, division, print_function
__metaclass__ = type
# Once we drop support for Ansible 2.9, ansible-base 2.10, and ansible-core 2.11, we can
# remove the _version.py file, and replace the following import by
#
# from ansible.module_utils.compat.version import LooseVersion
from ._version import LooseVersion

1
plugins/modules/cargo.py Symbolic link
View File

@@ -0,0 +1 @@
packaging/language/cargo.py

View File

@@ -120,7 +120,7 @@ __version__ = '${version}'
import os
import traceback
from distutils.version import LooseVersion
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
REQUESTS_IMP_ERR = None
try:

View File

@@ -161,7 +161,8 @@ __version__ = '${version}'
import json
import os
import traceback
from distutils.version import LooseVersion
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
REQUESTS_IMP_ERR = None
try:

View File

@@ -89,7 +89,8 @@ __version__ = '${version}'
import os
import traceback
from distutils.version import LooseVersion
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
REQUESTS_IMP_ERR = None
try:
@@ -132,8 +133,7 @@ class ClcBlueprintPackage:
self.module.fail_json(msg=missing_required_lib('clc-sdk'), exception=CLC_IMP_ERR)
if not REQUESTS_FOUND:
self.module.fail_json(msg=missing_required_lib('requests'), exception=REQUESTS_IMP_ERR)
if requests.__version__ and LooseVersion(
requests.__version__) < LooseVersion('2.5.0'):
if requests.__version__ and LooseVersion(requests.__version__) < LooseVersion('2.5.0'):
self.module.fail_json(
msg='requests library version should be >= 2.5.0')

View File

@@ -162,7 +162,8 @@ import os
import traceback
from ansible.module_utils.six.moves.urllib.parse import urlparse
from time import sleep
from distutils.version import LooseVersion
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
REQUESTS_IMP_ERR = None
try:
@@ -203,8 +204,7 @@ class ClcFirewallPolicy:
self.module.fail_json(msg=missing_required_lib('clc-sdk'), exception=CLC_IMP_ERR)
if not REQUESTS_FOUND:
self.module.fail_json(msg=missing_required_lib('requests'), exception=REQUESTS_IMP_ERR)
if requests.__version__ and LooseVersion(
requests.__version__) < LooseVersion('2.5.0'):
if requests.__version__ and LooseVersion(requests.__version__) < LooseVersion('2.5.0'):
self.module.fail_json(
msg='requests library version should be >= 2.5.0')

View File

@@ -207,7 +207,8 @@ __version__ = '${version}'
import os
import traceback
from distutils.version import LooseVersion
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
REQUESTS_IMP_ERR = None
try:

View File

@@ -210,7 +210,8 @@ import json
import os
import traceback
from time import sleep
from distutils.version import LooseVersion
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
REQUESTS_IMP_ERR = None
try:
@@ -255,8 +256,7 @@ class ClcLoadBalancer:
self.module.fail_json(msg=missing_required_lib('clc-sdk'), exception=CLC_IMP_ERR)
if not REQUESTS_FOUND:
self.module.fail_json(msg=missing_required_lib('requests'), exception=REQUESTS_IMP_ERR)
if requests.__version__ and LooseVersion(
requests.__version__) < LooseVersion('2.5.0'):
if requests.__version__ and LooseVersion(requests.__version__) < LooseVersion('2.5.0'):
self.module.fail_json(
msg='requests library version should be >= 2.5.0')

View File

@@ -311,7 +311,8 @@ __version__ = '${version}'
import json
import os
import traceback
from distutils.version import LooseVersion
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
REQUESTS_IMP_ERR = None
try:
@@ -355,8 +356,7 @@ class ClcModifyServer:
self.module.fail_json(msg=missing_required_lib('clc-sdk'), exception=CLC_IMP_ERR)
if not REQUESTS_FOUND:
self.module.fail_json(msg=missing_required_lib('requests'), exception=REQUESTS_IMP_ERR)
if requests.__version__ and LooseVersion(
requests.__version__) < LooseVersion('2.5.0'):
if requests.__version__ and LooseVersion(requests.__version__) < LooseVersion('2.5.0'):
self.module.fail_json(
msg='requests library version should be >= 2.5.0')

View File

@@ -117,7 +117,8 @@ __version__ = '${version}'
import os
import traceback
from distutils.version import LooseVersion
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
REQUESTS_IMP_ERR = None
try:

View File

@@ -433,7 +433,8 @@ import json
import os
import time
import traceback
from distutils.version import LooseVersion
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
REQUESTS_IMP_ERR = None
try:
@@ -478,8 +479,7 @@ class ClcServer:
self.module.fail_json(msg=missing_required_lib('clc-sdk'), exception=CLC_IMP_ERR)
if not REQUESTS_FOUND:
self.module.fail_json(msg=missing_required_lib('requests'), exception=REQUESTS_IMP_ERR)
if requests.__version__ and LooseVersion(
requests.__version__) < LooseVersion('2.5.0'):
if requests.__version__ and LooseVersion(requests.__version__) < LooseVersion('2.5.0'):
self.module.fail_json(
msg='requests library version should be >= 2.5.0')

View File

@@ -101,7 +101,8 @@ __version__ = '${version}'
import os
import traceback
from distutils.version import LooseVersion
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
REQUESTS_IMP_ERR = None
try:
@@ -145,8 +146,7 @@ class ClcSnapshot:
self.module.fail_json(msg=missing_required_lib('clc-sdk'), exception=CLC_IMP_ERR)
if not REQUESTS_FOUND:
self.module.fail_json(msg=missing_required_lib('requests'), exception=REQUESTS_IMP_ERR)
if requests.__version__ and LooseVersion(
requests.__version__) < LooseVersion('2.5.0'):
if requests.__version__ and LooseVersion(requests.__version__) < LooseVersion('2.5.0'):
self.module.fail_json(
msg='requests library version should be >= 2.5.0')

View File

@@ -422,6 +422,7 @@ import shutil
import subprocess
import tempfile
import time
import shlex
try:
import lxc
@@ -661,9 +662,8 @@ class LxcContainerManagement(object):
"""
for key, value in variables_dict.items():
build_command.append(
'%s %s' % (key, value)
)
build_command.append(str(key))
build_command.append(str(value))
return build_command
def _get_vars(self, variables):
@@ -686,24 +686,6 @@ class LxcContainerManagement(object):
return_dict[v] = _var
return return_dict
def _run_command(self, build_command, unsafe_shell=False):
"""Return information from running an Ansible Command.
This will squash the build command list into a string and then
execute the command via Ansible. The output is returned to the method.
This output is returned as `return_code`, `stdout`, `stderr`.
:param build_command: Used for the command and all options.
:type build_command: ``list``
:param unsafe_shell: Enable or Disable unsafe sell commands.
:type unsafe_shell: ``bol``
"""
return self.module.run_command(
' '.join(build_command),
use_unsafe_shell=unsafe_shell
)
def _config(self):
"""Configure an LXC container.
@@ -810,7 +792,7 @@ class LxcContainerManagement(object):
elif self.module.params.get('backing_store') == 'overlayfs':
build_command.append('--snapshot')
rc, return_data, err = self._run_command(build_command)
rc, return_data, err = self.module.run_command(build_command)
if rc != 0:
message = "Failed executing %s." % os.path.basename(clone_cmd)
self.failure(
@@ -843,7 +825,7 @@ class LxcContainerManagement(object):
build_command = [
self.module.get_bin_path('lxc-create', True),
'--name %s' % self.container_name,
'--name', self.container_name,
'--quiet'
]
@@ -869,10 +851,12 @@ class LxcContainerManagement(object):
log_path = os.getenv('HOME')
build_command.extend([
'--logfile %s' % os.path.join(
'--logfile',
os.path.join(
log_path, 'lxc-%s.log' % self.container_name
),
'--logpriority %s' % self.module.params.get(
'--logpriority',
self.module.params.get(
'container_log_level'
).upper()
])
@@ -880,9 +864,10 @@ class LxcContainerManagement(object):
# Add the template commands to the end of the command if there are any
template_options = self.module.params.get('template_options', None)
if template_options:
build_command.append('-- %s' % template_options)
build_command.append('--')
build_command += shlex.split(template_options)
rc, return_data, err = self._run_command(build_command)
rc, return_data, err = self.module.run_command(build_command)
if rc != 0:
message = "Failed executing lxc-create."
self.failure(
@@ -1186,7 +1171,7 @@ class LxcContainerManagement(object):
self.module.get_bin_path('lxc-config', True),
"lxc.bdev.lvm.vg"
]
rc, vg, err = self._run_command(build_command)
rc, vg, err = self.module.run_command(build_command)
if rc != 0:
self.failure(
err=err,
@@ -1204,7 +1189,7 @@ class LxcContainerManagement(object):
build_command = [
self.module.get_bin_path('lvs', True)
]
rc, stdout, err = self._run_command(build_command)
rc, stdout, err = self.module.run_command(build_command)
if rc != 0:
self.failure(
err=err,
@@ -1231,7 +1216,7 @@ class LxcContainerManagement(object):
'--units',
'g'
]
rc, stdout, err = self._run_command(build_command)
rc, stdout, err = self.module.run_command(build_command)
if rc != 0:
self.failure(
err=err,
@@ -1262,7 +1247,7 @@ class LxcContainerManagement(object):
'--units',
'g'
]
rc, stdout, err = self._run_command(build_command)
rc, stdout, err = self.module.run_command(build_command)
if rc != 0:
self.failure(
err=err,
@@ -1311,7 +1296,7 @@ class LxcContainerManagement(object):
os.path.join(vg, source_lv),
"-L%sg" % snapshot_size_gb
]
rc, stdout, err = self._run_command(build_command)
rc, stdout, err = self.module.run_command(build_command)
if rc != 0:
self.failure(
err=err,
@@ -1336,7 +1321,7 @@ class LxcContainerManagement(object):
"/dev/%s/%s" % (vg, lv_name),
mount_point,
]
rc, stdout, err = self._run_command(build_command)
rc, stdout, err = self.module.run_command(build_command)
if rc != 0:
self.failure(
err=err,
@@ -1380,9 +1365,8 @@ class LxcContainerManagement(object):
'.'
]
rc, stdout, err = self._run_command(
build_command=build_command,
unsafe_shell=True
rc, stdout, err = self.module.run_command(
build_command
)
os.umask(old_umask)
@@ -1410,7 +1394,7 @@ class LxcContainerManagement(object):
"-f",
"%s/%s" % (vg, lv_name),
]
rc, stdout, err = self._run_command(build_command)
rc, stdout, err = self.module.run_command(build_command)
if rc != 0:
self.failure(
err=err,
@@ -1442,11 +1426,10 @@ class LxcContainerManagement(object):
self.module.get_bin_path('rsync', True),
'-aHAX',
fs_path,
temp_dir
temp_dir,
]
rc, stdout, err = self._run_command(
rc, stdout, err = self.module.run_command(
build_command,
unsafe_shell=True
)
if rc != 0:
self.failure(
@@ -1467,7 +1450,7 @@ class LxcContainerManagement(object):
self.module.get_bin_path('umount', True),
mount_point,
]
rc, stdout, err = self._run_command(build_command)
rc, stdout, err = self.module.run_command(build_command)
if rc != 0:
self.failure(
err=err,
@@ -1489,12 +1472,12 @@ class LxcContainerManagement(object):
build_command = [
self.module.get_bin_path('mount', True),
'-t overlayfs',
'-o lowerdir=%s,upperdir=%s' % (lowerdir, upperdir),
'-t', 'overlayfs',
'-o', 'lowerdir=%s,upperdir=%s' % (lowerdir, upperdir),
'overlayfs',
mount_point,
]
rc, stdout, err = self._run_command(build_command)
rc, stdout, err = self.module.run_command(build_command)
if rc != 0:
self.failure(
err=err,

View File

@@ -11,29 +11,28 @@ __metaclass__ = type
DOCUMENTATION = '''
---
module: lxd_container
short_description: Manage LXD Containers
short_description: Manage LXD instances
description:
- Management of LXD containers
- Management of LXD containers and virtual machines.
author: "Hiroaki Nakamura (@hnakamur)"
options:
name:
description:
- Name of a container.
- Name of an instance.
type: str
required: true
architecture:
description:
- The architecture for the container (e.g. "x86_64" or "i686").
See U(https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-1)
- 'The architecture for the instance (for example C(x86_64) or C(i686)).
See U(https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-1).'
type: str
required: false
config:
description:
- 'The config for the container (e.g. {"limits.cpu": "2"}).
See U(https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-1)'
- If the container already exists and its "config" values in metadata
obtained from GET /1.0/containers/<name>
U(https://github.com/lxc/lxd/blob/master/doc/rest-api.md#10containersname)
- 'The config for the instance (for example C({"limits.cpu": "2"})).
See U(https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-1).'
- If the instance already exists and its "config" values in metadata
obtained from the LXD API U(https://github.com/lxc/lxd/blob/master/doc/rest-api.md#instances-containers-and-virtual-machines)
are different, this module tries to apply the configurations.
- The keys starting with C(volatile.) are ignored for this comparison when I(ignore_volatile_options=true).
type: dict
@@ -43,40 +42,39 @@ options:
- If set to C(true), options starting with C(volatile.) are ignored. As a result,
they are reapplied for each execution.
- This default behavior can be changed by setting this option to C(false).
- The default value C(true) will be deprecated in community.general 4.0.0,
and will change to C(false) in community.general 5.0.0.
- The current default value C(true) is deprecated since community.general 4.0.0,
and will change to C(false) in community.general 6.0.0.
type: bool
default: true
required: false
version_added: 3.7.0
profiles:
description:
- Profile to be used by the container
- Profile to be used by the instance.
type: list
elements: str
devices:
description:
- 'The devices for the container
(e.g. { "rootfs": { "path": "/dev/kvm", "type": "unix-char" }).
See U(https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-1)'
- 'The devices for the instance
(for example C({ "rootfs": { "path": "/dev/kvm", "type": "unix-char" }})).
See U(https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-1).'
type: dict
required: false
ephemeral:
description:
- Whether or not the container is ephemeral (e.g. true or false).
See U(https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-1)
- Whether or not the instance is ephemeral (for example C(true) or C(false)).
See U(https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-1).
required: false
type: bool
source:
description:
- 'The source for the container
- 'The source for the instance
(e.g. { "type": "image",
"mode": "pull",
"server": "https://images.linuxcontainers.org",
"protocol": "lxd",
"alias": "ubuntu/xenial/amd64" }).'
- 'See U(https://github.com/lxc/lxd/blob/master/doc/rest-api.md#post-1) for complete API documentation.'
- 'Note that C(protocol) accepts two choices: C(lxd) or C(simplestreams)'
- 'Note that C(protocol) accepts two choices: C(lxd) or C(simplestreams).'
required: false
type: dict
state:
@@ -87,39 +85,49 @@ options:
- absent
- frozen
description:
- Define the state of a container.
- Define the state of an instance.
required: false
default: started
type: str
target:
description:
- For cluster deployments. Will attempt to create a container on a target node.
If container exists elsewhere in a cluster, then container will not be replaced or moved.
- For cluster deployments. Will attempt to create an instance on a target node.
If the instance exists elsewhere in a cluster, then it will not be replaced or moved.
The name should respond to same name of the node you see in C(lxc cluster list).
type: str
required: false
version_added: 1.0.0
timeout:
description:
- A timeout for changing the state of the container.
- A timeout for changing the state of the instance.
- This is also used as a timeout for waiting until IPv4 addresses
are set to the all network interfaces in the container after
are set to the all network interfaces in the instance after
starting or restarting.
required: false
default: 30
type: int
type:
description:
- Instance type can be either C(virtual-machine) or C(container).
required: false
default: container
choices:
- container
- virtual-machine
type: str
version_added: 4.1.0
wait_for_ipv4_addresses:
description:
- If this is true, the C(lxd_container) waits until IPv4 addresses
are set to the all network interfaces in the container after
are set to the all network interfaces in the instance after
starting or restarting.
required: false
default: false
type: bool
force_stop:
description:
- If this is true, the C(lxd_container) forces to stop the container
when it stops or restarts the container.
- If this is true, the C(lxd_container) forces to stop the instance
when it stops or restarts the instance.
required: false
default: false
type: bool
@@ -152,27 +160,27 @@ options:
trust_password:
description:
- The client trusted password.
- You need to set this password on the LXD server before
running this module using the following command.
lxc config set core.trust_password <some random password>
See U(https://www.stgraber.org/2016/04/18/lxd-api-direct-interaction/)
- 'You need to set this password on the LXD server before
running this module using the following command:
C(lxc config set core.trust_password <some random password>).
See U(https://www.stgraber.org/2016/04/18/lxd-api-direct-interaction/).'
- If trust_password is set, this module send a request for
authentication before sending any requests.
required: false
type: str
notes:
- Containers must have a unique name. If you attempt to create a container
- Instances can be a container or a virtual machine, both of them must have unique name. If you attempt to create an instance
with a name that already existed in the users namespace the module will
simply return as "unchanged".
- There are two ways to run commands in containers, using the command
- There are two ways to run commands inside a container or virtual machine, using the command
module or using the ansible lxd connection plugin bundled in Ansible >=
2.1, the later requires python to be installed in the container which can
2.1, the later requires python to be installed in the instance which can
be done with the command module.
- You can copy a file from the host to the container
- You can copy a file from the host to the instance
with the Ansible M(ansible.builtin.copy) and M(ansible.builtin.template) module and the `lxd` connection plugin.
See the example below.
- You can copy a file in the created container to the localhost
with `command=lxc file pull container_name/dir/filename filename`.
- You can copy a file in the created instance to the localhost
with `command=lxc file pull instance_name/dir/filename filename`.
See the first example below.
'''
@@ -241,6 +249,7 @@ EXAMPLES = '''
community.general.lxd_container:
name: mycontainer
state: absent
type: container
# An example for restarting a container
- hosts: localhost
@@ -250,6 +259,7 @@ EXAMPLES = '''
community.general.lxd_container:
name: mycontainer
state: restarted
type: container
# An example for restarting a container using https to connect to the LXD server
- hosts: localhost
@@ -307,16 +317,36 @@ EXAMPLES = '''
mode: pull
alias: ubuntu/xenial/amd64
target: node02
# An example for creating a virtual machine
- hosts: localhost
connection: local
tasks:
- name: Create container on another node
community.general.lxd_container:
name: new-vm-1
type: virtual-machine
state: started
ignore_volatile_options: true
wait_for_ipv4_addresses: true
profiles: ["default"]
source:
protocol: simplestreams
type: image
mode: pull
server: https://images.linuxcontainers.org
alias: debian/11
timeout: 600
'''
RETURN = '''
addresses:
description: Mapping from the network device name to a list of IPv4 addresses in the container
description: Mapping from the network device name to a list of IPv4 addresses in the instance.
returned: when state is started or restarted
type: dict
sample: {"eth0": ["10.155.92.191"]}
old_state:
description: The old state of the container
description: The old state of the instance.
returned: when state is started or restarted
type: str
sample: "stopped"
@@ -326,7 +356,7 @@ logs:
type: list
sample: "(too long to be placed here)"
actions:
description: List of actions performed for the container.
description: List of actions performed for the instance.
returned: success
type: list
sample: '["create", "start"]'
@@ -385,6 +415,15 @@ class LXDContainerManagement(object):
self.addresses = None
self.target = self.module.params['target']
self.type = self.module.params['type']
# LXD Rest API provides additional endpoints for creating containers and virtual-machines.
self.api_endpoint = None
if self.type == 'container':
self.api_endpoint = '/1.0/containers'
elif self.type == 'virtual-machine':
self.api_endpoint = '/1.0/virtual-machines'
self.key_file = self.module.params.get('client_key')
if self.key_file is None:
self.key_file = '{0}/.config/lxc/client.key'.format(os.environ['HOME'])
@@ -420,20 +459,20 @@ class LXDContainerManagement(object):
if param_val is not None:
self.config[attr] = param_val
def _get_container_json(self):
def _get_instance_json(self):
return self.client.do(
'GET', '/1.0/containers/{0}'.format(self.name),
'GET', '{0}/{1}'.format(self.api_endpoint, self.name),
ok_error_codes=[404]
)
def _get_container_state_json(self):
def _get_instance_state_json(self):
return self.client.do(
'GET', '/1.0/containers/{0}/state'.format(self.name),
'GET', '{0}/{1}/state'.format(self.api_endpoint, self.name),
ok_error_codes=[404]
)
@staticmethod
def _container_json_to_module_state(resp_json):
def _instance_json_to_module_state(resp_json):
if resp_json['type'] == 'error':
return 'absent'
return ANSIBLE_LXD_STATES[resp_json['metadata']['status']]
@@ -442,45 +481,45 @@ class LXDContainerManagement(object):
body_json = {'action': action, 'timeout': self.timeout}
if force_stop:
body_json['force'] = True
return self.client.do('PUT', '/1.0/containers/{0}/state'.format(self.name), body_json=body_json)
return self.client.do('PUT', '{0}/{1}/state'.format(self.api_endpoint, self.name), body_json=body_json)
def _create_container(self):
def _create_instance(self):
config = self.config.copy()
config['name'] = self.name
if self.target:
self.client.do('POST', '/1.0/containers?' + urlencode(dict(target=self.target)), config)
self.client.do('POST', '{0}?{1}'.format(self.api_endpoint, urlencode(dict(target=self.target))), config)
else:
self.client.do('POST', '/1.0/containers', config)
self.client.do('POST', self.api_endpoint, config)
self.actions.append('create')
def _start_container(self):
def _start_instance(self):
self._change_state('start')
self.actions.append('start')
def _stop_container(self):
def _stop_instance(self):
self._change_state('stop', self.force_stop)
self.actions.append('stop')
def _restart_container(self):
def _restart_instance(self):
self._change_state('restart', self.force_stop)
self.actions.append('restart')
def _delete_container(self):
self.client.do('DELETE', '/1.0/containers/{0}'.format(self.name))
def _delete_instance(self):
self.client.do('DELETE', '{0}/{1}'.format(self.api_endpoint, self.name))
self.actions.append('delete')
def _freeze_container(self):
def _freeze_instance(self):
self._change_state('freeze')
self.actions.append('freeze')
def _unfreeze_container(self):
def _unfreeze_instance(self):
self._change_state('unfreeze')
self.actions.append('unfreez')
def _container_ipv4_addresses(self, ignore_devices=None):
def _instance_ipv4_addresses(self, ignore_devices=None):
ignore_devices = ['lo'] if ignore_devices is None else ignore_devices
resp_json = self._get_container_state_json()
resp_json = self._get_instance_state_json()
network = resp_json['metadata']['network'] or {}
network = dict((k, v) for k, v in network.items() if k not in ignore_devices) or {}
addresses = dict((k, [a['address'] for a in v['addresses'] if a['family'] == 'inet']) for k, v in network.items()) or {}
@@ -495,7 +534,7 @@ class LXDContainerManagement(object):
due = datetime.datetime.now() + datetime.timedelta(seconds=self.timeout)
while datetime.datetime.now() < due:
time.sleep(1)
addresses = self._container_ipv4_addresses()
addresses = self._instance_ipv4_addresses()
if self._has_all_ipv4_addresses(addresses):
self.addresses = addresses
return
@@ -505,72 +544,72 @@ class LXDContainerManagement(object):
def _started(self):
if self.old_state == 'absent':
self._create_container()
self._start_container()
self._create_instance()
self._start_instance()
else:
if self.old_state == 'frozen':
self._unfreeze_container()
self._unfreeze_instance()
elif self.old_state == 'stopped':
self._start_container()
if self._needs_to_apply_container_configs():
self._apply_container_configs()
self._start_instance()
if self._needs_to_apply_instance_configs():
self._apply_instance_configs()
if self.wait_for_ipv4_addresses:
self._get_addresses()
def _stopped(self):
if self.old_state == 'absent':
self._create_container()
self._create_instance()
else:
if self.old_state == 'stopped':
if self._needs_to_apply_container_configs():
self._start_container()
self._apply_container_configs()
self._stop_container()
if self._needs_to_apply_instance_configs():
self._start_instance()
self._apply_instance_configs()
self._stop_instance()
else:
if self.old_state == 'frozen':
self._unfreeze_container()
if self._needs_to_apply_container_configs():
self._apply_container_configs()
self._stop_container()
self._unfreeze_instance()
if self._needs_to_apply_instance_configs():
self._apply_instance_configs()
self._stop_instance()
def _restarted(self):
if self.old_state == 'absent':
self._create_container()
self._start_container()
self._create_instance()
self._start_instance()
else:
if self.old_state == 'frozen':
self._unfreeze_container()
if self._needs_to_apply_container_configs():
self._apply_container_configs()
self._restart_container()
self._unfreeze_instance()
if self._needs_to_apply_instance_configs():
self._apply_instance_configs()
self._restart_instance()
if self.wait_for_ipv4_addresses:
self._get_addresses()
def _destroyed(self):
if self.old_state != 'absent':
if self.old_state == 'frozen':
self._unfreeze_container()
self._unfreeze_instance()
if self.old_state != 'stopped':
self._stop_container()
self._delete_container()
self._stop_instance()
self._delete_instance()
def _frozen(self):
if self.old_state == 'absent':
self._create_container()
self._start_container()
self._freeze_container()
self._create_instance()
self._start_instance()
self._freeze_instance()
else:
if self.old_state == 'stopped':
self._start_container()
if self._needs_to_apply_container_configs():
self._apply_container_configs()
self._freeze_container()
self._start_instance()
if self._needs_to_apply_instance_configs():
self._apply_instance_configs()
self._freeze_instance()
def _needs_to_change_container_config(self, key):
def _needs_to_change_instance_config(self, key):
if key not in self.config:
return False
if key == 'config' and self.ignore_volatile_options: # the old behavior is to ignore configurations by keyword "volatile"
old_configs = dict((k, v) for k, v in self.old_container_json['metadata'][key].items() if not k.startswith('volatile.'))
old_configs = dict((k, v) for k, v in self.old_instance_json['metadata'][key].items() if not k.startswith('volatile.'))
for k, v in self.config['config'].items():
if k not in old_configs:
return True
@@ -578,7 +617,7 @@ class LXDContainerManagement(object):
return True
return False
elif key == 'config': # next default behavior
old_configs = dict((k, v) for k, v in self.old_container_json['metadata'][key].items())
old_configs = dict((k, v) for k, v in self.old_instance_json['metadata'][key].items())
for k, v in self.config['config'].items():
if k not in old_configs:
return True
@@ -586,39 +625,41 @@ class LXDContainerManagement(object):
return True
return False
else:
old_configs = self.old_container_json['metadata'][key]
old_configs = self.old_instance_json['metadata'][key]
return self.config[key] != old_configs
def _needs_to_apply_container_configs(self):
def _needs_to_apply_instance_configs(self):
return (
self._needs_to_change_container_config('architecture') or
self._needs_to_change_container_config('config') or
self._needs_to_change_container_config('ephemeral') or
self._needs_to_change_container_config('devices') or
self._needs_to_change_container_config('profiles')
self._needs_to_change_instance_config('architecture') or
self._needs_to_change_instance_config('config') or
self._needs_to_change_instance_config('ephemeral') or
self._needs_to_change_instance_config('devices') or
self._needs_to_change_instance_config('profiles')
)
def _apply_container_configs(self):
old_metadata = self.old_container_json['metadata']
def _apply_instance_configs(self):
old_metadata = self.old_instance_json['metadata']
body_json = {
'architecture': old_metadata['architecture'],
'config': old_metadata['config'],
'devices': old_metadata['devices'],
'profiles': old_metadata['profiles']
}
if self._needs_to_change_container_config('architecture'):
if self._needs_to_change_instance_config('architecture'):
body_json['architecture'] = self.config['architecture']
if self._needs_to_change_container_config('config'):
if self._needs_to_change_instance_config('config'):
for k, v in self.config['config'].items():
body_json['config'][k] = v
if self._needs_to_change_container_config('ephemeral'):
if self._needs_to_change_instance_config('ephemeral'):
body_json['ephemeral'] = self.config['ephemeral']
if self._needs_to_change_container_config('devices'):
if self._needs_to_change_instance_config('devices'):
body_json['devices'] = self.config['devices']
if self._needs_to_change_container_config('profiles'):
if self._needs_to_change_instance_config('profiles'):
body_json['profiles'] = self.config['profiles']
self.client.do('PUT', '/1.0/containers/{0}'.format(self.name), body_json=body_json)
self.actions.append('apply_container_configs')
self.client.do('PUT', '{0}/{1}'.format(self.api_endpoint, self.name), body_json=body_json)
self.actions.append('apply_instance_configs')
def run(self):
"""Run the main method."""
@@ -628,8 +669,8 @@ class LXDContainerManagement(object):
self.client.authenticate(self.trust_password)
self.ignore_volatile_options = self.module.params.get('ignore_volatile_options')
self.old_container_json = self._get_container_json()
self.old_state = self._container_json_to_module_state(self.old_container_json)
self.old_instance_json = self._get_instance_json()
self.old_state = self._instance_json_to_module_state(self.old_instance_json)
action = getattr(self, LXD_ANSIBLE_STATES[self.state])
action()
@@ -674,7 +715,6 @@ def main():
),
ignore_volatile_options=dict(
type='bool',
default=True
),
devices=dict(
type='dict',
@@ -700,6 +740,11 @@ def main():
type='int',
default=30
),
type=dict(
type='str',
default='container',
choices=['container', 'virtual-machine'],
),
wait_for_ipv4_addresses=dict(
type='bool',
default=False
@@ -728,13 +773,17 @@ def main():
),
supports_check_mode=False,
)
# if module.params['ignore_volatile_options'] is None:
# module.params['ignore_volatile_options'] = True
# module.deprecate(
# 'If the keyword "volatile" is used in a playbook in the config section, a
# "changed" message will appear with every run, even without a change to the playbook.
# This will change in the future.
# Please test your scripts by "ignore_volatile_options: false"', version='5.0.0', collection_name='community.general')
if module.params['ignore_volatile_options'] is None:
module.params['ignore_volatile_options'] = True
module.deprecate(
'If the keyword "volatile" is used in a playbook in the config'
'section, a "changed" message will appear with every run, even without a change'
'to the playbook.'
'This will change in the future. Please test your scripts'
'by "ignore_volatile_options: false". To keep the old behavior, set that option explicitly to "true"',
version='6.0.0', collection_name='community.general')
lxd_manage = LXDContainerManagement(module=module)
lxd_manage.run()

View File

@@ -13,7 +13,7 @@ short_description: management of instances in Proxmox VE cluster
description:
- allows you to create/delete/stop instances in Proxmox VE cluster
- Starting in Ansible 2.1, it automatically detects containerization type (lxc for PVE 4, openvz for older)
- From community.general 4.0.0 on, there will be no default values, see I(proxmox_default_behavior).
- Since community.general 4.0.0 on, there are no more default values, see I(proxmox_default_behavior).
options:
password:
description:
@@ -40,37 +40,27 @@ options:
comma-delimited list C([volume=]<volume> [,acl=<1|0>] [,mountoptions=<opt[;opt...]>] [,quota=<1|0>]
[,replicate=<1|0>] [,ro=<1|0>] [,shared=<1|0>] [,size=<DiskSize>])."
- See U(https://pve.proxmox.com/wiki/Linux_Container) for a full description.
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(3). Note that the default value of I(proxmox_default_behavior)
changes in community.general 4.0.0.
- This option has no default unless I(proxmox_default_behavior) is set to C(compatiblity); then the default is C(3).
type: str
cores:
description:
- Specify number of cores per socket.
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(1). Note that the default value of I(proxmox_default_behavior)
changes in community.general 4.0.0.
- This option has no default unless I(proxmox_default_behavior) is set to C(compatiblity); then the default is C(1).
type: int
cpus:
description:
- numbers of allocated cpus for instance
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(1). Note that the default value of I(proxmox_default_behavior)
changes in community.general 4.0.0.
- This option has no default unless I(proxmox_default_behavior) is set to C(compatiblity); then the default is C(1).
type: int
memory:
description:
- memory size in MB for instance
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(512). Note that the default value of I(proxmox_default_behavior)
changes in community.general 4.0.0.
- This option has no default unless I(proxmox_default_behavior) is set to C(compatiblity); then the default is C(512).
type: int
swap:
description:
- swap memory size in MB for instance
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(0). Note that the default value of I(proxmox_default_behavior)
changes in community.general 4.0.0.
- This option has no default unless I(proxmox_default_behavior) is set to C(compatiblity); then the default is C(0).
type: int
netif:
description:
@@ -94,9 +84,7 @@ options:
onboot:
description:
- specifies whether a VM will be started during system bootup
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(no). Note that the default value of I(proxmox_default_behavior)
changes in community.general 4.0.0.
- This option has no default unless I(proxmox_default_behavior) is set to C(compatiblity); then the default is C(no).
type: bool
storage:
description:
@@ -106,9 +94,7 @@ options:
cpuunits:
description:
- CPU weight for a VM
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(1000). Note that the default value of I(proxmox_default_behavior)
changes in community.general 4.0.0.
- This option has no default unless I(proxmox_default_behavior) is set to C(compatiblity); then the default is C(1000).
type: int
nameserver:
description:
@@ -168,20 +154,38 @@ options:
version_added: '0.2.0'
proxmox_default_behavior:
description:
- Various module options used to have default values. This cause problems when
user expects different behavior from proxmox by default or fill options which cause
problems when they have been set.
- The default value is C(compatibility), which will ensure that the default values
are used when the values are not explicitly specified by the user.
- From community.general 4.0.0 on, the default value will switch to C(no_defaults). To avoid
deprecation warnings, please set I(proxmox_default_behavior) to an explicit
value.
- As of community.general 4.0.0, various options no longer have default values.
These default values caused problems when users expected different behavior from Proxmox
by default or filled options which caused problems when set.
- The value C(compatibility) (default before community.general 4.0.0) will ensure that the default values
are used when the values are not explicitly specified by the user. The new default is C(no_defaults),
which makes sure these options have no defaults.
- This affects the I(disk), I(cores), I(cpus), I(memory), I(onboot), I(swap), I(cpuunits) options.
type: str
default: no_defaults
choices:
- compatibility
- no_defaults
version_added: "1.3.0"
clone:
description:
- ID of the container to be cloned.
- I(description), I(hostname), and I(pool) will be copied from the cloned container if not specified.
- The type of clone created is defined by the I(clone_type) parameter.
- This operator is only supported for Proxmox clusters that use LXC containerization (PVE version >= 4).
type: int
version_added: 4.3.0
clone_type:
description:
- Type of the clone created.
- C(full) creates a full clone, and I(storage) must be specified.
- C(linked) creates a linked clone, and the cloned container must be a template container.
- C(opportunistic) creates a linked clone if the cloned container is a template container, and a full clone if not.
I(storage) may be specified, if not it will fall back to the default.
type: str
choices: ['full', 'linked', 'opportunistic']
default: opportunistic
version_added: 4.3.0
author: Sergei Antipov (@UnderGreen)
extends_documentation_fragment:
- community.general.proxmox.documentation
@@ -307,6 +311,28 @@ EXAMPLES = r'''
- nesting=1
- mount=cifs,nfs
- name: >
Create a linked clone of the template container with id 100. The newly created container with be a
linked clone, because no storage parameter is defined
community.general.proxmox:
vmid: 201
node: uk-mc02
api_user: root@pam
api_password: 1q2w3e
api_host: node1
clone: 100
hostname: clone.example.org
- name: Create a full clone of the container with id 100
community.general.proxmox:
vmid: 201
node: uk-mc02
api_user: root@pam
api_password: 1q2w3e
api_host: node1
clone: 100
hostname: clone.example.org
storage: local
- name: Start container
community.general.proxmox:
@@ -363,7 +389,8 @@ EXAMPLES = r'''
import time
import traceback
from distutils.version import LooseVersion
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
try:
from proxmoxer import ProxmoxAPI
@@ -374,6 +401,10 @@ except ImportError:
from ansible.module_utils.basic import AnsibleModule, env_fallback
from ansible.module_utils.common.text.converters import to_native
from ansible_collections.community.general.plugins.module_utils.proxmox import (
ansible_to_proxmox_bool
)
VZ_TYPE = None
@@ -399,6 +430,13 @@ def content_check(proxmox, node, ostemplate, template_store):
return [True for cnt in proxmox.nodes(node).storage(template_store).content.get() if cnt['volid'] == ostemplate]
def is_template_container(proxmox, node, vmid):
"""Check if the specified container is a template."""
proxmox_node = proxmox.nodes(node)
config = getattr(proxmox_node, VZ_TYPE)(vmid).config.get()
return config['template']
def node_check(proxmox, node):
return [True for nd in proxmox.nodes.get() if nd['node'] == node]
@@ -408,8 +446,10 @@ def proxmox_version(proxmox):
return LooseVersion(apireturn['version'])
def create_instance(module, proxmox, vmid, node, disk, storage, cpus, memory, swap, timeout, **kwargs):
def create_instance(module, proxmox, vmid, node, disk, storage, cpus, memory, swap, timeout, clone, **kwargs):
proxmox_node = proxmox.nodes(node)
# Remove all empty kwarg entries
kwargs = dict((k, v) for k, v in kwargs.items() if v is not None)
if VZ_TYPE == 'lxc':
@@ -429,7 +469,49 @@ def create_instance(module, proxmox, vmid, node, disk, storage, cpus, memory, sw
kwargs['cpus'] = cpus
kwargs['disk'] = disk
taskid = getattr(proxmox_node, VZ_TYPE).create(vmid=vmid, storage=storage, memory=memory, swap=swap, **kwargs)
if clone is not None:
if VZ_TYPE != 'lxc':
module.fail_json(changed=False, msg="Clone operator is only supported for LXC enabled proxmox clusters.")
clone_is_template = is_template_container(proxmox, node, clone)
# By default, create a full copy only when the cloned container is not a template.
create_full_copy = not clone_is_template
# Only accept parameters that are compatible with the clone endpoint.
valid_clone_parameters = ['hostname', 'pool', 'description']
if module.params['storage'] is not None and clone_is_template:
# Cloning a template, so create a full copy instead of a linked copy
create_full_copy = True
elif module.params['storage'] is None and not clone_is_template:
# Not cloning a template, but also no defined storage. This isn't possible.
module.fail_json(changed=False, msg="Cloned container is not a template, storage needs to be specified.")
if module.params['clone_type'] == 'linked':
if not clone_is_template:
module.fail_json(changed=False, msg="'linked' clone type is specified, but cloned container is not a template container.")
# Don't need to do more, by default create_full_copy is set to false already
elif module.params['clone_type'] == 'opportunistic':
if not clone_is_template:
# Cloned container is not a template, so we need our 'storage' parameter
valid_clone_parameters.append('storage')
elif module.params['clone_type'] == 'full':
create_full_copy = True
valid_clone_parameters.append('storage')
clone_parameters = {}
if create_full_copy:
clone_parameters['full'] = '1'
else:
clone_parameters['full'] = '0'
for param in valid_clone_parameters:
if module.params[param] is not None:
clone_parameters[param] = module.params[param]
taskid = getattr(proxmox_node, VZ_TYPE)(clone).clone.post(newid=vmid, **clone_parameters)
else:
taskid = getattr(proxmox_node, VZ_TYPE).create(vmid=vmid, storage=storage, memory=memory, swap=swap, **kwargs)
while timeout:
if (proxmox_node.tasks(taskid).status.get()['status'] == 'stopped' and
@@ -529,11 +611,20 @@ def main():
unprivileged=dict(type='bool', default=False),
description=dict(type='str'),
hookscript=dict(type='str'),
proxmox_default_behavior=dict(type='str', choices=['compatibility', 'no_defaults']),
proxmox_default_behavior=dict(type='str', default='no_defaults', choices=['compatibility', 'no_defaults']),
clone=dict(type='int'),
clone_type=dict(default='opportunistic', choices=['full', 'linked', 'opportunistic']),
),
required_if=[('state', 'present', ['node', 'hostname', 'ostemplate'])],
required_together=[('api_token_id', 'api_token_secret')],
required_if=[
('state', 'present', ['node', 'hostname']),
('state', 'present', ('clone', 'ostemplate'), True), # Require one of clone and ostemplate. Together with mutually_exclusive this ensures that we
# either clone a container or create a new one from a template file.
],
required_together=[
('api_token_id', 'api_token_secret')
],
required_one_of=[('api_password', 'api_token_id')],
mutually_exclusive=[('clone', 'ostemplate')], # Creating a new container is done either by cloning an existing one, or based on a template.
)
if not HAS_PROXMOXER:
@@ -557,14 +648,8 @@ def main():
if module.params['ostemplate'] is not None:
template_store = module.params['ostemplate'].split(":")[0]
timeout = module.params['timeout']
clone = module.params['clone']
if module.params['proxmox_default_behavior'] is None:
module.params['proxmox_default_behavior'] = 'compatibility'
module.deprecate(
'The proxmox_default_behavior option will change its default value from "compatibility" to '
'"no_defaults" in community.general 4.0.0. To remove this warning, please specify an explicit value for it now',
version='4.0.0', collection_name='community.general'
)
if module.params['proxmox_default_behavior'] == 'compatibility':
old_default_values = dict(
disk="3",
@@ -605,7 +690,8 @@ def main():
elif not vmid:
module.exit_json(changed=False, msg="Vmid could not be fetched for the following action: %s" % state)
if state == 'present':
# Create a new container
if state == 'present' and clone is None:
try:
if get_instance(proxmox, vmid) and not module.params['force']:
module.exit_json(changed=False, msg="VM with vmid = %s is already exists" % vmid)
@@ -617,8 +703,11 @@ def main():
elif not content_check(proxmox, node, module.params['ostemplate'], template_store):
module.fail_json(msg="ostemplate '%s' not exists on node %s and storage %s"
% (module.params['ostemplate'], node, template_store))
except Exception as e:
module.fail_json(msg="Pre-creation checks of {VZ_TYPE} VM {vmid} failed with exception: {e}".format(VZ_TYPE=VZ_TYPE, vmid=vmid, e=e))
create_instance(module, proxmox, vmid, node, disk, storage, cpus, memory, swap, timeout,
try:
create_instance(module, proxmox, vmid, node, disk, storage, cpus, memory, swap, timeout, clone,
cores=module.params['cores'],
pool=module.params['pool'],
password=module.params['password'],
@@ -627,20 +716,40 @@ def main():
netif=module.params['netif'],
mounts=module.params['mounts'],
ip_address=module.params['ip_address'],
onboot=int(module.params['onboot']),
onboot=ansible_to_proxmox_bool(module.params['onboot']),
cpuunits=module.params['cpuunits'],
nameserver=module.params['nameserver'],
searchdomain=module.params['searchdomain'],
force=int(module.params['force']),
force=ansible_to_proxmox_bool(module.params['force']),
pubkey=module.params['pubkey'],
features=",".join(module.params['features']) if module.params['features'] is not None else None,
unprivileged=int(module.params['unprivileged']),
unprivileged=ansible_to_proxmox_bool(module.params['unprivileged']),
description=module.params['description'],
hookscript=module.params['hookscript'])
module.exit_json(changed=True, msg="deployed VM %s from template %s" % (vmid, module.params['ostemplate']))
module.exit_json(changed=True, msg="Deployed VM %s from template %s" % (vmid, module.params['ostemplate']))
except Exception as e:
module.fail_json(msg="creation of %s VM %s failed with exception: %s" % (VZ_TYPE, vmid, e))
module.fail_json(msg="Creation of %s VM %s failed with exception: %s" % (VZ_TYPE, vmid, e))
# Clone a container
elif state == 'present' and clone is not None:
try:
if get_instance(proxmox, vmid) and not module.params['force']:
module.exit_json(changed=False, msg="VM with vmid = %s is already exists" % vmid)
# If no vmid was passed, there cannot be another VM named 'hostname'
if not module.params['vmid'] and get_vmid(proxmox, hostname) and not module.params['force']:
module.exit_json(changed=False, msg="VM with hostname %s already exists and has ID number %s" % (hostname, get_vmid(proxmox, hostname)[0]))
if not get_instance(proxmox, clone):
module.exit_json(changed=False, msg="Container to be cloned does not exist")
except Exception as e:
module.fail_json(msg="Pre-clone checks of {VZ_TYPE} VM {vmid} failed with exception: {e}".format(VZ_TYPE=VZ_TYPE, vmid=vmid, e=e))
try:
create_instance(module, proxmox, vmid, node, disk, storage, cpus, memory, swap, timeout, clone)
module.exit_json(changed=True, msg="Cloned VM %s from %s" % (vmid, clone))
except Exception as e:
module.fail_json(msg="Cloning %s VM %s failed with exception: %s" % (VZ_TYPE, vmid, e))
elif state == 'started':
try:

View File

@@ -131,7 +131,7 @@ def main():
group = module.params['group']
if group:
groups = [proxmox.get_group(group=group)]
groups = [proxmox.get_group(groupid=group)]
else:
groups = proxmox.get_groups()
result['proxmox_groups'] = [group.group for group in groups]

View File

@@ -13,15 +13,13 @@ module: proxmox_kvm
short_description: Management of Qemu(KVM) Virtual Machines in Proxmox VE cluster.
description:
- Allows you to create/delete/stop Qemu(KVM) Virtual Machines in Proxmox VE cluster.
- From community.general 4.0.0 on, there will be no default values, see I(proxmox_default_behavior).
- Since community.general 4.0.0 on, there are no more default values, see I(proxmox_default_behavior).
author: "Abdoul Bah (@helldorado) <bahabdoul at gmail.com>"
options:
acpi:
description:
- Specify if ACPI should be enabled/disabled.
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(yes). Note that the default value of I(proxmox_default_behavior)
changes in community.general 4.0.0.
- This option has no default unless I(proxmox_default_behavior) is set to C(compatiblity); then the default is C(yes).
type: bool
agent:
description:
@@ -31,24 +29,19 @@ options:
description:
- Pass arbitrary arguments to kvm.
- This option is for experts only!
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(-serial unix:/var/run/qemu-server/<vmid>.serial,server,nowait).
Note that the default value of I(proxmox_default_behavior) changes in community.general 4.0.0.
- If I(proxmox_default_behavior) is set to C(compatiblity), this option has a default of
C(-serial unix:/var/run/qemu-server/<vmid>.serial,server,nowait).
type: str
autostart:
description:
- Specify if the VM should be automatically restarted after crash (currently ignored in PVE API).
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(no). Note that the default value of I(proxmox_default_behavior)
changes in community.general 4.0.0.
- This option has no default unless I(proxmox_default_behavior) is set to C(compatiblity); then the default is C(no).
type: bool
balloon:
description:
- Specify the amount of RAM for the VM in MB.
- Using zero disables the balloon driver.
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(0). Note that the default value of I(proxmox_default_behavior)
changes in community.general 4.0.0.
- This option has no default unless I(proxmox_default_behavior) is set to C(compatiblity); then the default is C(0).
type: int
bios:
description:
@@ -59,9 +52,7 @@ options:
description:
- Specify the boot order -> boot on floppy C(a), hard disk C(c), CD-ROM C(d), or network C(n).
- You can combine to set order.
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(cnd). Note that the default value of I(proxmox_default_behavior)
changes in community.general 4.0.0.
- This option has no default unless I(proxmox_default_behavior) is set to C(compatiblity); then the default is C(cnd).
type: str
bootdisk:
description:
@@ -97,16 +88,12 @@ options:
cores:
description:
- Specify number of cores per socket.
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(1). Note that the default value of I(proxmox_default_behavior)
changes in community.general 4.0.0.
- This option has no default unless I(proxmox_default_behavior) is set to C(compatiblity); then the default is C(1).
type: int
cpu:
description:
- Specify emulated CPU type.
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(kvm64). Note that the default value of I(proxmox_default_behavior)
changes in community.general 4.0.0.
- This option has no default unless I(proxmox_default_behavior) is set to C(compatiblity); then the default is C(kvm64).
type: str
cpulimit:
description:
@@ -117,9 +104,7 @@ options:
description:
- Specify CPU weight for a VM.
- You can disable fair-scheduler configuration by setting this to 0
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(1000). Note that the default value of I(proxmox_default_behavior)
changes in community.general 4.0.0.
- This option has no default unless I(proxmox_default_behavior) is set to C(compatiblity); then the default is C(1000).
type: int
delete:
description:
@@ -139,19 +124,15 @@ options:
description:
- Allow to force stop VM.
- Can be used with states C(stopped), C(restarted) and C(absent).
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(no). Note that the default value of I(proxmox_default_behavior)
changes in community.general 4.0.0.
- This option has no default unless I(proxmox_default_behavior) is set to C(compatiblity); then the default is C(no).
type: bool
format:
description:
- Target drive's backing file's data format.
- Used only with clone
- Use I(format=unspecified) and I(full=false) for a linked clone.
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(qcow2). If I(proxmox_default_behavior) is set to C(no_defaults),
not specifying this option is equivalent to setting it to C(unspecified).
Note that the default value of I(proxmox_default_behavior) changes in community.general 4.0.0.
- This option has no default unless I(proxmox_default_behavior) is set to C(compatiblity); then the default is C(qcow2).
If I(proxmox_default_behavior) is set to C(no_defaults), not specifying this option is equivalent to setting it to C(unspecified).
type: str
choices: [ "cloop", "cow", "qcow", "qcow2", "qed", "raw", "vmdk", "unspecified" ]
freeze:
@@ -216,9 +197,7 @@ options:
kvm:
description:
- Enable/disable KVM hardware virtualization.
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(yes). Note that the default value of I(proxmox_default_behavior)
changes in community.general 4.0.0.
- This option has no default unless I(proxmox_default_behavior) is set to C(compatiblity); then the default is C(yes).
type: bool
localtime:
description:
@@ -238,9 +217,7 @@ options:
memory:
description:
- Memory size in MB for instance.
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(512). Note that the default value of I(proxmox_default_behavior)
changes in community.general 4.0.0.
- This option has no default unless I(proxmox_default_behavior) is set to C(compatiblity); then the default is C(512).
type: int
migrate_downtime:
description:
@@ -296,17 +273,13 @@ options:
onboot:
description:
- Specifies whether a VM will be started during system bootup.
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(yes). Note that the default value of I(proxmox_default_behavior)
changes in community.general 4.0.0.
- This option has no default unless I(proxmox_default_behavior) is set to C(compatiblity); then the default is C(yes).
type: bool
ostype:
description:
- Specifies guest operating system. This is used to enable special optimization/features for specific operating systems.
- The l26 is Linux 2.6/3.X Kernel.
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(l26). Note that the default value of I(proxmox_default_behavior)
changes in community.general 4.0.0.
- This option has no default unless I(proxmox_default_behavior) is set to C(compatiblity); then the default is C(l26).
type: str
choices: ['other', 'wxp', 'w2k', 'w2k3', 'w2k8', 'wvista', 'win7', 'win8', 'win10', 'l24', 'l26', 'solaris']
parallel:
@@ -387,9 +360,7 @@ options:
sockets:
description:
- Sets the number of CPU sockets. (1 - N).
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(1). Note that the default value of I(proxmox_default_behavior)
changes in community.general 4.0.0.
- This option has no default unless I(proxmox_default_behavior) is set to C(compatiblity); then the default is C(1).
type: int
sshkeys:
description:
@@ -421,9 +392,7 @@ options:
tablet:
description:
- Enables/disables the USB tablet device.
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(no). Note that the default value of I(proxmox_default_behavior)
changes in community.general 4.0.0.
- This option has no default unless I(proxmox_default_behavior) is set to C(compatiblity); then the default is C(no).
type: bool
tags:
description:
@@ -445,9 +414,7 @@ options:
template:
description:
- Enables/disables the template.
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(no). Note that the default value of I(proxmox_default_behavior)
changes in community.general 4.0.0.
- This option has no default unless I(proxmox_default_behavior) is set to C(compatiblity); then the default is C(no).
type: bool
timeout:
description:
@@ -469,9 +436,7 @@ options:
vga:
description:
- Select VGA type. If you want to use high resolution modes (>= 1280x1024x16) then you should use option 'std' or 'vmware'.
- If I(proxmox_default_behavior) is set to C(compatiblity) (the default value), this
option has a default of C(std). Note that the default value of I(proxmox_default_behavior)
changes in community.general 4.0.0.
- This option has no default unless I(proxmox_default_behavior) is set to C(compatiblity); then the default is C(std).
type: str
choices: ['std', 'cirrus', 'vmware', 'qxl', 'serial0', 'serial1', 'serial2', 'serial3', 'qxl2', 'qxl3', 'qxl4']
virtio:
@@ -489,18 +454,17 @@ options:
type: str
proxmox_default_behavior:
description:
- Various module options used to have default values. This cause problems when
user expects different behavior from proxmox by default or fill options which cause
problems when they have been set.
- The default value is C(compatibility), which will ensure that the default values
are used when the values are not explicitly specified by the user.
- From community.general 4.0.0 on, the default value will switch to C(no_defaults). To avoid
deprecation warnings, please set I(proxmox_default_behavior) to an explicit
value.
- As of community.general 4.0.0, various options no longer have default values.
These default values caused problems when users expected different behavior from Proxmox
by default or filled options which caused problems when set.
- The value C(compatibility) (default before community.general 4.0.0) will ensure that the default values
are used when the values are not explicitly specified by the user. The new default is C(no_defaults),
which makes sure these options have no defaults.
- This affects the I(acpi), I(autostart), I(balloon), I(boot), I(cores), I(cpu),
I(cpuunits), I(force), I(format), I(kvm), I(memory), I(onboot), I(ostype), I(sockets),
I(tablet), I(template), I(vga), options.
type: str
default: no_defaults
choices:
- compatibility
- no_defaults
@@ -761,9 +725,10 @@ msg:
import re
import time
import traceback
from distutils.version import LooseVersion
from ansible.module_utils.six.moves.urllib.parse import quote
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
try:
from proxmoxer import ProxmoxAPI
HAS_PROXMOXER = True
@@ -1091,7 +1056,7 @@ def main():
virtio=dict(type='dict'),
vmid=dict(type='int'),
watchdog=dict(),
proxmox_default_behavior=dict(type='str', choices=['compatibility', 'no_defaults']),
proxmox_default_behavior=dict(type='str', default='no_defaults', choices=['compatibility', 'no_defaults']),
),
mutually_exclusive=[('delete', 'revert'), ('delete', 'update'), ('revert', 'update'), ('clone', 'update'), ('clone', 'delete'), ('clone', 'revert')],
required_together=[('api_token_id', 'api_token_secret')],
@@ -1122,13 +1087,6 @@ def main():
vmid = module.params['vmid']
validate_certs = module.params['validate_certs']
if module.params['proxmox_default_behavior'] is None:
module.params['proxmox_default_behavior'] = 'compatibility'
module.deprecate(
'The proxmox_default_behavior option will change its default value from "compatibility" to '
'"no_defaults" in community.general 4.0.0. To remove this warning, please specify an explicit value for it now',
version='4.0.0', collection_name='community.general'
)
if module.params['proxmox_default_behavior'] == 'compatibility':
old_default_values = dict(
acpi=True,

View File

@@ -0,0 +1,186 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2021, Andreas Botzner (@paginabianca) <andreas at botzner dot 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 = r'''
---
module: proxmox_tasks_info
short_description: Retrieve information about one or more Proxmox VE tasks
version_added: 3.8.0
description:
- Retrieve information about one or more Proxmox VE tasks.
author: 'Andreas Botzner (@paginabianca) <andreas at botzner dot com>'
options:
node:
description:
- Node where to get tasks.
required: true
type: str
task:
description:
- Return specific task.
aliases: ['upid', 'name']
type: str
extends_documentation_fragment:
- community.general.proxmox.documentation
'''
EXAMPLES = '''
- name: List tasks on node01
community.general.proxmox_task_info:
api_host: proxmoxhost
api_user: root@pam
api_password: '{{ password | default(omit) }}'
api_token_id: '{{ token_id | default(omit) }}'
api_token_secret: '{{ token_secret | default(omit) }}'
node: node01
register: result
- name: Retrieve information about specific tasks on node01
community.general.proxmox_task_info:
api_host: proxmoxhost
api_user: root@pam
api_password: '{{ password | default(omit) }}'
api_token_id: '{{ token_id | default(omit) }}'
api_token_secret: '{{ token_secret | default(omit) }}'
task: 'UPID:node01:00003263:16167ACE:621EE230:srvreload:networking:root@pam:'
node: node01
register: proxmox_tasks
'''
RETURN = '''
proxmox_tasks:
description: List of tasks.
returned: on success
type: list
elements: dict
contains:
id:
description: ID of the task.
returned: on success
type: str
node:
description: Node name.
returned: on success
type: str
pid:
description: PID of the task.
returned: on success
type: int
pstart:
description: pastart of the task.
returned: on success
type: int
starttime:
description: Starting time of the task.
returned: on success
type: int
type:
description: Type of the task.
returned: on success
type: str
upid:
description: UPID of the task.
returned: on success
type: str
user:
description: User that owns the task.
returned: on success
type: str
endtime:
description: Endtime of the task.
returned: on success, can be absent
type: int
status:
description: Status of the task.
returned: on success, can be absent
type: str
failed:
description: If the task failed.
returned: when status is defined
type: bool
msg:
description: Short message.
returned: on failure
type: str
sample: 'Task: UPID:xyz:xyz does not exist on node: proxmoxnode'
'''
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
from ansible_collections.community.general.plugins.module_utils.proxmox import (
proxmox_auth_argument_spec, ProxmoxAnsible, HAS_PROXMOXER, PROXMOXER_IMP_ERR)
class ProxmoxTaskInfoAnsible(ProxmoxAnsible):
def get_task(self, upid, node):
tasks = self.get_tasks(node)
for task in tasks:
if task.info['upid'] == upid:
return [task]
def get_tasks(self, node):
tasks = self.proxmox_api.nodes(node).tasks.get()
return [ProxmoxTask(task) for task in tasks]
class ProxmoxTask:
def __init__(self, task):
self.info = dict()
for k, v in task.items():
if k == 'status' and isinstance(v, str):
self.info[k] = v
if v != 'OK':
self.info['failed'] = True
else:
self.info[k] = v
def proxmox_task_info_argument_spec():
return dict(
task=dict(type='str', aliases=['upid', 'name'], required=False),
node=dict(type='str', required=True),
)
def main():
module_args = proxmox_auth_argument_spec()
task_info_args = proxmox_task_info_argument_spec()
module_args.update(task_info_args)
module = AnsibleModule(
argument_spec=module_args,
required_together=[('api_token_id', 'api_token_secret'),
('api_user', 'api_password')],
required_one_of=[('api_password', 'api_token_id')],
supports_check_mode=True)
result = dict(changed=False)
if not HAS_PROXMOXER:
module.fail_json(msg=missing_required_lib(
'proxmoxer'), exception=PROXMOXER_IMP_ERR)
proxmox = ProxmoxTaskInfoAnsible(module)
upid = module.params['task']
node = module.params['node']
if upid:
tasks = proxmox.get_task(upid=upid, node=node)
else:
tasks = proxmox.get_tasks(node=node)
if tasks is not None:
result['proxmox_tasks'] = [task.info for task in tasks]
module.exit_json(**result)
else:
result['msg'] = 'Task: {0} does not exist on node: {1}.'.format(
upid, node)
module.fail_json(**result)
if __name__ == '__main__':
main()

View File

@@ -137,6 +137,11 @@ options:
type: bool
default: false
version_added: '3.3.0'
parallelism:
description:
- Restrict concurrent operations when Terraform applies the plan.
type: int
version_added: '3.8.0'
notes:
- To just run a `terraform plan`, use check mode.
requirements: [ "terraform" ]
@@ -225,11 +230,12 @@ command:
import os
import json
import tempfile
from distutils.version import LooseVersion
from ansible.module_utils.six.moves import shlex_quote
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
module = None
@@ -314,11 +320,25 @@ def remove_workspace(bin_path, project_path, workspace):
_workspace_cmd(bin_path, project_path, 'delete', workspace)
def build_plan(command, project_path, variables_args, state_file, targets, state, plan_path=None):
def build_plan(command, project_path, variables_args, state_file, targets, state, apply_args, plan_path=None):
if plan_path is None:
f, plan_path = tempfile.mkstemp(suffix='.tfplan')
plan_command = [command[0], 'plan', '-input=false', '-no-color', '-detailed-exitcode', '-out', plan_path]
local_command = command.copy()
plan_command = [command[0], 'plan']
if state == "planned":
for c in local_command[1:]:
plan_command.append(c)
if state == "present":
for a in apply_args:
local_command.remove(a)
for c in local_command[1:]:
plan_command.append(c)
plan_command.extend(['-input=false', '-no-color', '-detailed-exitcode', '-out', plan_path])
for t in targets:
plan_command.extend(['-target', t])
@@ -363,6 +383,7 @@ def main():
init_reconfigure=dict(type='bool', default=False),
overwrite_init=dict(type='bool', default=True),
check_destroy=dict(type='bool', default=False),
parallelism=dict(type='int'),
),
required_if=[('state', 'planned', ['plan_file'])],
supports_check_mode=True,
@@ -415,6 +436,9 @@ def main():
elif state == 'absent':
command.extend(DESTROY_ARGS)
if state == 'present' and module.params.get('parallelism') is not None:
command.append('-parallelism=%d' % module.params.get('parallelism'))
variables_args = []
for k, v in variables.items():
variables_args.extend([
@@ -452,7 +476,7 @@ def main():
module.fail_json(msg='Could not find plan_file "{0}", check the path and try again.'.format(plan_file))
else:
plan_file, needs_application, out, err, command = build_plan(command, project_path, variables_args, state_file,
module.params.get('targets'), state, plan_file)
module.params.get('targets'), state, APPLY_ARGS, plan_file)
if state == 'present' and check_destroy and '- destroy' in out:
module.fail_json(msg="Aborting command because it would destroy some resources. "
"Consider switching the 'check_destroy' to false to suppress this error")

View File

@@ -15,7 +15,7 @@ description:
- Gather information about the servers.
- U(https://www.online.net/en/dedicated-server)
author:
- "Remy Leone (@sieben)"
- "Remy Leone (@remyleone)"
extends_documentation_fragment:
- community.general.online

View File

@@ -12,7 +12,7 @@ short_description: Gather information about Online user.
description:
- Gather information about the user.
author:
- "Remy Leone (@sieben)"
- "Remy Leone (@remyleone)"
extends_documentation_fragment:
- community.general.online
'''

View File

@@ -306,7 +306,7 @@ def rename_image(module, client, image, new_name):
tmp_image = get_image_by_name(module, client, new_name)
if tmp_image:
module.fail_json(msg="Name '" + new_name + "' is already taken by IMAGE with id=" + str(tmp_image.id))
module.fail_json(msg="Name '" + new_name + "' is already taken by IMAGE with id=" + str(tmp_image.ID))
if not module.check_mode:
client.image.rename(image.ID, new_name)

View File

@@ -97,7 +97,7 @@ EXAMPLES = '''
register: my_volume
'''
from distutils.version import LooseVersion
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
try:
import pyrax

View File

@@ -16,7 +16,7 @@ DOCUMENTATION = '''
---
module: scaleway_compute
short_description: Scaleway compute management module
author: Remy Leone (@sieben)
author: Remy Leone (@remyleone)
description:
- "This module manages compute instances on Scaleway."
extends_documentation_fragment:
@@ -54,8 +54,15 @@ options:
organization:
type: str
description:
- Organization identifier
required: true
- Organization identifier.
- Exactly one of I(project) and I(organization) must be specified.
project:
type: str
description:
- Project identifier.
- Exactly one of I(project) and I(organization) must be specified.
version_added: 4.3.0
state:
type: str
@@ -132,7 +139,7 @@ EXAMPLES = '''
name: foobar
state: present
image: 89ee4018-f8c3-4dc4-a6b5-bca14f985ebe
organization: 951df375-e094-4d26-97c1-ba548eeb9c42
project: 951df375-e094-4d26-97c1-ba548eeb9c42
region: ams1
commercial_type: VC1S
tags:
@@ -144,7 +151,7 @@ EXAMPLES = '''
name: foobar
state: present
image: 89ee4018-f8c3-4dc4-a6b5-bca14f985ebe
organization: 951df375-e094-4d26-97c1-ba548eeb9c42
project: 951df375-e094-4d26-97c1-ba548eeb9c42
region: ams1
commercial_type: VC1S
security_group: 4a31b633-118e-4900-bd52-facf1085fc8d
@@ -157,7 +164,7 @@ EXAMPLES = '''
name: foobar
state: absent
image: 89ee4018-f8c3-4dc4-a6b5-bca14f985ebe
organization: 951df375-e094-4d26-97c1-ba548eeb9c42
project: 951df375-e094-4d26-97c1-ba548eeb9c42
region: ams1
commercial_type: VC1S
'''
@@ -269,10 +276,15 @@ def create_server(compute_api, server):
"commercial_type": server["commercial_type"],
"image": server["image"],
"dynamic_ip_required": server["dynamic_ip_required"],
"name": server["name"],
"organization": server["organization"]
"name": server["name"]
}
if server["project"]:
data["project"] = server["project"]
if server["organization"]:
data["organization"] = server["organization"]
if server["security_group"]:
data["security_group"] = server["security_group"]
@@ -628,6 +640,7 @@ def core(module):
"enable_ipv6": module.params["enable_ipv6"],
"tags": module.params["tags"],
"organization": module.params["organization"],
"project": module.params["project"],
"security_group": module.params["security_group"]
}
module.params['api_url'] = SCALEWAY_LOCATION[region]["api_endpoint"]
@@ -655,7 +668,8 @@ def main():
public_ip=dict(default="absent"),
state=dict(choices=list(state_strategy.keys()), default='present'),
tags=dict(type="list", elements="str", default=[]),
organization=dict(required=True),
organization=dict(),
project=dict(),
wait=dict(type="bool", default=False),
wait_timeout=dict(type="int", default=300),
wait_sleep_time=dict(type="int", default=3),
@@ -664,6 +678,12 @@ def main():
module = AnsibleModule(
argument_spec=argument_spec,
supports_check_mode=True,
mutually_exclusive=[
('organization', 'project'),
],
required_one_of=[
('organization', 'project'),
],
)
core(module)

View File

@@ -15,7 +15,7 @@ description:
- Gather information about the Scaleway images available.
author:
- "Yanis Guenane (@Spredzy)"
- "Remy Leone (@sieben)"
- "Remy Leone (@remyleone)"
extends_documentation_fragment:
- community.general.scaleway

View File

@@ -13,7 +13,7 @@ DOCUMENTATION = '''
---
module: scaleway_ip
short_description: Scaleway IP management module
author: Remy Leone (@sieben)
author: Remy Leone (@remyleone)
description:
- This module manages IP on Scaleway account
U(https://developer.scaleway.com)

View File

@@ -15,7 +15,7 @@ description:
- Gather information about the Scaleway ips available.
author:
- "Yanis Guenane (@Spredzy)"
- "Remy Leone (@sieben)"
- "Remy Leone (@remyleone)"
extends_documentation_fragment:
- community.general.scaleway

View File

@@ -16,7 +16,7 @@ DOCUMENTATION = '''
---
module: scaleway_lb
short_description: Scaleway load-balancer management module
author: Remy Leone (@sieben)
author: Remy Leone (@remyleone)
description:
- "This module manages load-balancers on Scaleway."
extends_documentation_fragment:

View File

@@ -15,7 +15,7 @@ description:
- Gather information about the Scaleway organizations available.
author:
- "Yanis Guenane (@Spredzy)"
- "Remy Leone (@sieben)"
- "Remy Leone (@remyleone)"
options:
api_url:
description:

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