mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-04-04 17:50:32 -07:00
Merge branch 'ansible-collections:main' into main
This commit is contained in:
commit
abe8eb0e90
221 changed files with 7682 additions and 3331 deletions
15
.github/BOTMETA.yml
vendored
15
.github/BOTMETA.yml
vendored
|
@ -111,6 +111,9 @@ files:
|
|||
$connections/lxd.py:
|
||||
labels: lxd
|
||||
maintainers: mattclay
|
||||
$connections/proxmox_pct_remote.py:
|
||||
labels: proxmox
|
||||
maintainers: mietzen
|
||||
$connections/qubes.py:
|
||||
maintainers: kushaldas
|
||||
$connections/saltstack.py:
|
||||
|
@ -161,6 +164,14 @@ files:
|
|||
maintainers: Ajpantuso
|
||||
$filters/jc.py:
|
||||
maintainers: kellyjonbrazil
|
||||
$filters/json_diff.yml:
|
||||
maintainers: numo68
|
||||
$filters/json_patch.py:
|
||||
maintainers: numo68
|
||||
$filters/json_patch.yml:
|
||||
maintainers: numo68
|
||||
$filters/json_patch_recipe.yml:
|
||||
maintainers: numo68
|
||||
$filters/json_query.py: {}
|
||||
$filters/keep_keys.py:
|
||||
maintainers: vbotka
|
||||
|
@ -296,6 +307,8 @@ files:
|
|||
$lookups/onepassword_raw.py:
|
||||
ignore: scottsb
|
||||
maintainers: azenk
|
||||
$lookups/onepassword_ssh_key.py:
|
||||
maintainers: mohammedbabelly20
|
||||
$lookups/passwordstore.py: {}
|
||||
$lookups/random_pet.py:
|
||||
maintainers: Akasurde
|
||||
|
@ -1135,6 +1148,8 @@ files:
|
|||
maintainers: helldorado krauthosting
|
||||
$modules/proxmox_backup.py:
|
||||
maintainers: IamLunchbox
|
||||
$modules/proxmox_backup_info.py:
|
||||
maintainers: raoufnezhad mmayabi
|
||||
$modules/proxmox_nic.py:
|
||||
maintainers: Kogelvis krauthosting
|
||||
$modules/proxmox_node_info.py:
|
||||
|
|
11
changelogs/fragments/9225-proxmox-module-refactoring.yml
Normal file
11
changelogs/fragments/9225-proxmox-module-refactoring.yml
Normal file
|
@ -0,0 +1,11 @@
|
|||
minor_changes:
|
||||
- proxmox - refactors the proxmox module (https://github.com/ansible-collections/community.general/pull/9225).
|
||||
|
||||
bugfixes:
|
||||
- proxmox - fixes idempotency of template conversions (https://github.com/ansible-collections/community.general/pull/9225, https://github.com/ansible-collections/community.general/issues/8811).
|
||||
- proxmox - fixes issues with disk_volume variable (https://github.com/ansible-collections/community.general/pull/9225, https://github.com/ansible-collections/community.general/issues/9065).
|
||||
- proxmox - fixes incorrect parsing for bind-only mounts (https://github.com/ansible-collections/community.general/pull/9225, https://github.com/ansible-collections/community.general/issues/8982).
|
||||
- proxmox module utils - fixes ignoring of ``choose_first_if_multiple`` argument in ``get_vmid`` (https://github.com/ansible-collections/community.general/pull/9225).
|
||||
|
||||
deprecated_features:
|
||||
- proxmox - removes default value ``false`` of ``update`` parameter. This will be changed to a default of ``true`` in community.general 11.0.0 (https://github.com/ansible-collections/community.general/pull/9225).
|
|
@ -0,0 +1,2 @@
|
|||
minor_changes:
|
||||
- keycloak_* modules - ``refresh_token`` parameter added. When multiple authentication parameters are provided (``token``, ``refresh_token``, and ``auth_username``/``auth_password``), modules will now automatically retry requests upon authentication errors (401), using in order the token, refresh token, and username/password (https://github.com/ansible-collections/community.general/pull/9494).
|
2
changelogs/fragments/9547-one_template-filter.yml
Normal file
2
changelogs/fragments/9547-one_template-filter.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
minor_changes:
|
||||
- one_template - adds ``filter`` option for retrieving templates which are not owned by the user (https://github.com/ansible-collections/community.general/pull/9547, https://github.com/ansible-collections/community.general/issues/9278).
|
|
@ -0,0 +1,3 @@
|
|||
minor_changes:
|
||||
- cpanm - enable usage of option ``--with-recommends`` (https://github.com/ansible-collections/community.general/issues/9554, https://github.com/ansible-collections/community.general/pull/9555).
|
||||
- cpanm - enable usage of option ``--with-suggests`` (https://github.com/ansible-collections/community.general/pull/9555).
|
|
@ -0,0 +1,2 @@
|
|||
minor_changes:
|
||||
- nmcli - add a option ``fail_over_mac`` (https://github.com/ansible-collections/community.general/issues/9570, https://github.com/ansible-collections/community.general/pull/9571).
|
2
changelogs/fragments/9573-iocage-inventory-sudo.yml
Normal file
2
changelogs/fragments/9573-iocage-inventory-sudo.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
minor_changes:
|
||||
- iocage inventory plugin - the new parameter ``sudo`` of the plugin lets the command ``iocage list -l`` to run as root on the iocage host. This is needed to get the IPv4 of a running DHCP jail (https://github.com/ansible-collections/community.general/issues/9572, https://github.com/ansible-collections/community.general/pull/9573).
|
6
changelogs/fragments/9577-mh-delegate-debug.yml
Normal file
6
changelogs/fragments/9577-mh-delegate-debug.yml
Normal file
|
@ -0,0 +1,6 @@
|
|||
minor_changes:
|
||||
- MH module utils - delegate ``debug`` to the underlying ``AnsibleModule`` instance or issues a warning if an attribute already exists with that name (https://github.com/ansible-collections/community.general/pull/9577).
|
||||
deprecated_features:
|
||||
- >
|
||||
MH module utils - attribute ``debug`` definition in subclasses of MH is now deprecated, as that name will become a delegation to ``AnsibleModule`` in
|
||||
community.general 12.0.0, and any such attribute will be overridden by that delegation in that version (https://github.com/ansible-collections/community.general/pull/9577).
|
|
@ -0,0 +1,7 @@
|
|||
bugfixes:
|
||||
- |
|
||||
redhat_subscription - do not try to unsubscribe (i.e. remove subscriptions)
|
||||
when unregistering a system: newer versions of subscription-manager, as
|
||||
available in EL 10 and Fedora 41+, do not support entitlements anymore, and
|
||||
thus unsubscribing will fail
|
||||
(https://github.com/ansible-collections/community.general/pull/9578).
|
11
changelogs/fragments/9579-with-open.yml
Normal file
11
changelogs/fragments/9579-with-open.yml
Normal file
|
@ -0,0 +1,11 @@
|
|||
minor_changes:
|
||||
- known_hosts - open file using ``open()`` as a context manager (https://github.com/ansible-collections/community.general/pull/9579).
|
||||
- cloud_init_data_facts - open file using ``open()`` as a context manager (https://github.com/ansible-collections/community.general/pull/9579).
|
||||
- cronvar - open file using ``open()`` as a context manager (https://github.com/ansible-collections/community.general/pull/9579).
|
||||
- crypttab - open file using ``open()`` as a context manager (https://github.com/ansible-collections/community.general/pull/9579).
|
||||
- parted - open file using ``open()`` as a context manager (https://github.com/ansible-collections/community.general/pull/9579).
|
||||
- pulp_repo - open file using ``open()`` as a context manager (https://github.com/ansible-collections/community.general/pull/9579).
|
||||
- redhat_subscription - open file using ``open()`` as a context manager (https://github.com/ansible-collections/community.general/pull/9579).
|
||||
- solaris_zone - open file using ``open()`` as a context manager (https://github.com/ansible-collections/community.general/pull/9579).
|
||||
- sorcery - open file using ``open()`` as a context manager (https://github.com/ansible-collections/community.general/pull/9579).
|
||||
- timezone - open file using ``open()`` as a context manager (https://github.com/ansible-collections/community.general/pull/9579).
|
2
changelogs/fragments/9582-add-support-for-vrrp.yml
Normal file
2
changelogs/fragments/9582-add-support-for-vrrp.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
minor_changes:
|
||||
- ufw - add support for ``vrrp`` protocol (https://github.com/ansible-collections/community.general/issues/9562, https://github.com/ansible-collections/community.general/pull/9582).
|
|
@ -0,0 +1,43 @@
|
|||
minor_changes:
|
||||
- iptables_state action plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- shutdown action plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- doas become plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- dzdo become plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- ksu become plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- machinectl become plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- pbrun become plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- pfexec become plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- pmrun become plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- run0 become plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- sesu become plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- sudosu become plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- memcached cache plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- pickle cache plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- redis cache plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- yaml cache plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- cgroup_memory_recap callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- context_demo callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- counter_enabled callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- default_without_diff callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- dense callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- diy callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- elastic callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- jabber callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- log_plays callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- loganalytics callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- logdna callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- logentries callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- logstash callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- mail callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- nrdp callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- null callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- opentelemetry callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- say callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- selective callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- slack callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- splunk callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- sumologic callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- syslog_json callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- timestamp callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- unixy callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
||||
- yaml callback plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9583).
|
|
@ -0,0 +1,26 @@
|
|||
minor_changes:
|
||||
- chroot connection plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
||||
- funcd connection plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
||||
- incus connection plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
||||
- iocage connection plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
||||
- jail connection plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
||||
- lxc connection plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
||||
- lxd connection plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
||||
- proxmox_pct_remote connection plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
||||
- qubes connection plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
||||
- saltstack connection plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
||||
- zone connection plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
||||
- cobbler inventory plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
||||
- gitlab_runners inventory plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
||||
- icinga2 inventory plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
||||
- iocage inventory plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
||||
- linode inventory plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
||||
- lxd inventory plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
||||
- nmap inventory plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
||||
- online inventory plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
||||
- opennebula inventory plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
||||
- proxmox inventory plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
||||
- scaleway inventory plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
||||
- stackpath_compute inventory plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
||||
- virtualbox inventory plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
||||
- xen_orchestra inventory plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9584).
|
22
changelogs/fragments/9585-py3-imports-filter.yml
Normal file
22
changelogs/fragments/9585-py3-imports-filter.yml
Normal file
|
@ -0,0 +1,22 @@
|
|||
minor_changes:
|
||||
- counter filter plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9585).
|
||||
- crc32 filter plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9585).
|
||||
- dict filter plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9585).
|
||||
- dict_kv filter plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9585).
|
||||
- from_csv filter plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9585).
|
||||
- from_ini filter plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9585).
|
||||
- groupby_as_dict filter plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9585).
|
||||
- hashids filter plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9585).
|
||||
- jc filter plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9585).
|
||||
- json_query filter plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9585).
|
||||
- keep_keys filter plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9585).
|
||||
- lists filter plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9585).
|
||||
- lists_mergeby filter plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9585).
|
||||
- random_mac filter plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9585).
|
||||
- remove_keys filter plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9585).
|
||||
- replace_keys filter plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9585).
|
||||
- reveal_ansible_type filter plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9585).
|
||||
- time filter plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9585).
|
||||
- to_ini filter plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9585).
|
||||
- unicode_normalize filter plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9585).
|
||||
- version_sort filter plugin - adjust standard preamble for Python 3 (https://github.com/ansible-collections/community.general/pull/9585).
|
2
changelogs/fragments/9586-allow-transition-id-jira.yml
Normal file
2
changelogs/fragments/9586-allow-transition-id-jira.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
minor_changes:
|
||||
- jira - transition operation now has ``status_id`` to directly reference wanted transition (https://github.com/ansible-collections/community.general/pull/9602).
|
3
changelogs/fragments/9598-snap-version.yml
Normal file
3
changelogs/fragments/9598-snap-version.yml
Normal file
|
@ -0,0 +1,3 @@
|
|||
minor_changes:
|
||||
- snap - add return value ``version`` (https://github.com/ansible-collections/community.general/pull/9598).
|
||||
- snap_alias - add return value ``version`` (https://github.com/ansible-collections/community.general/pull/9598).
|
2
changelogs/fragments/9599-apache2-mod-proxy-revamp1.yml
Normal file
2
changelogs/fragments/9599-apache2-mod-proxy-revamp1.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
minor_changes:
|
||||
- apache2_mod_proxy - refactor repeated code into method (https://github.com/ansible-collections/community.general/pull/9599).
|
2
changelogs/fragments/9600-apache2-mod-proxy-revamp2.yml
Normal file
2
changelogs/fragments/9600-apache2-mod-proxy-revamp2.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
minor_changes:
|
||||
- apache2_mod_proxy - change type of ``state`` to a list of strings. No change for the users (https://github.com/ansible-collections/community.general/pull/9600).
|
|
@ -0,0 +1,2 @@
|
|||
minor_changes:
|
||||
- proxmox_template - add support for checksum validation with new options ``checksum_algorithm`` and ``checksum`` (https://github.com/ansible-collections/community.general/issues/9553, https://github.com/ansible-collections/community.general/pull/9601).
|
2
changelogs/fragments/9608-apache2-mod-proxy-revamp3.yml
Normal file
2
changelogs/fragments/9608-apache2-mod-proxy-revamp3.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
minor_changes:
|
||||
- apache2_mod_proxy - improve readability when using results from ``fecth_url()`` (https://github.com/ansible-collections/community.general/pull/9608).
|
2
changelogs/fragments/9609-apache2-mod-proxy-revamp4.yml
Normal file
2
changelogs/fragments/9609-apache2-mod-proxy-revamp4.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
minor_changes:
|
||||
- apache2_mod_proxy - better handling regexp extraction (https://github.com/ansible-collections/community.general/pull/9609).
|
2
changelogs/fragments/9612-apache2-mod-proxy-revamp5.yml
Normal file
2
changelogs/fragments/9612-apache2-mod-proxy-revamp5.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
minor_changes:
|
||||
- apache2_mod_proxy - use ``deps`` to handle dependencies (https://github.com/ansible-collections/community.general/pull/9612).
|
3
changelogs/fragments/9614-apache2-mod-proxy-revamp7.yml
Normal file
3
changelogs/fragments/9614-apache2-mod-proxy-revamp7.yml
Normal file
|
@ -0,0 +1,3 @@
|
|||
minor_changes:
|
||||
- apache2_mod_proxy - simplified and improved string manipulation (https://github.com/ansible-collections/community.general/pull/9614).
|
||||
- apache2_mod_proxy - remove unused parameter and code from ``Balancer`` constructor (https://github.com/ansible-collections/community.general/pull/9614).
|
|
@ -0,0 +1,2 @@
|
|||
security_fixes:
|
||||
- keycloak_client - Sanitize ``saml.encryption.private.key`` so it does not show in the logs (https://github.com/ansible-collections/community.general/pull/9621).
|
2
changelogs/fragments/9623-pipx-global-latest.yml
Normal file
2
changelogs/fragments/9623-pipx-global-latest.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
bugfixes:
|
||||
- pipx - honor option ``global`` when ``state=latest`` (https://github.com/ansible-collections/community.general/pull/9623).
|
2
changelogs/fragments/9633-onepassword_ssh_key.yml
Normal file
2
changelogs/fragments/9633-onepassword_ssh_key.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
minor_changes:
|
||||
- "onepassword_ssh_key - refactor to move code to lookup class (https://github.com/ansible-collections/community.general/pull/9633)."
|
3
changelogs/fragments/9645-proxmox-fix-pubkey.yml
Normal file
3
changelogs/fragments/9645-proxmox-fix-pubkey.yml
Normal file
|
@ -0,0 +1,3 @@
|
|||
bugfixes:
|
||||
- proxmox - fixes a typo in the translation of the ``pubkey`` parameter to proxmox' ``ssh-public-keys`` (https://github.com/ansible-collections/community.general/issues/9642, https://github.com/ansible-collections/community.general/pull/9645).
|
||||
- proxmox - adds the ``pubkey`` parameter (back to) the ``update`` state (https://github.com/ansible-collections/community.general/issues/9642, https://github.com/ansible-collections/community.general/pull/9645).
|
|
@ -0,0 +1,2 @@
|
|||
bugfixes:
|
||||
- cloudflare_dns - fix crash when deleting a DNS record or when updating a record with ``solo=true`` (https://github.com/ansible-collections/community.general/issues/9652, https://github.com/ansible-collections/community.general/pull/9649).
|
|
@ -468,6 +468,11 @@ Additionally, MH will also delegate:
|
|||
- ``diff_mode`` to ``self.module._diff``
|
||||
- ``verbosity`` to ``self.module._verbosity``
|
||||
|
||||
Starting in community.general 10.3.0, MH will also delegate the method ``debug`` to ``self.module``.
|
||||
If any existing module already has a ``debug`` attribute defined, a warning message will be generated,
|
||||
requesting it to be renamed. Upon the release of community.general 12.0.0, the delegation will be
|
||||
preemptive and will override any existing method or property in the subclasses.
|
||||
|
||||
Decorators
|
||||
""""""""""
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
namespace: community
|
||||
name: general
|
||||
version: 10.3.0
|
||||
version: 10.4.0
|
||||
readme: README.md
|
||||
authors:
|
||||
- Ansible (https://github.com/ansible)
|
||||
|
|
|
@ -17,6 +17,7 @@ action_groups:
|
|||
proxmox:
|
||||
- proxmox
|
||||
- proxmox_backup
|
||||
- proxmox_backup_info
|
||||
- proxmox_disk
|
||||
- proxmox_domain_info
|
||||
- proxmox_group_info
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
|
||||
|
|
|
@ -5,9 +5,8 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
from __future__ import annotations
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
from ansible.errors import AnsibleError, AnsibleConnectionFailure
|
||||
from ansible.module_utils.common.text.converters import to_native, to_text
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
# Copyright (c) 2018, Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: doas
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
# Copyright (c) 2018, Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: dzdo
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
# Copyright (c) 2018, Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: ksu
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
# Copyright (c) 2018, Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: machinectl
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
# Copyright (c) 2018, Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: pbrun
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
# Copyright (c) 2018, Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: pfexec
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
# Copyright (c) 2018, Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: pmrun
|
||||
|
|
|
@ -3,9 +3,8 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
from __future__ import annotations
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: run0
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
# Copyright (c) 2018, Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: sesu
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
# Copyright (c) 2021, Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: sudosu
|
||||
|
|
3
plugins/cache/memcached.py
vendored
3
plugins/cache/memcached.py
vendored
|
@ -4,8 +4,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Unknown (!UNKNOWN)
|
||||
|
|
3
plugins/cache/pickle.py
vendored
3
plugins/cache/pickle.py
vendored
|
@ -5,8 +5,7 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Make coding more python3-ish
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: pickle
|
||||
|
|
3
plugins/cache/redis.py
vendored
3
plugins/cache/redis.py
vendored
|
@ -3,8 +3,7 @@
|
|||
# Copyright (c) 2017 Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Unknown (!UNKNOWN)
|
||||
|
|
3
plugins/cache/yaml.py
vendored
3
plugins/cache/yaml.py
vendored
|
@ -5,8 +5,7 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Make coding more python3-ish
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: yaml
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Make coding more python3-ish
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Unknown (!UNKNOWN)
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Unknown (!UNKNOWN)
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
Counter enabled Ansible callback plugin (See DOCUMENTATION for more information)
|
||||
'''
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Unknown (!UNKNOWN)
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: default_without_diff
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: dense
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: diy
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Victor Martinez (@v1v) <VictorMartinezRubio@gmail.com>
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Unknown (!UNKNOWN)
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Unknown (!UNKNOWN)
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: loganalytics
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Unknown (!UNKNOWN)
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
# Copyright (c) 2017 Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Unknown (!UNKNOWN)
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Yevhen Khmelenko (@ujenmr)
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: mail
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Make coding more python3-ish
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: nrdp
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Make coding more python3-ish
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Unknown (!UNKNOWN)
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Victor Martinez (@v1v) <VictorMartinezRubio@gmail.com>
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Make coding more python3-ish
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Unknown (!UNKNOWN)
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Unknown (!UNKNOWN)
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Make coding more python3-ish
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Unknown (!UNKNOWN)
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: splunk
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: sumologic
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Make coding more python3-ish
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Unknown (!UNKNOWN)
|
||||
|
|
|
@ -5,9 +5,8 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
from __future__ import annotations
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: timestamp
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Make coding more python3-ish
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: unixy
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Make coding more python3-ish
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Unknown (!UNKNOWN)
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Maykel Moya (!UNKNOWN) <mmoya@speedyrails.com>
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Michael Scherer (@mscherer) <misc@zarb.org>
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Stéphane Graber (@stgraber)
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Stephan Lohse (!UNKNOWN) <dev-github@ploek.org>
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Ansible Core Team
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Joerg Thalheim (!UNKNOWN) <joerg@higgsboson.tk>
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Matt Clay (@mattclay) <matt@mystile.com>
|
||||
|
|
857
plugins/connection/proxmox_pct_remote.py
Normal file
857
plugins/connection/proxmox_pct_remote.py
Normal file
|
@ -0,0 +1,857 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Derived from ansible/plugins/connection/paramiko_ssh.py (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
|
||||
# Copyright (c) 2024 Nils Stein (@mietzen) <github.nstein@mailbox.org>
|
||||
# Copyright (c) 2024 Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Nils Stein (@mietzen) <github.nstein@mailbox.org>
|
||||
name: proxmox_pct_remote
|
||||
short_description: Run tasks in Proxmox LXC container instances using pct CLI via SSH
|
||||
requirements:
|
||||
- paramiko
|
||||
description:
|
||||
- Run commands or put/fetch files to an existing Proxmox LXC container using pct CLI via SSH.
|
||||
- Uses the Python SSH implementation (Paramiko) to connect to the Proxmox host.
|
||||
version_added: "10.3.0"
|
||||
options:
|
||||
remote_addr:
|
||||
description:
|
||||
- Address of the remote target.
|
||||
default: inventory_hostname
|
||||
type: string
|
||||
vars:
|
||||
- name: inventory_hostname
|
||||
- name: ansible_host
|
||||
- name: ansible_ssh_host
|
||||
- name: ansible_paramiko_host
|
||||
port:
|
||||
description: Remote port to connect to.
|
||||
type: int
|
||||
default: 22
|
||||
ini:
|
||||
- section: defaults
|
||||
key: remote_port
|
||||
- section: paramiko_connection
|
||||
key: remote_port
|
||||
env:
|
||||
- name: ANSIBLE_REMOTE_PORT
|
||||
- name: ANSIBLE_REMOTE_PARAMIKO_PORT
|
||||
vars:
|
||||
- name: ansible_port
|
||||
- name: ansible_ssh_port
|
||||
- name: ansible_paramiko_port
|
||||
keyword:
|
||||
- name: port
|
||||
remote_user:
|
||||
description:
|
||||
- User to login/authenticate as.
|
||||
- Can be set from the CLI via the C(--user) or C(-u) options.
|
||||
type: string
|
||||
vars:
|
||||
- name: ansible_user
|
||||
- name: ansible_ssh_user
|
||||
- name: ansible_paramiko_user
|
||||
env:
|
||||
- name: ANSIBLE_REMOTE_USER
|
||||
- name: ANSIBLE_PARAMIKO_REMOTE_USER
|
||||
ini:
|
||||
- section: defaults
|
||||
key: remote_user
|
||||
- section: paramiko_connection
|
||||
key: remote_user
|
||||
keyword:
|
||||
- name: remote_user
|
||||
password:
|
||||
description:
|
||||
- Secret used to either login the SSH server or as a passphrase for SSH keys that require it.
|
||||
- Can be set from the CLI via the C(--ask-pass) option.
|
||||
type: string
|
||||
vars:
|
||||
- name: ansible_password
|
||||
- name: ansible_ssh_pass
|
||||
- name: ansible_ssh_password
|
||||
- name: ansible_paramiko_pass
|
||||
- name: ansible_paramiko_password
|
||||
use_rsa_sha2_algorithms:
|
||||
description:
|
||||
- Whether or not to enable RSA SHA2 algorithms for pubkeys and hostkeys.
|
||||
- On paramiko versions older than 2.9, this only affects hostkeys.
|
||||
- For behavior matching paramiko<2.9 set this to V(false).
|
||||
vars:
|
||||
- name: ansible_paramiko_use_rsa_sha2_algorithms
|
||||
ini:
|
||||
- {key: use_rsa_sha2_algorithms, section: paramiko_connection}
|
||||
env:
|
||||
- {name: ANSIBLE_PARAMIKO_USE_RSA_SHA2_ALGORITHMS}
|
||||
default: true
|
||||
type: boolean
|
||||
host_key_auto_add:
|
||||
description: "Automatically add host keys to C(~/.ssh/known_hosts)."
|
||||
env:
|
||||
- name: ANSIBLE_PARAMIKO_HOST_KEY_AUTO_ADD
|
||||
ini:
|
||||
- key: host_key_auto_add
|
||||
section: paramiko_connection
|
||||
type: boolean
|
||||
look_for_keys:
|
||||
default: True
|
||||
description: "Set to V(false) to disable searching for private key files in C(~/.ssh/)."
|
||||
env:
|
||||
- name: ANSIBLE_PARAMIKO_LOOK_FOR_KEYS
|
||||
ini:
|
||||
- {key: look_for_keys, section: paramiko_connection}
|
||||
type: boolean
|
||||
proxy_command:
|
||||
default: ""
|
||||
description:
|
||||
- Proxy information for running the connection via a jumphost.
|
||||
type: string
|
||||
env:
|
||||
- name: ANSIBLE_PARAMIKO_PROXY_COMMAND
|
||||
ini:
|
||||
- {key: proxy_command, section: paramiko_connection}
|
||||
vars:
|
||||
- name: ansible_paramiko_proxy_command
|
||||
pty:
|
||||
default: True
|
||||
description: "C(sudo) usually requires a PTY, V(true) to give a PTY and V(false) to not give a PTY."
|
||||
env:
|
||||
- name: ANSIBLE_PARAMIKO_PTY
|
||||
ini:
|
||||
- section: paramiko_connection
|
||||
key: pty
|
||||
type: boolean
|
||||
record_host_keys:
|
||||
default: True
|
||||
description: "Save the host keys to a file."
|
||||
env:
|
||||
- name: ANSIBLE_PARAMIKO_RECORD_HOST_KEYS
|
||||
ini:
|
||||
- section: paramiko_connection
|
||||
key: record_host_keys
|
||||
type: boolean
|
||||
host_key_checking:
|
||||
description: "Set this to V(false) if you want to avoid host key checking by the underlying tools Ansible uses to connect to the host."
|
||||
type: boolean
|
||||
default: true
|
||||
env:
|
||||
- name: ANSIBLE_HOST_KEY_CHECKING
|
||||
- name: ANSIBLE_SSH_HOST_KEY_CHECKING
|
||||
- name: ANSIBLE_PARAMIKO_HOST_KEY_CHECKING
|
||||
ini:
|
||||
- section: defaults
|
||||
key: host_key_checking
|
||||
- section: paramiko_connection
|
||||
key: host_key_checking
|
||||
vars:
|
||||
- name: ansible_host_key_checking
|
||||
- name: ansible_ssh_host_key_checking
|
||||
- name: ansible_paramiko_host_key_checking
|
||||
use_persistent_connections:
|
||||
description: "Toggles the use of persistence for connections."
|
||||
type: boolean
|
||||
default: False
|
||||
env:
|
||||
- name: ANSIBLE_USE_PERSISTENT_CONNECTIONS
|
||||
ini:
|
||||
- section: defaults
|
||||
key: use_persistent_connections
|
||||
banner_timeout:
|
||||
type: float
|
||||
default: 30
|
||||
description:
|
||||
- Configures, in seconds, the amount of time to wait for the SSH
|
||||
banner to be presented. This option is supported by paramiko
|
||||
version 1.15.0 or newer.
|
||||
ini:
|
||||
- section: paramiko_connection
|
||||
key: banner_timeout
|
||||
env:
|
||||
- name: ANSIBLE_PARAMIKO_BANNER_TIMEOUT
|
||||
timeout:
|
||||
type: int
|
||||
default: 10
|
||||
description: Number of seconds until the plugin gives up on failing to establish a TCP connection.
|
||||
ini:
|
||||
- section: defaults
|
||||
key: timeout
|
||||
- section: ssh_connection
|
||||
key: timeout
|
||||
- section: paramiko_connection
|
||||
key: timeout
|
||||
env:
|
||||
- name: ANSIBLE_TIMEOUT
|
||||
- name: ANSIBLE_SSH_TIMEOUT
|
||||
- name: ANSIBLE_PARAMIKO_TIMEOUT
|
||||
vars:
|
||||
- name: ansible_ssh_timeout
|
||||
- name: ansible_paramiko_timeout
|
||||
cli:
|
||||
- name: timeout
|
||||
lock_file_timeout:
|
||||
type: int
|
||||
default: 60
|
||||
description: Number of seconds until the plugin gives up on trying to write a lock file when writing SSH known host keys.
|
||||
vars:
|
||||
- name: ansible_lock_file_timeout
|
||||
env:
|
||||
- name: ANSIBLE_LOCK_FILE_TIMEOUT
|
||||
private_key_file:
|
||||
description:
|
||||
- Path to private key file to use for authentication.
|
||||
type: string
|
||||
ini:
|
||||
- section: defaults
|
||||
key: private_key_file
|
||||
- section: paramiko_connection
|
||||
key: private_key_file
|
||||
env:
|
||||
- name: ANSIBLE_PRIVATE_KEY_FILE
|
||||
- name: ANSIBLE_PARAMIKO_PRIVATE_KEY_FILE
|
||||
vars:
|
||||
- name: ansible_private_key_file
|
||||
- name: ansible_ssh_private_key_file
|
||||
- name: ansible_paramiko_private_key_file
|
||||
cli:
|
||||
- name: private_key_file
|
||||
option: "--private-key"
|
||||
vmid:
|
||||
description:
|
||||
- LXC Container ID
|
||||
type: int
|
||||
vars:
|
||||
- name: proxmox_vmid
|
||||
proxmox_become_method:
|
||||
description:
|
||||
- Become command used in proxmox
|
||||
type: str
|
||||
default: sudo
|
||||
vars:
|
||||
- name: proxmox_become_method
|
||||
notes:
|
||||
- >
|
||||
When NOT using this plugin as root, you need to have a become mechanism,
|
||||
e.g. C(sudo), installed on Proxmox and setup so we can run it without prompting for the password.
|
||||
Inside the container, we need a shell, for example C(sh) and the C(cat) command to be available in the C(PATH) for this plugin to work.
|
||||
"""
|
||||
|
||||
EXAMPLES = r"""
|
||||
# --------------------------------------------------------------
|
||||
# Setup sudo with password less access to pct for user 'ansible':
|
||||
# --------------------------------------------------------------
|
||||
#
|
||||
# Open a Proxmox root shell and execute:
|
||||
# $ useradd -d /opt/ansible-pct -r -m -s /bin/sh ansible
|
||||
# $ mkdir -p /opt/ansible-pct/.ssh
|
||||
# $ ssh-keygen -t ed25519 -C 'ansible' -N "" -f /opt/ansible-pct/.ssh/ansible <<< y > /dev/null
|
||||
# $ cat /opt/ansible-pct/.ssh/ansible
|
||||
# $ mv /opt/ansible-pct/.ssh/ansible.pub /opt/ansible-pct/.ssh/authorized-keys
|
||||
# $ rm /opt/ansible-pct/.ssh/ansible*
|
||||
# $ chown -R ansible:ansible /opt/ansible-pct/.ssh
|
||||
# $ chmod 700 /opt/ansible-pct/.ssh
|
||||
# $ chmod 600 /opt/ansible-pct/.ssh/authorized-keys
|
||||
# $ echo 'ansible ALL = (root) NOPASSWD: /usr/sbin/pct' > /etc/sudoers.d/ansible_pct
|
||||
#
|
||||
# Save the displayed private key and add it to your ssh-agent
|
||||
#
|
||||
# Or use ansible:
|
||||
# ---
|
||||
# - name: Setup ansible-pct user and configure environment on Proxmox host
|
||||
# hosts: proxmox
|
||||
# become: true
|
||||
# gather_facts: false
|
||||
#
|
||||
# tasks:
|
||||
# - name: Create ansible user
|
||||
# ansible.builtin.user:
|
||||
# name: ansible
|
||||
# comment: Ansible User
|
||||
# home: /opt/ansible-pct
|
||||
# shell: /bin/sh
|
||||
# create_home: true
|
||||
# system: true
|
||||
#
|
||||
# - name: Create .ssh directory
|
||||
# ansible.builtin.file:
|
||||
# path: /opt/ansible-pct/.ssh
|
||||
# state: directory
|
||||
# owner: ansible
|
||||
# group: ansible
|
||||
# mode: '0700'
|
||||
#
|
||||
# - name: Generate SSH key for ansible user
|
||||
# community.crypto.openssh_keypair:
|
||||
# path: /opt/ansible-pct/.ssh/ansible
|
||||
# type: ed25519
|
||||
# comment: 'ansible'
|
||||
# force: true
|
||||
# mode: '0600'
|
||||
# owner: ansible
|
||||
# group: ansible
|
||||
#
|
||||
# - name: Set public key as authorized key
|
||||
# ansible.builtin.copy:
|
||||
# src: /opt/ansible-pct/.ssh/ansible.pub
|
||||
# dest: /opt/ansible-pct/.ssh/authorized-keys
|
||||
# remote_src: yes
|
||||
# owner: ansible
|
||||
# group: ansible
|
||||
# mode: '0600'
|
||||
#
|
||||
# - name: Add sudoers entry for ansible user
|
||||
# ansible.builtin.copy:
|
||||
# content: 'ansible ALL = (root) NOPASSWD: /usr/sbin/pct'
|
||||
# dest: /etc/sudoers.d/ansible_pct
|
||||
# owner: root
|
||||
# group: root
|
||||
# mode: '0440'
|
||||
#
|
||||
# - name: Fetch private SSH key to localhost
|
||||
# ansible.builtin.fetch:
|
||||
# src: /opt/ansible-pct/.ssh/ansible
|
||||
# dest: ~/.ssh/proxmox_ansible_private_key
|
||||
# flat: yes
|
||||
# fail_on_missing: true
|
||||
#
|
||||
# - name: Clean up generated SSH keys
|
||||
# ansible.builtin.file:
|
||||
# path: /opt/ansible-pct/.ssh/ansible*
|
||||
# state: absent
|
||||
#
|
||||
# - name: Configure private key permissions on localhost
|
||||
# hosts: localhost
|
||||
# tasks:
|
||||
# - name: Set permissions for fetched private key
|
||||
# ansible.builtin.file:
|
||||
# path: ~/.ssh/proxmox_ansible_private_key
|
||||
# mode: '0600'
|
||||
#
|
||||
# --------------------------------
|
||||
# Static inventory file: hosts.yml
|
||||
# --------------------------------
|
||||
# all:
|
||||
# children:
|
||||
# lxc:
|
||||
# hosts:
|
||||
# container-1:
|
||||
# ansible_host: 10.0.0.10
|
||||
# proxmox_vmid: 100
|
||||
# ansible_connection: community.general.proxmox_pct_remote
|
||||
# ansible_user: ansible
|
||||
# container-2:
|
||||
# ansible_host: 10.0.0.10
|
||||
# proxmox_vmid: 200
|
||||
# ansible_connection: community.general.proxmox_pct_remote
|
||||
# ansible_user: ansible
|
||||
# proxmox:
|
||||
# hosts:
|
||||
# proxmox-1:
|
||||
# ansible_host: 10.0.0.10
|
||||
#
|
||||
#
|
||||
# ---------------------------------------------
|
||||
# Dynamic inventory file: inventory.proxmox.yml
|
||||
# ---------------------------------------------
|
||||
# plugin: community.general.proxmox
|
||||
# url: https://10.0.0.10:8006
|
||||
# validate_certs: false
|
||||
# user: ansible@pam
|
||||
# token_id: ansible
|
||||
# token_secret: !vault |
|
||||
# $ANSIBLE_VAULT;1.1;AES256
|
||||
# ...
|
||||
|
||||
# want_facts: true
|
||||
# exclude_nodes: true
|
||||
# filters:
|
||||
# - proxmox_vmtype == "lxc"
|
||||
# want_proxmox_nodes_ansible_host: false
|
||||
# compose:
|
||||
# ansible_host: "'10.0.0.10'"
|
||||
# ansible_connection: "'community.general.proxmox_pct_remote'"
|
||||
# ansible_user: "'ansible'"
|
||||
#
|
||||
#
|
||||
# ----------------------
|
||||
# Playbook: playbook.yml
|
||||
# ----------------------
|
||||
---
|
||||
- hosts: lxc
|
||||
# On nodes with many containers you might want to deactivate the devices facts
|
||||
# or set `gather_facts: false` if you don't need them.
|
||||
# More info on gathering fact subsets:
|
||||
# https://docs.ansible.com/ansible/latest/collections/ansible/builtin/setup_module.html
|
||||
#
|
||||
# gather_facts: true
|
||||
# gather_subset:
|
||||
# - "!devices"
|
||||
tasks:
|
||||
- name: Ping LXC container
|
||||
ansible.builtin.ping:
|
||||
"""
|
||||
|
||||
import os
|
||||
import pathlib
|
||||
import socket
|
||||
import tempfile
|
||||
import typing as t
|
||||
|
||||
from ansible.errors import (
|
||||
AnsibleAuthenticationFailure,
|
||||
AnsibleConnectionFailure,
|
||||
AnsibleError,
|
||||
)
|
||||
from ansible_collections.community.general.plugins.module_utils._filelock import FileLock, LockTimeout
|
||||
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
|
||||
from ansible.module_utils.compat.paramiko import PARAMIKO_IMPORT_ERR, paramiko
|
||||
from ansible.module_utils.compat.version import LooseVersion
|
||||
from ansible.plugins.connection import ConnectionBase
|
||||
from ansible.utils.display import Display
|
||||
from ansible.utils.path import makedirs_safe
|
||||
from binascii import hexlify
|
||||
|
||||
|
||||
display = Display()
|
||||
|
||||
|
||||
def authenticity_msg(hostname: str, ktype: str, fingerprint: str) -> str:
|
||||
msg = f"""
|
||||
paramiko: The authenticity of host '{hostname}' can't be established.
|
||||
The {ktype} key fingerprint is {fingerprint}.
|
||||
Are you sure you want to continue connecting (yes/no)?
|
||||
"""
|
||||
return msg
|
||||
|
||||
|
||||
MissingHostKeyPolicy: type = object
|
||||
if paramiko:
|
||||
MissingHostKeyPolicy = paramiko.MissingHostKeyPolicy
|
||||
|
||||
|
||||
class MyAddPolicy(MissingHostKeyPolicy):
|
||||
"""
|
||||
Based on AutoAddPolicy in paramiko so we can determine when keys are added
|
||||
|
||||
and also prompt for input.
|
||||
|
||||
Policy for automatically adding the hostname and new host key to the
|
||||
local L{HostKeys} object, and saving it. This is used by L{SSHClient}.
|
||||
"""
|
||||
|
||||
def __init__(self, connection: Connection) -> None:
|
||||
self.connection = connection
|
||||
self._options = connection._options
|
||||
|
||||
def missing_host_key(self, client, hostname, key) -> None:
|
||||
|
||||
if all((self.connection.get_option('host_key_checking'), not self.connection.get_option('host_key_auto_add'))):
|
||||
|
||||
fingerprint = hexlify(key.get_fingerprint())
|
||||
ktype = key.get_name()
|
||||
|
||||
if self.connection.get_option('use_persistent_connections') or self.connection.force_persistence:
|
||||
# don't print the prompt string since the user cannot respond
|
||||
# to the question anyway
|
||||
raise AnsibleError(authenticity_msg(hostname, ktype, fingerprint)[1:92])
|
||||
|
||||
inp = to_text(
|
||||
display.prompt_until(authenticity_msg(hostname, ktype, fingerprint), private=False),
|
||||
errors='surrogate_or_strict'
|
||||
)
|
||||
|
||||
if inp.lower() not in ['yes', 'y', '']:
|
||||
raise AnsibleError('host connection rejected by user')
|
||||
|
||||
key._added_by_ansible_this_time = True
|
||||
|
||||
# existing implementation below:
|
||||
client._host_keys.add(hostname, key.get_name(), key)
|
||||
|
||||
# host keys are actually saved in close() function below
|
||||
# in order to control ordering.
|
||||
|
||||
|
||||
class Connection(ConnectionBase):
|
||||
""" SSH based connections (paramiko) to Proxmox pct """
|
||||
|
||||
transport = 'community.general.proxmox_pct_remote'
|
||||
_log_channel: str | None = None
|
||||
|
||||
def __init__(self, play_context, new_stdin, *args, **kwargs):
|
||||
super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
|
||||
|
||||
def _set_log_channel(self, name: str) -> None:
|
||||
""" Mimic paramiko.SSHClient.set_log_channel """
|
||||
self._log_channel = name
|
||||
|
||||
def _parse_proxy_command(self, port: int = 22) -> dict[str, t.Any]:
|
||||
proxy_command = self.get_option('proxy_command') or None
|
||||
|
||||
sock_kwarg = {}
|
||||
if proxy_command:
|
||||
replacers = {
|
||||
'%h': self.get_option('remote_addr'),
|
||||
'%p': port,
|
||||
'%r': self.get_option('remote_user')
|
||||
}
|
||||
for find, replace in replacers.items():
|
||||
proxy_command = proxy_command.replace(find, str(replace))
|
||||
try:
|
||||
sock_kwarg = {'sock': paramiko.ProxyCommand(proxy_command)}
|
||||
display.vvv(f'CONFIGURE PROXY COMMAND FOR CONNECTION: {proxy_command}', host=self.get_option('remote_addr'))
|
||||
except AttributeError:
|
||||
display.warning('Paramiko ProxyCommand support unavailable. '
|
||||
'Please upgrade to Paramiko 1.9.0 or newer. '
|
||||
'Not using configured ProxyCommand')
|
||||
|
||||
return sock_kwarg
|
||||
|
||||
def _connect(self) -> Connection:
|
||||
""" activates the connection object """
|
||||
|
||||
if paramiko is None:
|
||||
raise AnsibleError(f'paramiko is not installed: {to_native(PARAMIKO_IMPORT_ERR)}')
|
||||
|
||||
port = self.get_option('port')
|
||||
display.vvv(f'ESTABLISH PARAMIKO SSH CONNECTION FOR USER: {self.get_option("remote_user")} on PORT {to_text(port)} TO {self.get_option("remote_addr")}',
|
||||
host=self.get_option('remote_addr'))
|
||||
|
||||
ssh = paramiko.SSHClient()
|
||||
|
||||
# Set pubkey and hostkey algorithms to disable, the only manipulation allowed currently
|
||||
# is keeping or omitting rsa-sha2 algorithms
|
||||
# default_keys: t.Tuple[str] = ()
|
||||
paramiko_preferred_pubkeys = getattr(paramiko.Transport, '_preferred_pubkeys', ())
|
||||
paramiko_preferred_hostkeys = getattr(paramiko.Transport, '_preferred_keys', ())
|
||||
use_rsa_sha2_algorithms = self.get_option('use_rsa_sha2_algorithms')
|
||||
disabled_algorithms: t.Dict[str, t.Iterable[str]] = {}
|
||||
if not use_rsa_sha2_algorithms:
|
||||
if paramiko_preferred_pubkeys:
|
||||
disabled_algorithms['pubkeys'] = tuple(a for a in paramiko_preferred_pubkeys if 'rsa-sha2' in a)
|
||||
if paramiko_preferred_hostkeys:
|
||||
disabled_algorithms['keys'] = tuple(a for a in paramiko_preferred_hostkeys if 'rsa-sha2' in a)
|
||||
|
||||
# override paramiko's default logger name
|
||||
if self._log_channel is not None:
|
||||
ssh.set_log_channel(self._log_channel)
|
||||
|
||||
self.keyfile = os.path.expanduser('~/.ssh/known_hosts')
|
||||
|
||||
if self.get_option('host_key_checking'):
|
||||
for ssh_known_hosts in ('/etc/ssh/ssh_known_hosts', '/etc/openssh/ssh_known_hosts'):
|
||||
try:
|
||||
ssh.load_system_host_keys(ssh_known_hosts)
|
||||
break
|
||||
except IOError:
|
||||
pass # file was not found, but not required to function
|
||||
except paramiko.hostkeys.InvalidHostKey as e:
|
||||
raise AnsibleConnectionFailure(f'Invalid host key: {to_text(e.line)}')
|
||||
try:
|
||||
ssh.load_system_host_keys()
|
||||
except paramiko.hostkeys.InvalidHostKey as e:
|
||||
raise AnsibleConnectionFailure(f'Invalid host key: {to_text(e.line)}')
|
||||
|
||||
ssh_connect_kwargs = self._parse_proxy_command(port)
|
||||
ssh.set_missing_host_key_policy(MyAddPolicy(self))
|
||||
conn_password = self.get_option('password')
|
||||
allow_agent = True
|
||||
|
||||
if conn_password is not None:
|
||||
allow_agent = False
|
||||
|
||||
try:
|
||||
key_filename = None
|
||||
if self.get_option('private_key_file'):
|
||||
key_filename = os.path.expanduser(self.get_option('private_key_file'))
|
||||
|
||||
# paramiko 2.2 introduced auth_timeout parameter
|
||||
if LooseVersion(paramiko.__version__) >= LooseVersion('2.2.0'):
|
||||
ssh_connect_kwargs['auth_timeout'] = self.get_option('timeout')
|
||||
|
||||
# paramiko 1.15 introduced banner timeout parameter
|
||||
if LooseVersion(paramiko.__version__) >= LooseVersion('1.15.0'):
|
||||
ssh_connect_kwargs['banner_timeout'] = self.get_option('banner_timeout')
|
||||
|
||||
ssh.connect(
|
||||
self.get_option('remote_addr').lower(),
|
||||
username=self.get_option('remote_user'),
|
||||
allow_agent=allow_agent,
|
||||
look_for_keys=self.get_option('look_for_keys'),
|
||||
key_filename=key_filename,
|
||||
password=conn_password,
|
||||
timeout=self.get_option('timeout'),
|
||||
port=port,
|
||||
disabled_algorithms=disabled_algorithms,
|
||||
**ssh_connect_kwargs,
|
||||
)
|
||||
except paramiko.ssh_exception.BadHostKeyException as e:
|
||||
raise AnsibleConnectionFailure(f'host key mismatch for {to_text(e.hostname)}')
|
||||
except paramiko.ssh_exception.AuthenticationException as e:
|
||||
msg = f'Failed to authenticate: {e}'
|
||||
raise AnsibleAuthenticationFailure(msg)
|
||||
except Exception as e:
|
||||
msg = to_text(e)
|
||||
if u'PID check failed' in msg:
|
||||
raise AnsibleError('paramiko version issue, please upgrade paramiko on the machine running ansible')
|
||||
elif u'Private key file is encrypted' in msg:
|
||||
msg = f'ssh {self.get_option("remote_user")}@{self.get_options("remote_addr")}:{port} : ' + \
|
||||
f'{msg}\nTo connect as a different user, use -u <username>.'
|
||||
raise AnsibleConnectionFailure(msg)
|
||||
else:
|
||||
raise AnsibleConnectionFailure(msg)
|
||||
self.ssh = ssh
|
||||
self._connected = True
|
||||
return self
|
||||
|
||||
def _any_keys_added(self) -> bool:
|
||||
for hostname, keys in self.ssh._host_keys.items():
|
||||
for keytype, key in keys.items():
|
||||
added_this_time = getattr(key, '_added_by_ansible_this_time', False)
|
||||
if added_this_time:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _save_ssh_host_keys(self, filename: str) -> None:
|
||||
"""
|
||||
not using the paramiko save_ssh_host_keys function as we want to add new SSH keys at the bottom so folks
|
||||
don't complain about it :)
|
||||
"""
|
||||
|
||||
if not self._any_keys_added():
|
||||
return
|
||||
|
||||
path = os.path.expanduser('~/.ssh')
|
||||
makedirs_safe(path)
|
||||
|
||||
with open(filename, 'w') as f:
|
||||
for hostname, keys in self.ssh._host_keys.items():
|
||||
for keytype, key in keys.items():
|
||||
# was f.write
|
||||
added_this_time = getattr(key, '_added_by_ansible_this_time', False)
|
||||
if not added_this_time:
|
||||
f.write(f'{hostname} {keytype} {key.get_base64()}\n')
|
||||
|
||||
for hostname, keys in self.ssh._host_keys.items():
|
||||
for keytype, key in keys.items():
|
||||
added_this_time = getattr(key, '_added_by_ansible_this_time', False)
|
||||
if added_this_time:
|
||||
f.write(f'{hostname} {keytype} {key.get_base64()}\n')
|
||||
|
||||
def _build_pct_command(self, cmd: str) -> str:
|
||||
cmd = ['/usr/sbin/pct', 'exec', str(self.get_option('vmid')), '--', cmd]
|
||||
if self.get_option('remote_user') != 'root':
|
||||
cmd = [self.get_option('proxmox_become_method')] + cmd
|
||||
display.vvv(f'INFO Running as non root user: {self.get_option("remote_user")}, trying to run pct with become method: ' +
|
||||
f'{self.get_option("proxmox_become_method")}',
|
||||
host=self.get_option('remote_addr'))
|
||||
return ' '.join(cmd)
|
||||
|
||||
def exec_command(self, cmd: str, in_data: bytes | None = None, sudoable: bool = True) -> tuple[int, bytes, bytes]:
|
||||
""" run a command on inside the LXC container """
|
||||
|
||||
cmd = self._build_pct_command(cmd)
|
||||
|
||||
super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
|
||||
|
||||
bufsize = 4096
|
||||
|
||||
try:
|
||||
self.ssh.get_transport().set_keepalive(5)
|
||||
chan = self.ssh.get_transport().open_session()
|
||||
except Exception as e:
|
||||
text_e = to_text(e)
|
||||
msg = 'Failed to open session'
|
||||
if text_e:
|
||||
msg += f': {text_e}'
|
||||
raise AnsibleConnectionFailure(to_native(msg))
|
||||
|
||||
# sudo usually requires a PTY (cf. requiretty option), therefore
|
||||
# we give it one by default (pty=True in ansible.cfg), and we try
|
||||
# to initialise from the calling environment when sudoable is enabled
|
||||
if self.get_option('pty') and sudoable:
|
||||
chan.get_pty(term=os.getenv('TERM', 'vt100'), width=int(os.getenv('COLUMNS', 0)), height=int(os.getenv('LINES', 0)))
|
||||
|
||||
display.vvv(f'EXEC {cmd}', host=self.get_option('remote_addr'))
|
||||
|
||||
cmd = to_bytes(cmd, errors='surrogate_or_strict')
|
||||
|
||||
no_prompt_out = b''
|
||||
no_prompt_err = b''
|
||||
become_output = b''
|
||||
|
||||
try:
|
||||
chan.exec_command(cmd)
|
||||
if self.become and self.become.expect_prompt():
|
||||
password_prompt = False
|
||||
become_success = False
|
||||
while not (become_success or password_prompt):
|
||||
display.debug('Waiting for Privilege Escalation input')
|
||||
|
||||
chunk = chan.recv(bufsize)
|
||||
display.debug(f'chunk is: {to_text(chunk)}')
|
||||
if not chunk:
|
||||
if b'unknown user' in become_output:
|
||||
n_become_user = to_native(self.become.get_option('become_user'))
|
||||
raise AnsibleError(f'user {n_become_user} does not exist')
|
||||
else:
|
||||
break
|
||||
# raise AnsibleError('ssh connection closed waiting for password prompt')
|
||||
become_output += chunk
|
||||
|
||||
# need to check every line because we might get lectured
|
||||
# and we might get the middle of a line in a chunk
|
||||
for line in become_output.splitlines(True):
|
||||
if self.become.check_success(line):
|
||||
become_success = True
|
||||
break
|
||||
elif self.become.check_password_prompt(line):
|
||||
password_prompt = True
|
||||
break
|
||||
|
||||
if password_prompt:
|
||||
if self.become:
|
||||
become_pass = self.become.get_option('become_pass')
|
||||
chan.sendall(to_bytes(become_pass, errors='surrogate_or_strict') + b'\n')
|
||||
else:
|
||||
raise AnsibleError('A password is required but none was supplied')
|
||||
else:
|
||||
no_prompt_out += become_output
|
||||
no_prompt_err += become_output
|
||||
|
||||
if in_data:
|
||||
for i in range(0, len(in_data), bufsize):
|
||||
chan.send(in_data[i:i + bufsize])
|
||||
chan.shutdown_write()
|
||||
elif in_data == b'':
|
||||
chan.shutdown_write()
|
||||
|
||||
except socket.timeout:
|
||||
raise AnsibleError('ssh timed out waiting for privilege escalation.\n' + to_text(become_output))
|
||||
|
||||
stdout = b''.join(chan.makefile('rb', bufsize))
|
||||
stderr = b''.join(chan.makefile_stderr('rb', bufsize))
|
||||
returncode = chan.recv_exit_status()
|
||||
|
||||
if 'pct: not found' in stderr.decode('utf-8'):
|
||||
raise AnsibleError(
|
||||
f'pct not found in path of host: {to_text(self.get_option("remote_addr"))}')
|
||||
|
||||
return (returncode, no_prompt_out + stdout, no_prompt_out + stderr)
|
||||
|
||||
def put_file(self, in_path: str, out_path: str) -> None:
|
||||
""" transfer a file from local to remote """
|
||||
|
||||
display.vvv(f'PUT {in_path} TO {out_path}', host=self.get_option('remote_addr'))
|
||||
try:
|
||||
with open(in_path, 'rb') as f:
|
||||
data = f.read()
|
||||
returncode, stdout, stderr = self.exec_command(
|
||||
' '.join([
|
||||
self._shell.executable, '-c',
|
||||
self._shell.quote(f'cat > {out_path}')]),
|
||||
in_data=data,
|
||||
sudoable=False)
|
||||
if returncode != 0:
|
||||
if 'cat: not found' in stderr.decode('utf-8'):
|
||||
raise AnsibleError(
|
||||
f'cat not found in path of container: {to_text(self.get_option("vmid"))}')
|
||||
raise AnsibleError(
|
||||
f'{to_text(stdout)}\n{to_text(stderr)}')
|
||||
except Exception as e:
|
||||
raise AnsibleError(
|
||||
f'error occurred while putting file from {in_path} to {out_path}!\n{to_text(e)}')
|
||||
|
||||
def fetch_file(self, in_path: str, out_path: str) -> None:
|
||||
""" save a remote file to the specified path """
|
||||
|
||||
display.vvv(f'FETCH {in_path} TO {out_path}', host=self.get_option('remote_addr'))
|
||||
try:
|
||||
returncode, stdout, stderr = self.exec_command(
|
||||
' '.join([
|
||||
self._shell.executable, '-c',
|
||||
self._shell.quote(f'cat {in_path}')]),
|
||||
sudoable=False)
|
||||
if returncode != 0:
|
||||
if 'cat: not found' in stderr.decode('utf-8'):
|
||||
raise AnsibleError(
|
||||
f'cat not found in path of container: {to_text(self.get_option("vmid"))}')
|
||||
raise AnsibleError(
|
||||
f'{to_text(stdout)}\n{to_text(stderr)}')
|
||||
with open(out_path, 'wb') as f:
|
||||
f.write(stdout)
|
||||
except Exception as e:
|
||||
raise AnsibleError(
|
||||
f'error occurred while fetching file from {in_path} to {out_path}!\n{to_text(e)}')
|
||||
|
||||
def reset(self) -> None:
|
||||
""" reset the connection """
|
||||
|
||||
if not self._connected:
|
||||
return
|
||||
self.close()
|
||||
self._connect()
|
||||
|
||||
def close(self) -> None:
|
||||
""" terminate the connection """
|
||||
|
||||
if self.get_option('host_key_checking') and self.get_option('record_host_keys') and self._any_keys_added():
|
||||
# add any new SSH host keys -- warning -- this could be slow
|
||||
# (This doesn't acquire the connection lock because it needs
|
||||
# to exclude only other known_hosts writers, not connections
|
||||
# that are starting up.)
|
||||
lockfile = os.path.basename(self.keyfile)
|
||||
dirname = os.path.dirname(self.keyfile)
|
||||
makedirs_safe(dirname)
|
||||
tmp_keyfile_name = None
|
||||
try:
|
||||
with FileLock().lock_file(lockfile, dirname, self.get_option('lock_file_timeout')):
|
||||
# just in case any were added recently
|
||||
|
||||
self.ssh.load_system_host_keys()
|
||||
self.ssh._host_keys.update(self.ssh._system_host_keys)
|
||||
|
||||
# gather information about the current key file, so
|
||||
# we can ensure the new file has the correct mode/owner
|
||||
|
||||
key_dir = os.path.dirname(self.keyfile)
|
||||
if os.path.exists(self.keyfile):
|
||||
key_stat = os.stat(self.keyfile)
|
||||
mode = key_stat.st_mode & 0o777
|
||||
uid = key_stat.st_uid
|
||||
gid = key_stat.st_gid
|
||||
else:
|
||||
mode = 0o644
|
||||
uid = os.getuid()
|
||||
gid = os.getgid()
|
||||
|
||||
# Save the new keys to a temporary file and move it into place
|
||||
# rather than rewriting the file. We set delete=False because
|
||||
# the file will be moved into place rather than cleaned up.
|
||||
|
||||
with tempfile.NamedTemporaryFile(dir=key_dir, delete=False) as tmp_keyfile:
|
||||
tmp_keyfile_name = tmp_keyfile.name
|
||||
os.chmod(tmp_keyfile_name, mode)
|
||||
os.chown(tmp_keyfile_name, uid, gid)
|
||||
self._save_ssh_host_keys(tmp_keyfile_name)
|
||||
|
||||
os.rename(tmp_keyfile_name, self.keyfile)
|
||||
except LockTimeout:
|
||||
raise AnsibleError(
|
||||
f'writing lock file for {self.keyfile} ran in to the timeout of {self.get_option("lock_file_timeout")}s')
|
||||
except paramiko.hostkeys.InvalidHostKey as e:
|
||||
raise AnsibleConnectionFailure(f'Invalid host key: {e.line}')
|
||||
except Exception as e:
|
||||
# unable to save keys, including scenario when key was invalid
|
||||
# and caught earlier
|
||||
raise AnsibleError(
|
||||
f'error occurred while writing SSH host keys!\n{to_text(e)}')
|
||||
finally:
|
||||
if tmp_keyfile_name is not None:
|
||||
pathlib.Path(tmp_keyfile_name).unlink(missing_ok=True)
|
||||
|
||||
self.ssh.close()
|
||||
self._connected = False
|
|
@ -8,8 +8,7 @@
|
|||
#
|
||||
# Written by: Kushal Das (https://github.com/kushaldas)
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Michael Scherer (@mscherer) <misc@zarb.org>
|
||||
|
|
|
@ -8,8 +8,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author: Ansible Core Team
|
||||
|
|
|
@ -57,6 +57,12 @@ options:
|
|||
type: str
|
||||
version_added: 3.0.0
|
||||
|
||||
refresh_token:
|
||||
description:
|
||||
- Authentication refresh token for Keycloak API.
|
||||
type: str
|
||||
version_added: 10.3.0
|
||||
|
||||
validate_certs:
|
||||
description:
|
||||
- Verify TLS certificates (do not disable this in production).
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: counter
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
# Copyright (c) 2022, Julien Riou <julien@riou.xyz>
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
from ansible.errors import AnsibleFilterError
|
||||
from ansible.module_utils.common.text.converters import to_bytes
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: dict
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: dict_kv
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: from_csv
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: from_ini
|
||||
|
@ -44,7 +44,6 @@ _value:
|
|||
type: dictionary
|
||||
"""
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
from ansible.errors import AnsibleFilterError
|
||||
from ansible.module_utils.six import string_types
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: groupby_as_dict
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
from ansible.errors import (
|
||||
AnsibleError,
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
#
|
||||
# contributed by Kelly Brazil <kellyjonbrazil@gmail.com>
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: jc
|
||||
|
|
56
plugins/filter/json_diff.yml
Normal file
56
plugins/filter/json_diff.yml
Normal file
|
@ -0,0 +1,56 @@
|
|||
---
|
||||
# Copyright (c) Stanislav Meduna (@numo68)
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
DOCUMENTATION:
|
||||
name: json_diff
|
||||
short_description: Create a JSON patch by comparing two JSON files
|
||||
description:
|
||||
- This filter compares the input with the argument and computes a list of operations
|
||||
that can be consumed by the P(community.general.json_patch_recipe#filter) to change the input
|
||||
to the argument.
|
||||
requirements:
|
||||
- jsonpatch
|
||||
version_added: 10.3.0
|
||||
author:
|
||||
- Stanislav Meduna (@numo68)
|
||||
positional: target
|
||||
options:
|
||||
_input:
|
||||
description: A list or a dictionary representing a source JSON object, or a string containing a JSON object.
|
||||
type: raw
|
||||
required: true
|
||||
target:
|
||||
description: A list or a dictionary representing a target JSON object, or a string containing a JSON object.
|
||||
type: raw
|
||||
required: true
|
||||
seealso:
|
||||
- name: RFC 6902
|
||||
description: JavaScript Object Notation (JSON) Patch
|
||||
link: https://datatracker.ietf.org/doc/html/rfc6902
|
||||
- name: RFC 6901
|
||||
description: JavaScript Object Notation (JSON) Pointer
|
||||
link: https://datatracker.ietf.org/doc/html/rfc6901
|
||||
- name: jsonpatch Python Package
|
||||
description: A Python library for applying JSON patches
|
||||
link: https://pypi.org/project/jsonpatch/
|
||||
|
||||
RETURN:
|
||||
_value:
|
||||
description: A list of JSON patch operations to apply.
|
||||
type: list
|
||||
elements: dict
|
||||
|
||||
EXAMPLES: |
|
||||
- name: Compute a difference
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ input | community.general.json_diff(target) }}"
|
||||
vars:
|
||||
input: {"foo": 1, "bar":{"baz": 2}, "baw": [1, 2, 3], "hello": "day"}
|
||||
target: {"foo": 1, "bar": {"baz": 2}, "baw": [1, 3], "baq": {"baz": 2}, "hello": "night"}
|
||||
# => [
|
||||
# {"op": "add", "path": "/baq", "value": {"baz": 2}},
|
||||
# {"op": "remove", "path": "/baw/1"},
|
||||
# {"op": "replace", "path": "/hello", "value": "night"}
|
||||
# ]
|
195
plugins/filter/json_patch.py
Normal file
195
plugins/filter/json_patch.py
Normal file
|
@ -0,0 +1,195 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) Stanislav Meduna (@numo68)
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import annotations
|
||||
from json import loads
|
||||
from typing import TYPE_CHECKING
|
||||
from ansible.errors import AnsibleFilterError
|
||||
|
||||
__metaclass__ = type # pylint: disable=C0103
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Callable, Union
|
||||
|
||||
try:
|
||||
import jsonpatch
|
||||
|
||||
except ImportError as exc:
|
||||
HAS_LIB = False
|
||||
JSONPATCH_IMPORT_ERROR = exc
|
||||
else:
|
||||
HAS_LIB = True
|
||||
JSONPATCH_IMPORT_ERROR = None
|
||||
|
||||
OPERATIONS_AVAILABLE = ["add", "copy", "move", "remove", "replace", "test"]
|
||||
OPERATIONS_NEEDING_FROM = ["copy", "move"]
|
||||
OPERATIONS_NEEDING_VALUE = ["add", "replace", "test"]
|
||||
|
||||
|
||||
class FilterModule:
|
||||
"""Filter plugin."""
|
||||
|
||||
def check_json_object(self, filter_name: str, object_name: str, inp: Any):
|
||||
if isinstance(inp, (str, bytes, bytearray)):
|
||||
try:
|
||||
return loads(inp)
|
||||
except Exception as e:
|
||||
raise AnsibleFilterError(
|
||||
f"{filter_name}: could not decode JSON from {object_name}: {e}"
|
||||
) from e
|
||||
|
||||
if not isinstance(inp, (list, dict)):
|
||||
raise AnsibleFilterError(
|
||||
f"{filter_name}: {object_name} is not dictionary, list or string"
|
||||
)
|
||||
|
||||
return inp
|
||||
|
||||
def check_patch_arguments(self, filter_name: str, args: dict):
|
||||
|
||||
if "op" not in args or not isinstance(args["op"], str):
|
||||
raise AnsibleFilterError(f"{filter_name}: 'op' argument is not a string")
|
||||
|
||||
if args["op"] not in OPERATIONS_AVAILABLE:
|
||||
raise AnsibleFilterError(
|
||||
f"{filter_name}: unsupported 'op' argument: {args['op']}"
|
||||
)
|
||||
|
||||
if "path" not in args or not isinstance(args["path"], str):
|
||||
raise AnsibleFilterError(f"{filter_name}: 'path' argument is not a string")
|
||||
|
||||
if args["op"] in OPERATIONS_NEEDING_FROM:
|
||||
if "from" not in args:
|
||||
raise AnsibleFilterError(
|
||||
f"{filter_name}: 'from' argument missing for '{args['op']}' operation"
|
||||
)
|
||||
if not isinstance(args["from"], str):
|
||||
raise AnsibleFilterError(
|
||||
f"{filter_name}: 'from' argument is not a string"
|
||||
)
|
||||
|
||||
def json_patch(
|
||||
self,
|
||||
inp: Union[str, list, dict, bytes, bytearray],
|
||||
op: str,
|
||||
path: str,
|
||||
value: Any = None,
|
||||
**kwargs: dict,
|
||||
) -> Any:
|
||||
|
||||
if not HAS_LIB:
|
||||
raise AnsibleFilterError(
|
||||
"You need to install 'jsonpatch' package prior to running 'json_patch' filter"
|
||||
) from JSONPATCH_IMPORT_ERROR
|
||||
|
||||
args = {"op": op, "path": path}
|
||||
from_arg = kwargs.pop("from", None)
|
||||
fail_test = kwargs.pop("fail_test", False)
|
||||
|
||||
if kwargs:
|
||||
raise AnsibleFilterError(
|
||||
f"json_patch: unexpected keywords arguments: {', '.join(sorted(kwargs))}"
|
||||
)
|
||||
|
||||
if not isinstance(fail_test, bool):
|
||||
raise AnsibleFilterError("json_patch: 'fail_test' argument is not a bool")
|
||||
|
||||
if op in OPERATIONS_NEEDING_VALUE:
|
||||
args["value"] = value
|
||||
if op in OPERATIONS_NEEDING_FROM and from_arg is not None:
|
||||
args["from"] = from_arg
|
||||
|
||||
inp = self.check_json_object("json_patch", "input", inp)
|
||||
self.check_patch_arguments("json_patch", args)
|
||||
|
||||
result = None
|
||||
|
||||
try:
|
||||
result = jsonpatch.apply_patch(inp, [args])
|
||||
except jsonpatch.JsonPatchTestFailed as e:
|
||||
if fail_test:
|
||||
raise AnsibleFilterError(
|
||||
f"json_patch: test operation failed: {e}"
|
||||
) from e
|
||||
else:
|
||||
pass
|
||||
except Exception as e:
|
||||
raise AnsibleFilterError(f"json_patch: patch failed: {e}") from e
|
||||
|
||||
return result
|
||||
|
||||
def json_patch_recipe(
|
||||
self,
|
||||
inp: Union[str, list, dict, bytes, bytearray],
|
||||
operations: list,
|
||||
/,
|
||||
fail_test: bool = False,
|
||||
) -> Any:
|
||||
|
||||
if not HAS_LIB:
|
||||
raise AnsibleFilterError(
|
||||
"You need to install 'jsonpatch' package prior to running 'json_patch_recipe' filter"
|
||||
) from JSONPATCH_IMPORT_ERROR
|
||||
|
||||
if not isinstance(operations, list):
|
||||
raise AnsibleFilterError(
|
||||
"json_patch_recipe: 'operations' needs to be a list"
|
||||
)
|
||||
|
||||
if not isinstance(fail_test, bool):
|
||||
raise AnsibleFilterError("json_patch: 'fail_test' argument is not a bool")
|
||||
|
||||
result = None
|
||||
|
||||
inp = self.check_json_object("json_patch_recipe", "input", inp)
|
||||
for args in operations:
|
||||
self.check_patch_arguments("json_patch_recipe", args)
|
||||
|
||||
try:
|
||||
result = jsonpatch.apply_patch(inp, operations)
|
||||
except jsonpatch.JsonPatchTestFailed as e:
|
||||
if fail_test:
|
||||
raise AnsibleFilterError(
|
||||
f"json_patch_recipe: test operation failed: {e}"
|
||||
) from e
|
||||
else:
|
||||
pass
|
||||
except Exception as e:
|
||||
raise AnsibleFilterError(f"json_patch_recipe: patch failed: {e}") from e
|
||||
|
||||
return result
|
||||
|
||||
def json_diff(
|
||||
self,
|
||||
inp: Union[str, list, dict, bytes, bytearray],
|
||||
target: Union[str, list, dict, bytes, bytearray],
|
||||
) -> list:
|
||||
|
||||
if not HAS_LIB:
|
||||
raise AnsibleFilterError(
|
||||
"You need to install 'jsonpatch' package prior to running 'json_diff' filter"
|
||||
) from JSONPATCH_IMPORT_ERROR
|
||||
|
||||
inp = self.check_json_object("json_diff", "input", inp)
|
||||
target = self.check_json_object("json_diff", "target", target)
|
||||
|
||||
try:
|
||||
result = list(jsonpatch.make_patch(inp, target))
|
||||
except Exception as e:
|
||||
raise AnsibleFilterError(f"JSON diff failed: {e}") from e
|
||||
|
||||
return result
|
||||
|
||||
def filters(self) -> dict[str, Callable[..., Any]]:
|
||||
"""Map filter plugin names to their functions.
|
||||
|
||||
Returns:
|
||||
dict: The filter plugin functions.
|
||||
"""
|
||||
return {
|
||||
"json_patch": self.json_patch,
|
||||
"json_patch_recipe": self.json_patch_recipe,
|
||||
"json_diff": self.json_diff,
|
||||
}
|
145
plugins/filter/json_patch.yml
Normal file
145
plugins/filter/json_patch.yml
Normal file
|
@ -0,0 +1,145 @@
|
|||
---
|
||||
# Copyright (c) Stanislav Meduna (@numo68)
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
DOCUMENTATION:
|
||||
name: json_patch
|
||||
short_description: Apply a JSON-Patch (RFC 6902) operation to an object
|
||||
description:
|
||||
- This filter applies a single JSON patch operation and returns a modified object.
|
||||
- If the operation is a test, the filter returns an ummodified object if the test
|
||||
succeeded and a V(none) value otherwise.
|
||||
requirements:
|
||||
- jsonpatch
|
||||
version_added: 10.3.0
|
||||
author:
|
||||
- Stanislav Meduna (@numo68)
|
||||
positional: op, path, value
|
||||
options:
|
||||
_input:
|
||||
description: A list or a dictionary representing a JSON object, or a string containing a JSON object.
|
||||
type: raw
|
||||
required: true
|
||||
op:
|
||||
description: Operation to perform (see L(RFC 6902, https://datatracker.ietf.org/doc/html/rfc6902)).
|
||||
type: str
|
||||
choices: [add, copy, move, remove, replace, test]
|
||||
required: true
|
||||
path:
|
||||
description: JSON Pointer path to the target location (see L(RFC 6901, https://datatracker.ietf.org/doc/html/rfc6901)).
|
||||
type: str
|
||||
required: true
|
||||
value:
|
||||
description: Value to use in the operation. Ignored for O(op=copy), O(op=move), and O(op=remove).
|
||||
type: raw
|
||||
from:
|
||||
description: The source location for the copy and move operation. Mandatory
|
||||
for O(op=copy) and O(op=move), ignored otherwise.
|
||||
type: str
|
||||
fail_test:
|
||||
description: If V(false), a failed O(op=test) will return V(none). If V(true), the filter
|
||||
invocation will fail with an error.
|
||||
type: bool
|
||||
default: false
|
||||
seealso:
|
||||
- name: RFC 6902
|
||||
description: JavaScript Object Notation (JSON) Patch
|
||||
link: https://datatracker.ietf.org/doc/html/rfc6902
|
||||
- name: RFC 6901
|
||||
description: JavaScript Object Notation (JSON) Pointer
|
||||
link: https://datatracker.ietf.org/doc/html/rfc6901
|
||||
- name: jsonpatch Python Package
|
||||
description: A Python library for applying JSON patches
|
||||
link: https://pypi.org/project/jsonpatch/
|
||||
|
||||
RETURN:
|
||||
_value:
|
||||
description: A modified object or V(none) if O(op=test), O(fail_test=false) and the test failed.
|
||||
type: any
|
||||
returned: always
|
||||
|
||||
EXAMPLES: |
|
||||
- name: Insert a new element into an array at a specified index
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ input | community.general.json_patch('add', '/1', {'baz': 'qux'}) }}"
|
||||
vars:
|
||||
input: ["foo": { "one": 1 }, "bar": { "two": 2 }]
|
||||
# => [{"foo": {"one": 1}}, {"baz": "qux"}, {"bar": {"two": 2}}]
|
||||
|
||||
- name: Insert a new key into a dictionary
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ input | community.general.json_patch('add', '/bar/baz', 'qux') }}"
|
||||
vars:
|
||||
input: { "foo": { "one": 1 }, "bar": { "two": 2 } }
|
||||
# => {"foo": {"one": 1}, "bar": {"baz": "qux", "two": 2}}
|
||||
|
||||
- name: Input is a string
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ input | community.general.json_patch('add', '/baz', 3) }}"
|
||||
vars:
|
||||
input: '{ "foo": { "one": 1 }, "bar": { "two": 2 } }'
|
||||
# => {"foo": {"one": 1}, "bar": { "two": 2 }, "baz": 3}
|
||||
|
||||
- name: Existing key is replaced
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ input | community.general.json_patch('add', '/bar', 'qux') }}"
|
||||
vars:
|
||||
input: { "foo": { "one": 1 }, "bar": { "two": 2 } }
|
||||
# => {"foo": {"one": 1}, "bar": "qux"}
|
||||
|
||||
- name: Escaping tilde as ~0 and slash as ~1 in the path
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ input | community.general.json_patch('add', '/~0~1', 'qux') }}"
|
||||
vars:
|
||||
input: {}
|
||||
# => {"~/": "qux"}
|
||||
|
||||
- name: Add at the end of the array
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ input | community.general.json_patch('add', '/-', 4) }}"
|
||||
vars:
|
||||
input: [1, 2, 3]
|
||||
# => [1, 2, 3, 4]
|
||||
|
||||
- name: Remove a key
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ input | community.general.json_patch('remove', '/bar') }}"
|
||||
vars:
|
||||
input: { "foo": { "one": 1 }, "bar": { "two": 2 } }
|
||||
# => {"foo": {"one": 1} }
|
||||
|
||||
- name: Replace a value
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ input | community.general.json_patch('replace', '/bar', 2) }}"
|
||||
vars:
|
||||
input: { "foo": { "one": 1 }, "bar": { "two": 2 } }
|
||||
# => {"foo": {"one": 1}, "bar": 2}
|
||||
|
||||
- name: Copy a value
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ input | community.general.json_patch('copy', '/baz', from='/bar') }}"
|
||||
vars:
|
||||
input: { "foo": { "one": 1 }, "bar": { "two": 2 } }
|
||||
# => {"foo": {"one": 1}, "bar": { "two": 2 }, "baz": { "two": 2 }}
|
||||
|
||||
- name: Move a value
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ input | community.general.json_patch('move', '/baz', from='/bar') }}"
|
||||
vars:
|
||||
input: { "foo": { "one": 1 }, "bar": { "two": 2 } }
|
||||
# => {"foo": {"one": 1}, "baz": { "two": 2 }}
|
||||
|
||||
- name: Successful test
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ input | community.general.json_patch('test', '/bar/two', 2) | ternary('OK', 'Failed') }}"
|
||||
vars:
|
||||
input: { "foo": { "one": 1 }, "bar": { "two": 2 } }
|
||||
# => OK
|
||||
|
||||
- name: Unuccessful test
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ input | community.general.json_patch('test', '/bar/two', 9) | ternary('OK', 'Failed') }}"
|
||||
vars:
|
||||
input: { "foo": { "one": 1 }, "bar": { "two": 2 } }
|
||||
# => Failed
|
102
plugins/filter/json_patch_recipe.yml
Normal file
102
plugins/filter/json_patch_recipe.yml
Normal file
|
@ -0,0 +1,102 @@
|
|||
---
|
||||
# Copyright (c) Stanislav Meduna (@numo68)
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
DOCUMENTATION:
|
||||
name: json_patch_recipe
|
||||
short_description: Apply JSON-Patch (RFC 6902) operations to an object
|
||||
description:
|
||||
- This filter sequentially applies JSON patch operations and returns a modified object.
|
||||
- If there is a test operation in the list, the filter continues if the test
|
||||
succeeded and returns a V(none) value otherwise.
|
||||
requirements:
|
||||
- jsonpatch
|
||||
version_added: 10.3.0
|
||||
author:
|
||||
- Stanislav Meduna (@numo68)
|
||||
positional: operations, fail_test
|
||||
options:
|
||||
_input:
|
||||
description: A list or a dictionary representing a JSON object, or a string containing a JSON object.
|
||||
type: raw
|
||||
required: true
|
||||
operations:
|
||||
description: A list of JSON patch operations to apply.
|
||||
type: list
|
||||
elements: dict
|
||||
required: true
|
||||
suboptions:
|
||||
op:
|
||||
description: Operation to perform (see L(RFC 6902, https://datatracker.ietf.org/doc/html/rfc6902)).
|
||||
type: str
|
||||
choices: [add, copy, move, remove, replace, test]
|
||||
required: true
|
||||
path:
|
||||
description: JSON Pointer path to the target location (see L(RFC 6901, https://datatracker.ietf.org/doc/html/rfc6901)).
|
||||
type: str
|
||||
required: true
|
||||
value:
|
||||
description: Value to use in the operation. Ignored for O(operations[].op=copy), O(operations[].op=move), and O(operations[].op=remove).
|
||||
type: raw
|
||||
from:
|
||||
description: The source location for the copy and move operation. Mandatory
|
||||
for O(operations[].op=copy) and O(operations[].op=move), ignored otherwise.
|
||||
type: str
|
||||
fail_test:
|
||||
description: If V(false), a failed O(operations[].op=test) will return V(none). If V(true), the filter
|
||||
invocation will fail with an error.
|
||||
type: bool
|
||||
default: false
|
||||
seealso:
|
||||
- name: RFC 6902
|
||||
description: JavaScript Object Notation (JSON) Patch
|
||||
link: https://datatracker.ietf.org/doc/html/rfc6902
|
||||
- name: RFC 6901
|
||||
description: JavaScript Object Notation (JSON) Pointer
|
||||
link: https://datatracker.ietf.org/doc/html/rfc6901
|
||||
- name: jsonpatch Python Package
|
||||
description: A Python library for applying JSON patches
|
||||
link: https://pypi.org/project/jsonpatch/
|
||||
|
||||
RETURN:
|
||||
_value:
|
||||
description: A modified object or V(none) if O(operations[].op=test), O(fail_test=false)
|
||||
and the test failed.
|
||||
type: any
|
||||
returned: always
|
||||
|
||||
EXAMPLES: |
|
||||
- name: Apply a series of operations
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ input | community.general.json_patch_recipe(operations) }}"
|
||||
vars:
|
||||
input: {}
|
||||
operations:
|
||||
- op: 'add'
|
||||
path: '/foo'
|
||||
value: 1
|
||||
- op: 'add'
|
||||
path: '/bar'
|
||||
value: []
|
||||
- op: 'add'
|
||||
path: '/bar/-'
|
||||
value: 2
|
||||
- op: 'add'
|
||||
path: '/bar/0'
|
||||
value: 1
|
||||
- op: 'remove'
|
||||
path: '/bar/0'
|
||||
- op: 'move'
|
||||
from: '/foo'
|
||||
path: '/baz'
|
||||
- op: 'copy'
|
||||
from: '/baz'
|
||||
path: '/bax'
|
||||
- op: 'copy'
|
||||
from: '/baz'
|
||||
path: '/bay'
|
||||
- op: 'replace'
|
||||
path: '/baz'
|
||||
value: [10, 20, 30]
|
||||
# => {"bar":[2],"bax":1,"bay":1,"baz":[10,20,30]}
|
|
@ -3,8 +3,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: json_query
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
name: keep_keys
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue