Compare commits

...

30 Commits
6.6.4 ... 6.6.6

Author SHA1 Message Date
Felix Fontein
7f7e622262 Release 6.6.6. 2023-10-08 13:31:17 +02:00
Felix Fontein
e1551b3d34 Prepare 6.6.6 release. 2023-10-08 12:59:23 +02:00
patchback[bot]
a3bc0535a5 [PR #7334/92d7bd68 backport][stable-6] Fix Galaxy URLs (#7336)
Fix Galaxy URLs (#7334)

Fix Galaxy URLs.

(cherry picked from commit 92d7bd68e9)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-09-30 21:30:16 +02:00
patchback[bot]
9e59665bee [PR #7301/7bf24eeb backport][stable-6] Fixing incorrect string encapsulation for -backend-config. (#7314)
Fixing incorrect string encapsulation for -backend-config. (#7301)

* Fixing incorrect string encapsulation for -backend-config. Removing shlex_quote.

* Adding change log fragemnt for bugfix:

- "terraform module - prevents `-backend-config` option double encapsulating with `shlex_quote` function. (https://github.com/ansible-collections/community.general/pull/7301)."

* Update changelogs/fragments/7301-fix-backend-config-string-encapsulation.yml

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

---------

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

Co-authored-by: Kosala Atapattu <kosala@kosala.net>
2023-09-25 05:51:19 +02:00
patchback[bot]
30b29d24ab [PR #7309/522fb23e backport][stable-6] xinetd no longer exists; use mdadm instead (#7312)
xinetd no longer exists; use mdadm instead (#7309)

xinetd no longer exists; use mdadm instead.

(cherry picked from commit 522fb23e06)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-09-25 05:51:04 +02:00
patchback[bot]
d5efc3f13a [PR #7303/f4237dde backport][stable-6] Fix incorrect parsing of headers containing equal character (#7305)
Fix incorrect parsing of headers containing equal character (#7303)

* Fix incorrect parsing of header containing equal character

* Add changelog fragment

* Update changelogs/fragments/7303-mail-incorrect-header-parsing.yml

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

---------

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

Co-authored-by: Théo Lévesque <Theo024@users.noreply.github.com>
2023-09-22 13:17:29 +02:00
patchback[bot]
d237faa447 [PR #7296/756e8f5c backport][stable-6] Update from_csv.py docs (#7299)
Update from_csv.py docs (#7296)

Typo fix

(cherry picked from commit 756e8f5cca)

Co-authored-by: bontreger <bontreger@users.noreply.github.com>
2023-09-20 22:44:17 +02:00
Felix Fontein
65ce979d4a [stable-6] CI: devel → stable-2.16, move stable-2.13 to EOL CI (#7287)
CI: devel → stable-2.16, move stable-2.13 to EOL CI.
2023-09-19 17:51:41 +02:00
patchback[bot]
938367b67a [PR #7249/4030481b backport][stable-6] ipa_user documentation: givenname and sn are required when user doesn't exist (#7280)
* ipa_user documentation: givenname and sn are required when user doesn't exist (#7249)

* Edit  givenname and sn description.

* Update plugins/modules/ipa_user.py

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

* Update plugins/modules/ipa_user.py

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

---------

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

* Remove semantic markup.

---------

Co-authored-by: Christer Warén <cwchristerw@gmail.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2023-09-17 14:36:10 +02:00
patchback[bot]
578df1b054 [PR #7241/1beb38ce backport][stable-6] Use get(..) instead of [..] for safe lookup of value (Fixes #7240) (#7257)
Use `get(..)` instead of [..] for safe lookup of value (Fixes #7240) (#7241)

A OnePassword field item might not have a value (property) when the user has omitted it (on purpose).

(cherry picked from commit 1beb38ceff)

Co-authored-by: Wouter Klein Heerenbrink <wouter@fluxility.com>
2023-09-13 06:24:24 +00:00
patchback[bot]
0b494a5d2d [PR #7252/7d97b37b backport][stable-6] Update my maintainer status for 1PW plugin (#7253)
Update my maintainer status for 1PW plugin (#7252)

* ignore notifications for scottsb on 1pw plugin; update email

* Also update maintainers list.

---------

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

Co-authored-by: Scott Buchanan <scottiesb@gmail.com>
2023-09-13 07:20:10 +02:00
Felix Fontein
f92043c7f5 Next release will be 6.6.6. 2023-09-11 19:50:55 +02:00
Felix Fontein
839336c21d Release 6.6.5. 2023-09-11 19:05:43 +02:00
patchback[bot]
2a5e4b8a46 [PR #7219/208df2c9 backport][stable-6] nsupdate: fix 'index out of range' error when no TTL answer is given (#7235)
nsupdate: fix 'index out of range' error when no TTL answer is given (#7219)

* nsupdate: fix 'index out of range' error when no TTL answer is given

Fix a possible `list index out of range` when no answer is returned in the `ttl_changed` method
by applying the existing workaround for NS records to all record types.

Resolves #836

* fixup! nsupdate: fix 'index out of range' error when no TTL answer is given

(cherry picked from commit 208df2c9e6)

Co-authored-by: Silke Hofstra <silkeh@users.noreply.github.com>
2023-09-11 06:01:01 +02:00
Felix Fontein
fae1dbc198 Prepare 6.6.5 release. 2023-09-10 21:31:33 +02:00
patchback[bot]
dc7aba3bca [PR #7200/8fa667ee backport][stable-6] CmdRunner bugfix (#7227)
CmdRunner bugfix (#7200)

* cmd_runner module utils: fix bug when passing absolute path not in standard search paths

* improved tests

* changed /usr/bin/echo to /bin/echo for the sake of alpine

* fixed error messaging for last testcase

* add condition to test cases, and remove macos from troubling ones

* fix templating

* fix templating

* exclude centos 6 from testcases copying echo to tmp dir

* try different way of specifying version

* trying trick for old jinjas

* use os.path.isabs() to determine if path is absolute

* add changelog frag

* Update plugins/module_utils/cmd_runner.py

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

* Update changelogs/fragments/7200-cmd-runner-abs-path.yml

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

---------

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

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2023-09-10 09:00:20 +02:00
patchback[bot]
03c66d0db4 [PR #7205/58d89ce4 backport][stable-6] smbios option description (#7223)
* smbios option description (#7205)

* smbios option description

More detailed description smbios option

* Update plugins/modules/proxmox_kvm.py

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

* Change map to string

* Update proxmox_kvm.py

---------

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

* Avoid semantic markup.

---------

Co-authored-by: Андрей Неустроев <99169437+aneustroev@users.noreply.github.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2023-09-08 17:38:34 +02:00
patchback[bot]
5707fc1b33 [PR #7180/9021e741 backport][stable-6] community.general.make: (#7217)
* community.general.make: (#7180)

* community.general.make:

  allows parameters without value

  closes #7178

* add changelog fragment for community.general.make

* correction: v != none -> v is not None

* update fragment changelog as per developer request

* add an example

* document the modification

* update example with comments as per maintainer request

(cherry picked from commit 9021e7416d)

* Avoid semantic markup for stable-6.

---------

Co-authored-by: snail59 <25689269+snail59@users.noreply.github.com>
Co-authored-by: Felix Fontein <felix@fontein.de>
2023-09-07 06:29:27 +02:00
patchback[bot]
830e3988aa [PR #7161/a23cd6c1 backport][stable-6] Update incorrect path for pritunl organization post (#7213)
Update incorrect path for pritunl organization post (#7161)

* Update incorrect path for organization post

* Create changelog fragment

* Update changelog fragment.

---------

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

Co-authored-by: dsmackie <48046804+dsmackie@users.noreply.github.com>
2023-09-06 22:06:20 +02:00
patchback[bot]
f4ccef462e [PR #7156/0862511e backport][stable-6] Ensure pritunl validate_certs is honoured in all methods (#7215)
Ensure pritunl validate_certs is honoured in all methods (#7156)

* Ensure pritunl validate_certs is honoured in all methods

* Create changelog fragment

* Rename 7156-ensure-validate-certs-parameter-is-honoured to 7156-ensure-validate-certs-parameter-is-honoured.yml

* Update changelog fragment.

---------

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

Co-authored-by: dsmackie <48046804+dsmackie@users.noreply.github.com>
2023-09-06 22:06:02 +02:00
patchback[bot]
cd26dd6b0a [PR #7209/9f1a9e30 backport][stable-6] plugins/modules/apache2_module: fix typo (#7210)
plugins/modules/apache2_module: fix typo (#7209)

(cherry picked from commit 9f1a9e306c)

Co-authored-by: Célestin Matte <celestin.matte@gmail.com>
2023-09-06 19:09:59 +02:00
patchback[bot]
009bfd786d [PR #7181/d6ebba1a backport][stable-6] cmd tests improvement (#7186)
cmd tests improvement (#7181)

* cmd tests improvement

* fix sanity

* remove commented line

* fixed class init code

(cherry picked from commit d6ebba1aea)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2023-09-01 11:28:01 +00:00
patchback[bot]
9f08cc11a8 [PR #7170/63030966 backport][stable-6] xfconf*: using yaml-specified unit tests (#7176)
xfconf*: using yaml-specified unit tests (#7170)

(cherry picked from commit 6303096648)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2023-08-30 06:16:20 +02:00
patchback[bot]
cae4bc80af [PR #7172/f3a02b3e backport][stable-6] CI: make sure EXTERNALLY-MANAGED is absent on Arch Linux (#7174)
CI: make sure EXTERNALLY-MANAGED is absent on Arch Linux (#7172)

Make sure EXTERNALLY-MANAGED is absent on Arch.

(cherry picked from commit f3a02b3efb)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-08-30 06:15:57 +02:00
patchback[bot]
058462973e [PR #7154/8652fd95 backport][stable-6] Refactored unit tests for modules based on CmdRunner (#7167)
Refactored unit tests for modules based on CmdRunner (#7154)

* refactored unit tests for modules based on CmdRunner

* improved/fixed test helper

* fixed sanity

* refactored yaml spec out of the python file

* small adjustments

(cherry picked from commit 8652fd9528)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2023-08-29 13:22:08 +02:00
patchback[bot]
23dc90812f [PR #7162/4c8c25bc backport][stable-6] keycloak_clientscope_type: fixed example (#7164)
keycloak_clientscope_type: fixed example (#7162)

(cherry picked from commit 4c8c25bc93)

Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com>
2023-08-29 07:47:32 +02:00
patchback[bot]
97e17fcee2 [PR #7125/77214203 backport][stable-6] Fix inappropriate comparison on the length of a Collection (#7146)
Fix inappropriate comparison on the length of a Collection (#7125)

* Comment: Fixed inappropriate comparison on the length of a Collection. Added changlelog fragment file.

* Comment: Updated the scope of the changelog fragment based on feedback.

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

---------

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

Co-authored-by: Munawar <munawar.hafiz@gmail.com>
2023-08-23 06:13:58 +02:00
patchback[bot]
d75d5f67f7 [PR #7104/eafdf87b backport][stable-6] lxc: fix remote_addr default to inventory_hostname (#7108)
lxc: fix remote_addr default to inventory_hostname (#7104)

* lxc: fix remote_addr default to inventory_hostname

* Update changelogs/fragments/7104_fix_lxc_remoteaddr_default.yml

---------

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

Co-authored-by: Corubba <97832352+corubba@users.noreply.github.com>
2023-08-13 22:15:22 +02:00
patchback[bot]
c597a75372 [PR #7103/5e27bbfd backport][stable-6] CI: FreeBSD 13.0 and 12.3 are no longer availabe, bump versions and disable since these versions are already tested with stable-2.15 (#7106)
CI: FreeBSD 13.0 and 12.3 are no longer availabe, bump versions and disable since these versions are already tested with stable-2.15 (#7103)

FreeBSD 13.0 and 12.3 are no longer availabe, bump versions and disable since these versions are already tested with stable-2.15.

(cherry picked from commit 5e27bbfdf6)

Co-authored-by: Felix Fontein <felix@fontein.de>
2023-08-13 20:12:44 +02:00
Felix Fontein
031a3b56bf Next release will be 6.6.5. 2023-08-13 11:34:09 +02:00
38 changed files with 1058 additions and 804 deletions

View File

@@ -59,14 +59,14 @@ pool: Standard
stages:
### Sanity
- stage: Sanity_devel
displayName: Sanity devel
- stage: Sanity_2_16
displayName: Sanity 2.16
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Test {0}
testFormat: devel/sanity/{0}
testFormat: 2.16/sanity/{0}
targets:
- test: 1
- test: 2
@@ -99,28 +99,15 @@ stages:
- test: 2
- test: 3
- test: 4
- stage: Sanity_2_13
displayName: Sanity 2.13
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Test {0}
testFormat: 2.13/sanity/{0}
targets:
- test: 1
- test: 2
- test: 3
- test: 4
### Units
- stage: Units_devel
displayName: Units devel
- stage: Units_2_16
displayName: Units 2.16
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: devel/units/{0}/1
testFormat: 2.16/units/{0}/1
targets:
- test: 2.7
- test: 3.6
@@ -150,26 +137,15 @@ stages:
testFormat: 2.14/units/{0}/1
targets:
- test: 3.9
- stage: Units_2_13
displayName: Units 2.13
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: 2.13/units/{0}/1
targets:
- test: 2.7
- test: 3.8
## Remote
- stage: Remote_devel_extra_vms
displayName: Remote devel extra VMs
- stage: Remote_2_16_extra_vms
displayName: Remote 2.16 extra VMs
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: devel/{0}
testFormat: 2.16/{0}
targets:
- name: Alpine 3.18
test: alpine/3.18
@@ -179,13 +155,13 @@ stages:
test: ubuntu/22.04
groups:
- vm
- stage: Remote_devel
displayName: Remote devel
- stage: Remote_2_16
displayName: Remote 2.16
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: devel/{0}
testFormat: 2.16/{0}
targets:
- name: macOS 13.2
test: macos/13.2
@@ -231,39 +207,21 @@ stages:
targets:
- name: RHEL 9.0
test: rhel/9.0
- name: FreeBSD 12.3
test: freebsd/12.3
groups:
- 1
- 2
- 3
- stage: Remote_2_13
displayName: Remote 2.13
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.13/{0}
targets:
- name: macOS 12.0
test: macos/12.0
- name: RHEL 8.5
test: rhel/8.5
- name: FreeBSD 13.0
test: freebsd/13.0
#- name: FreeBSD 12.4
# test: freebsd/12.4
groups:
- 1
- 2
- 3
### Docker
- stage: Docker_devel
displayName: Docker devel
- stage: Docker_2_16
displayName: Docker 2.16
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: devel/linux/{0}
testFormat: 2.16/linux/{0}
targets:
- name: Fedora 38
test: fedora38
@@ -309,33 +267,15 @@ stages:
- 1
- 2
- 3
- stage: Docker_2_13
displayName: Docker 2.13
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.13/linux/{0}
targets:
- name: Fedora 35
test: fedora35
- name: openSUSE 15 py2
test: opensuse15py2
- name: Alpine 3
test: alpine3
groups:
- 1
- 2
- 3
### Community Docker
- stage: Docker_community_devel
displayName: Docker (community images) devel
- stage: Docker_community_2_16
displayName: Docker (community images) 2.16
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: devel/linux-community/{0}
testFormat: 2.16/linux-community/{0}
targets:
- name: Debian Bullseye
test: debian-bullseye/3.9
@@ -349,14 +289,14 @@ stages:
- 3
### Generic
- stage: Generic_devel
displayName: Generic devel
- stage: Generic_2_16
displayName: Generic 2.16
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: devel/generic/{0}/1
testFormat: 2.16/generic/{0}/1
targets:
- test: 2.7
- test: '3.11'
@@ -380,42 +320,27 @@ stages:
testFormat: 2.14/generic/{0}/1
targets:
- test: '3.10'
- stage: Generic_2_13
displayName: Generic 2.13
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: 2.13/generic/{0}/1
targets:
- test: 3.9
- stage: Summary
condition: succeededOrFailed()
dependsOn:
- Sanity_devel
- Sanity_2_13
- Sanity_2_14
- Sanity_2_15
- Units_devel
- Units_2_13
- Sanity_2_16
- Units_2_14
- Units_2_15
- Remote_devel_extra_vms
- Remote_devel
- Remote_2_13
- Units_2_16
- Remote_2_14
- Remote_2_15
- Docker_devel
- Docker_2_13
- Remote_2_16
- Remote_2_16_extra_vms
- Docker_2_14
- Docker_2_15
- Docker_community_devel
- Docker_2_16
- Docker_community_2_16
# Right now all generic tests are disabled. Uncomment when at least one of them is re-enabled.
# - Generic_devel
# - Generic_2_13
# - Generic_2_14
# - Generic_2_15
# - Generic_2_16
jobs:
- template: templates/coverage.yml

6
.github/BOTMETA.yml vendored
View File

@@ -247,9 +247,11 @@ files:
labels: onepassword
maintainers: samdoran
$lookups/onepassword.py:
maintainers: azenk scottsb
ignore: scottsb
maintainers: azenk
$lookups/onepassword_raw.py:
maintainers: azenk scottsb
ignore: scottsb
maintainers: azenk
$lookups/passwordstore.py: {}
$lookups/random_pet.py:
maintainers: Akasurde

View File

@@ -31,6 +31,7 @@ jobs:
ansible:
- '2.11'
- '2.12'
- '2.13'
# Ansible-test on various stable branches does not yet work well with cgroups v2.
# Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04
# image for these stable branches. The list of branches where this is necessary will
@@ -80,6 +81,10 @@ jobs:
python: '2.6'
- ansible: '2.12'
python: '3.8'
- ansible: '2.13'
python: '2.7'
- ansible: '2.13'
python: '3.8'
steps:
- name: >-
@@ -211,6 +216,48 @@ jobs:
# docker: default
# python: '3.8'
# target: azp/generic/1/
# 2.13
- ansible: '2.13'
docker: fedora35
python: ''
target: azp/posix/1/
- ansible: '2.13'
docker: fedora35
python: ''
target: azp/posix/2/
- ansible: '2.13'
docker: fedora35
python: ''
target: azp/posix/3/
- ansible: '2.13'
docker: opensuse15py2
python: ''
target: azp/posix/1/
- ansible: '2.13'
docker: opensuse15py2
python: ''
target: azp/posix/2/
- ansible: '2.13'
docker: opensuse15py2
python: ''
target: azp/posix/3/
- ansible: '2.13'
docker: alpine3
python: ''
target: azp/posix/1/
- ansible: '2.13'
docker: alpine3
python: ''
target: azp/posix/2/
- ansible: '2.13'
docker: alpine3
python: ''
target: azp/posix/3/
# Right now all generic tests are disabled. Uncomment when at least one of them is re-enabled.
# - ansible: '2.13'
# docker: default
# python: '3.9'
# target: azp/generic/1/
steps:
- name: >-

View File

@@ -6,6 +6,44 @@ Community General Release Notes
This changelog describes changes after version 5.0.0.
v6.6.6
======
Release Summary
---------------
Regular bugfix release.
Bugfixes
--------
- mail - skip headers containing equals characters due to missing ``maxsplit`` on header key/value parsing (https://github.com/ansible-collections/community.general/pull/7303).
- onepassword - fix KeyError exception when trying to access value of a field that is not filled out in OnePassword item (https://github.com/ansible-collections/community.general/pull/7241).
- terraform - prevents ``-backend-config`` option double encapsulating with ``shlex_quote`` function. (https://github.com/ansible-collections/community.general/pull/7301).
v6.6.5
======
Release Summary
---------------
Regular bugfix release.
Minor Changes
-------------
- make - allows ``params`` to be used without value (https://github.com/ansible-collections/community.general/pull/7180).
- pritunl module utils - ensure ``validate_certs`` parameter is honoured in all methods (https://github.com/ansible-collections/community.general/pull/7156).
Bugfixes
--------
- CmdRunner module utils - does not attempt to resolve path if executable is a relative or absolute path (https://github.com/ansible-collections/community.general/pull/7200).
- lxc connection plugin - now handles ``remote_addr`` defaulting to ``inventory_hostname`` correctly (https://github.com/ansible-collections/community.general/pull/7104).
- nsupdate - fix a possible ``list index out of range`` exception (https://github.com/ansible-collections/community.general/issues/836).
- oci_utils module util - fix inappropriate logical comparison expressions and makes them simpler. The previous checks had logical short circuits (https://github.com/ansible-collections/community.general/pull/7125).
- pritunl module utils - fix incorrect URL parameter for orgnization add method (https://github.com/ansible-collections/community.general/pull/7161).
v6.6.4
======

View File

@@ -24,7 +24,7 @@ If you encounter abusive behavior violating the [Ansible Code of Conduct](https:
## Tested with Ansible
Tested with the current ansible-core 2.11, ansible-core 2.12, ansible-core 2.13, ansible-core 2.14, ansible-core 2.15 releases and the current development version of ansible-core. Ansible-core versions before 2.11.0 are not supported. This includes all ansible-base 2.10 and Ansible 2.9 releases.
Tested with the current ansible-core 2.11, ansible-core 2.12, ansible-core 2.13, ansible-core 2.14, ansible-core 2.15, and ansible-core 2.16 releases. Ansible-core versions before 2.11.0 are not supported. This includes all ansible-base 2.10 and Ansible 2.9 releases.
Parts of this collection will not work with ansible-core 2.11 on Python 3.12+.
@@ -34,13 +34,13 @@ Some modules and plugins require external libraries. Please check the requiremen
## Included content
Please check the included content on the [Ansible Galaxy page for this collection](https://galaxy.ansible.com/community/general) or the [documentation on the Ansible docs site](https://docs.ansible.com/ansible/latest/collections/community/general/).
Please check the included content on the [Ansible Galaxy page for this collection](https://galaxy.ansible.com/ui/repo/published/community/general/) or the [documentation on the Ansible docs site](https://docs.ansible.com/ansible/latest/collections/community/general/).
## Using this collection
This collection is shipped with the Ansible package. So if you have it installed, no more action is required.
If you have a minimal installation (only Ansible Core installed) or you want to use the latest version of the collection along with the whole Ansible package, you need to install the collection from [Ansible Galaxy](https://galaxy.ansible.com/community/general) manually with the `ansible-galaxy` command-line tool:
If you have a minimal installation (only Ansible Core installed) or you want to use the latest version of the collection along with the whole Ansible package, you need to install the collection from [Ansible Galaxy](https://galaxy.ansible.com/ui/repo/published/community/general/) manually with the `ansible-galaxy` command-line tool:
ansible-galaxy collection install community.general
@@ -57,7 +57,7 @@ Note that if you install the collection manually, it will not be upgraded automa
ansible-galaxy collection install community.general --upgrade
```
You can also install a specific version of the collection, for example, if you need to downgrade when something is broken in the latest version (please report an issue in this repository). Use the following syntax where `X.Y.Z` can be any [available version](https://galaxy.ansible.com/community/general):
You can also install a specific version of the collection, for example, if you need to downgrade when something is broken in the latest version (please report an issue in this repository). Use the following syntax where `X.Y.Z` can be any [available version](https://galaxy.ansible.com/ui/repo/published/community/general/):
```bash
ansible-galaxy collection install community.general:==X.Y.Z

View File

@@ -1530,3 +1530,46 @@ releases:
- 7081-redfish-utils-fix-for-storagecontrollers-deprecated-key.yaml
- 7085-sanity.yml
release_date: '2023-08-13'
6.6.5:
changes:
bugfixes:
- CmdRunner module utils - does not attempt to resolve path if executable is
a relative or absolute path (https://github.com/ansible-collections/community.general/pull/7200).
- lxc connection plugin - now handles ``remote_addr`` defaulting to ``inventory_hostname``
correctly (https://github.com/ansible-collections/community.general/pull/7104).
- nsupdate - fix a possible ``list index out of range`` exception (https://github.com/ansible-collections/community.general/issues/836).
- oci_utils module util - fix inappropriate logical comparison expressions and
makes them simpler. The previous checks had logical short circuits (https://github.com/ansible-collections/community.general/pull/7125).
- pritunl module utils - fix incorrect URL parameter for orgnization add method
(https://github.com/ansible-collections/community.general/pull/7161).
minor_changes:
- make - allows ``params`` to be used without value (https://github.com/ansible-collections/community.general/pull/7180).
- pritunl module utils - ensure ``validate_certs`` parameter is honoured in
all methods (https://github.com/ansible-collections/community.general/pull/7156).
release_summary: Regular bugfix release.
fragments:
- 6.6.5.yml
- 7104_fix_lxc_remoteaddr_default.yml
- 7125-fix-inappropriate-comparison.yml
- 7156-ensure-validate-certs-parameter-is-honoured.yml
- 7161-fix-incorrect-post-parameter.yml
- 7180-make_params_without_value.yml
- 7200-cmd-runner-abs-path.yml
- 7219-fix-nsupdate-cname.yaml
release_date: '2023-09-11'
6.6.6:
changes:
bugfixes:
- mail - skip headers containing equals characters due to missing ``maxsplit``
on header key/value parsing (https://github.com/ansible-collections/community.general/pull/7303).
- onepassword - fix KeyError exception when trying to access value of a field
that is not filled out in OnePassword item (https://github.com/ansible-collections/community.general/pull/7241).
- terraform - prevents ``-backend-config`` option double encapsulating with
``shlex_quote`` function. (https://github.com/ansible-collections/community.general/pull/7301).
release_summary: Regular bugfix release.
fragments:
- 6.6.6.yml
- 7241-prevent-key-error-when-value-does-not-exist.yml
- 7301-fix-backend-config-string-encapsulation.yml
- 7303-mail-incorrect-header-parsing.yml
release_date: '2023-10-08'

View File

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

View File

@@ -19,6 +19,7 @@ DOCUMENTATION = '''
- Container identifier
default: inventory_hostname
vars:
- name: inventory_hostname
- name: ansible_host
- name: ansible_lxc_host
executable:

View File

@@ -56,7 +56,7 @@ EXAMPLES = '''
- name: Parse a CSV file's contents
ansible.builtin.debug:
msg: >-
{{ csv_data | community.genera.from_csv(dialect='unix') }}
{{ csv_data | community.general.from_csv(dialect='unix') }}
vars:
csv_data: |
Column 1,Value

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018, Scott Buchanan <sbuchanan@ri.pn>
# Copyright (c) 2018, Scott Buchanan <scott@buchanan.works>
# Copyright (c) 2016, Andrew Zenk <azenk@umn.edu> (lastpass.py used as starting point)
# 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)
@@ -451,10 +451,10 @@ class OnePassCLIv2(OnePassCLIBase):
# If the field name doesn't exist in the section, match on the value of "label"
# then "id" and return "value"
if field.get("label") == field_name:
return field["value"]
return field.get("value", "")
if field.get("id") == field_name:
return field["value"]
return field.get("value", "")
# Look at the section data and get an indentifier. The value of 'id' is either a unique ID
# or a human-readable string. If a 'label' field exists, prefer that since
@@ -464,10 +464,10 @@ class OnePassCLIv2(OnePassCLIBase):
if section_title == current_section_title:
# In the correct section. Check "label" then "id" for the desired field_name
if field.get("label") == field_name:
return field["value"]
return field.get("value", "")
if field.get("id") == field_name:
return field["value"]
return field.get("value", "")
return ""

View File

@@ -6,6 +6,7 @@
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import os
from functools import wraps
from ansible.module_utils.common.collections import is_sequence
@@ -199,12 +200,17 @@ class CmdRunner(object):
environ_update = {}
self.environ_update = environ_update
self.command[0] = module.get_bin_path(self.command[0], opt_dirs=path_prefix, required=True)
_cmd = self.command[0]
self.command[0] = _cmd if (os.path.isabs(_cmd) or '/' in _cmd) else module.get_bin_path(_cmd, opt_dirs=path_prefix, required=True)
for mod_param_name, spec in iteritems(module.argument_spec):
if mod_param_name not in self.arg_formats:
self.arg_formats[mod_param_name] = _Format.as_default_type(spec.get('type', 'str'), mod_param_name)
@property
def binary(self):
return self.command[0]
def __call__(self, args_order=None, output_process=None, ignore_value_none=True, check_mode_skip=False, check_mode_return=None, **kwargs):
if output_process is None:
output_process = _process_as_is

View File

@@ -79,7 +79,7 @@ def _post_pritunl_organization(
api_secret=api_secret,
base_url=base_url,
method="POST",
path="/organization/%s",
path="/organization",
headers={"Content-Type": "application/json"},
data=json.dumps(organization_data),
validate_certs=validate_certs,
@@ -220,7 +220,7 @@ def post_pritunl_organization(
api_secret=api_secret,
base_url=base_url,
organization_data={"name": organization_name},
validate_certs=True,
validate_certs=validate_certs,
)
if response.getcode() != 200:
@@ -248,7 +248,7 @@ def post_pritunl_user(
base_url=base_url,
organization_id=organization_id,
user_data=user_data,
validate_certs=True,
validate_certs=validate_certs,
)
if response.getcode() != 200:
@@ -267,7 +267,7 @@ def post_pritunl_user(
organization_id=organization_id,
user_data=user_data,
user_id=user_id,
validate_certs=True,
validate_certs=validate_certs,
)
if response.getcode() != 200:
@@ -287,7 +287,7 @@ def delete_pritunl_organization(
api_secret=api_secret,
base_url=base_url,
organization_id=organization_id,
validate_certs=True,
validate_certs=validate_certs,
)
if response.getcode() != 200:
@@ -307,7 +307,7 @@ def delete_pritunl_user(
base_url=base_url,
organization_id=organization_id,
user_id=user_id,
validate_certs=True,
validate_certs=validate_certs,
)
if response.getcode() != 200:

View File

@@ -561,7 +561,7 @@ def are_lists_equal(s, t):
if s is None and t is None:
return True
if (s is None and len(t) >= 0) or (t is None and len(s) >= 0) or (len(s) != len(t)):
if s is None or t is None or (len(s) != len(t)):
return False
if len(s) == 0:
@@ -1026,10 +1026,7 @@ def check_if_user_value_matches_resources_attr(
return
if (
resources_value_for_attr is None
and len(user_provided_value_for_attr) >= 0
or user_provided_value_for_attr is None
and len(resources_value_for_attr) >= 0
resources_value_for_attr is None or user_provided_value_for_attr is None
):
res[0] = False
return

View File

@@ -154,7 +154,7 @@ def _get_ctl_binary(module):
if ctl_binary is not None:
return ctl_binary
module.fail_json(msg="Neither of apache2ctl nor apachctl found. At least one apache control binary is necessary.")
module.fail_json(msg="Neither of apache2ctl nor apachectl found. At least one apache control binary is necessary.")
def _module_is_enabled(module):

View File

@@ -30,7 +30,9 @@ options:
default: 'always'
choices: [ always, on_create ]
givenname:
description: First name.
description:
- First name.
- If user does not exist and I(state=present), the usage of I(givenname) is required.
type: str
krbpasswordexpiration:
description:
@@ -54,7 +56,9 @@ options:
- Will not be set for an existing user unless I(update_password=always), which is the default.
type: str
sn:
description: Surname.
description:
- Surname.
- If user does not exist and I(state=present), the usage of I(sn) is required.
type: str
sshpubkey:
description:

View File

@@ -67,7 +67,7 @@ author:
EXAMPLES = '''
- name: Set default client scopes on realm level
community.general.keycloak_clientsecret_info:
community.general.keycloak_clientscope_type:
auth_client_id: admin-cli
auth_keycloak_url: https://auth.example.com/auth
auth_realm: master
@@ -79,7 +79,7 @@ EXAMPLES = '''
- name: Set default and optional client scopes on client level with token auth
community.general.keycloak_clientsecret_info:
community.general.keycloak_clientscope_type:
auth_client_id: admin-cli
auth_keycloak_url: https://auth.example.com/auth
token: TOKEN

View File

@@ -354,7 +354,7 @@ def main():
# NOTE: Backward compatible with old syntax using '|' as delimiter
for hdr in [x.strip() for x in header.split('|')]:
try:
h_key, h_val = hdr.split('=')
h_key, h_val = hdr.split('=', 1)
h_val = to_native(Header(h_val, charset))
msg.add_header(h_key, h_val)
except Exception:

View File

@@ -49,6 +49,7 @@ options:
params:
description:
- Any extra parameters to pass to make.
- If the value is empty, only the key will be used. For example, C(FOO:) will produce C(FOO), not C(FOO=).
type: dict
target:
description:
@@ -81,6 +82,18 @@ EXAMPLES = r'''
chdir: /home/ubuntu/cool-project
target: all
file: /some-project/Makefile
- name: build arm64 kernel on FreeBSD, with 16 parallel jobs
community.general.make:
chdir: /usr/src
jobs: 16
target: buildkernel
params:
# This adds -DWITH_FDT to the command line:
-DWITH_FDT:
# The following adds TARGET=arm64 TARGET_ARCH=aarch64 to the command line:
TARGET: arm64
TARGET_ARCH: aarch64
'''
RETURN = r'''
@@ -174,7 +187,7 @@ def main():
make_path = module.get_bin_path('make', required=True)
make_target = module.params['target']
if module.params['params'] is not None:
make_parameters = [k + '=' + str(v) for k, v in iteritems(module.params['params'])]
make_parameters = [k + (('=' + str(v)) if v is not None else '') for k, v in iteritems(module.params['params'])]
else:
make_parameters = []

View File

@@ -467,10 +467,8 @@ class RecordManager(object):
if lookup.rcode() != dns.rcode.NOERROR:
self.module.fail_json(msg='Failed to lookup TTL of existing matching record.')
if self.module.params['type'] == 'NS':
current_ttl = lookup.answer[0].ttl if lookup.answer else lookup.authority[0].ttl
else:
current_ttl = lookup.answer[0].ttl
current_ttl = lookup.answer[0].ttl if lookup.answer else lookup.authority[0].ttl
return current_ttl != self.module.params['ttl']

View File

@@ -408,6 +408,14 @@ options:
smbios:
description:
- Specifies SMBIOS type 1 fields.
- "Comma separated, Base64 encoded (optional) SMBIOS properties:"
- C([base64=<1|0>] [,family=<Base64 encoded string>])
- C([,manufacturer=<Base64 encoded string>])
- C([,product=<Base64 encoded string>])
- C([,serial=<Base64 encoded string>])
- C([,sku=<Base64 encoded string>])
- C([,uuid=<UUID>])
- C([,version=<Base64 encoded string>])
type: str
snapname:
description:

View File

@@ -325,7 +325,7 @@ def init_plugins(bin_path, project_path, backend_config, backend_config_files, i
for key, val in backend_config.items():
command.extend([
'-backend-config',
shlex_quote('{0}={1}'.format(key, val))
'{0}={1}'.format(key, val)
])
if backend_config_files:
for f in backend_config_files:

View File

@@ -21,6 +21,8 @@ from ansible_collections.community.general.plugins.module_utils.cmd_runner impor
def main():
module = AnsibleModule(
argument_spec=dict(
cmd=dict(type="str", default="echo"),
path_prefix=dict(type="str"),
arg_formats=dict(type="dict", default={}),
arg_order=dict(type="raw", required=True),
arg_values=dict(type="dict", default={}),
@@ -41,7 +43,7 @@ def main():
arg_formats[arg] = func(*args)
runner = CmdRunner(module, ['echo', '--'], arg_formats=arg_formats)
runner = CmdRunner(module, [module.params["cmd"], '--'], arg_formats=arg_formats, path_prefix=module.params["path_prefix"])
with runner.context(p['arg_order'], check_mode_skip=p['check_mode_skip']) as ctx:
result = ctx.run(**p['arg_values'])

View File

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

View File

@@ -6,3 +6,4 @@
ansible.builtin.include_tasks:
file: test_cmd_echo.yml
loop: "{{ cmd_echo_tests }}"
when: item.condition | default(true) | bool

View File

@@ -3,17 +3,26 @@
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
- name: test cmd_echo [{{ item.name }}]
cmd_echo:
arg_formats: "{{ item.arg_formats|default(omit) }}"
arg_order: "{{ item.arg_order }}"
arg_values: "{{ item.arg_values|default(omit) }}"
check_mode_skip: "{{ item.check_mode_skip|default(omit) }}"
aa: "{{ item.aa|default(omit) }}"
register: test_result
check_mode: "{{ item.check_mode|default(omit) }}"
ignore_errors: "{{ item.expect_error|default(omit) }}"
- name: create copy of /bin/echo ({{ item.name }})
ansible.builtin.copy:
src: /bin/echo
dest: "{{ item.copy_to }}/echo"
mode: "755"
when: item.copy_to is defined
- name: check results [{{ item.name }}]
- name: test cmd_echo module ({{ item.name }})
cmd_echo:
cmd: "{{ item.cmd | default(omit) }}"
path_prefix: "{{ item.path_prefix | default(omit) }}"
arg_formats: "{{ item.arg_formats | default(omit) }}"
arg_order: "{{ item.arg_order }}"
arg_values: "{{ item.arg_values | default(omit) }}"
check_mode_skip: "{{ item.check_mode_skip | default(omit) }}"
aa: "{{ item.aa | default(omit) }}"
register: test_result
check_mode: "{{ item.check_mode | default(omit) }}"
ignore_errors: "{{ item.expect_error | default(omit) }}"
- name: check results ({{ item.name }})
assert:
that: "{{ item.assertions }}"

View File

@@ -138,3 +138,125 @@ cmd_echo_tests:
- test_result.rc == 0
- test_result.out == "-- --answer=11 --tt-arg potatoes\n"
- test_result.err == ""
- name: use cmd echo
cmd: echo
arg_formats:
aa:
func: as_opt_eq_val
args: [--answer]
tt:
func: as_opt_val
args: [--tt-arg]
arg_order: 'aa tt'
arg_values:
tt: potatoes
aa: 11
assertions:
- test_result.rc == 0
- test_result.out == "-- --answer=11 --tt-arg potatoes\n"
- test_result.err == ""
- name: use cmd /bin/echo
cmd: /bin/echo
arg_formats:
aa:
func: as_opt_eq_val
args: [--answer]
tt:
func: as_opt_val
args: [--tt-arg]
arg_order: 'aa tt'
arg_values:
tt: potatoes
aa: 11
assertions:
- test_result.rc == 0
- test_result.out == "-- --answer=11 --tt-arg potatoes\n"
- test_result.err == ""
# this will not be in the regular set of paths get_bin_path() searches
- name: use cmd {{ remote_tmp_dir }}/echo
condition: >
{{
ansible_distribution != "MacOSX" and
not (ansible_distribution == "CentOS" and ansible_distribution_major_version is version('7.0', '<'))
}}
copy_to: "{{ remote_tmp_dir }}"
cmd: "{{ remote_tmp_dir }}/echo"
arg_formats:
aa:
func: as_opt_eq_val
args: [--answer]
tt:
func: as_opt_val
args: [--tt-arg]
arg_order: 'aa tt'
arg_values:
tt: potatoes
aa: 11
assertions:
- test_result.rc == 0
- test_result.out == "-- --answer=11 --tt-arg potatoes\n"
- test_result.err == ""
- name: use cmd echo with path_prefix {{ remote_tmp_dir }}
cmd: echo
condition: >
{{
ansible_distribution != "MacOSX" and
not (ansible_distribution == "CentOS" and ansible_distribution_major_version is version('7.0', '<'))
}}
copy_to: "{{ remote_tmp_dir }}"
path_prefix: "{{ remote_tmp_dir }}"
arg_formats:
aa:
func: as_opt_eq_val
args: [--answer]
tt:
func: as_opt_val
args: [--tt-arg]
arg_order: 'aa tt'
arg_values:
tt: potatoes
aa: 11
assertions:
- test_result.rc == 0
- test_result.out == "-- --answer=11 --tt-arg potatoes\n"
- test_result.err == ""
- name: use cmd never-existed
cmd: never-existed
arg_formats:
aa:
func: as_opt_eq_val
args: [--answer]
tt:
func: as_opt_val
args: [--tt-arg]
arg_order: 'aa tt'
arg_values:
tt: potatoes
aa: 11
expect_error: true
assertions:
- >
"Failed to find required executable" in test_result.msg
- name: use cmd /usr/bin/never-existed
cmd: /usr/bin/never-existed
arg_formats:
aa:
func: as_opt_eq_val
args: [--answer]
tt:
func: as_opt_val
args: [--tt-arg]
arg_order: 'aa tt'
arg_values:
tt: potatoes
aa: 11
expect_error: true
assertions:
- >
"No such file or directory" in test_result.msg

View File

@@ -4,13 +4,14 @@
# SPDX-License-Identifier: GPL-3.0-or-later
- vars:
package_name: xinetd
config_file: /etc/xinetd.conf
package_name: mdadm
config_file: /etc/mdadm.conf
block:
- name: Make sure that {{ package_name }} is not installed
pacman:
name: '{{ package_name }}'
state: absent
- name: Make sure {{config_file}}.pacsave file doesn't exist
file:
path: '{{config_file}}.pacsave'
@@ -32,6 +33,7 @@
pacman:
name: '{{ package_name }}'
state: absent
- name: Make sure {{config_file}}.pacsave exists
stat:
path: '{{config_file}}.pacsave'

View File

@@ -21,3 +21,8 @@
update_cache: true
upgrade: true
when: archlinux_upgrade_tag is changed
- name: Remove EXTERNALLY-MANAGED file
file:
path: /usr/lib/python{{ ansible_python.version.major }}.{{ ansible_python.version.minor }}/EXTERNALLY-MANAGED
state: absent

View File

@@ -81,5 +81,47 @@ MOCK_ENTRIES = {
"expected": ["first value"],
"output": load_file("v2_out_03.json")
},
{
# Request data from an omitted value (label lookup, no section)
"vault_name": "Test Vault",
"queries": ["Omitted values"],
"kwargs": {
"field": "label-without-value",
},
"expected": [""],
"output": load_file("v2_out_04.json")
},
{
# Request data from an omitted value (id lookup, no section)
"vault_name": "Test Vault",
"queries": ["Omitted values"],
"kwargs": {
"field": "67890q7mspf4x6zrlw3qejn7m",
},
"expected": [""],
"output": load_file("v2_out_04.json")
},
{
# Request data from an omitted value (label lookup, with section)
"vault_name": "Test Vault",
"queries": ["Omitted values"],
"kwargs": {
"field": "section-label-without-value",
"section": "section-without-values"
},
"expected": [""],
"output": load_file("v2_out_04.json")
},
{
# Request data from an omitted value (id lookup, with section)
"vault_name": "Test Vault",
"queries": ["Omitted values"],
"kwargs": {
"field": "123345q7mspf4x6zrlw3qejn7m",
"section": "section-without-values",
},
"expected": [""],
"output": load_file("v2_out_04.json")
},
],
}

View File

@@ -0,0 +1,67 @@
{
"id": "bgqegp3xcxnpfkb45olwigpkpi",
"title": "OmittedValues",
"version": 1,
"vault": {
"id": "stpebbaccrq72xulgouxsk4p7y",
"name": "Private"
},
"category": "LOGIN",
"last_edited_by": "WOUTERRUYBH7BFPHMZ2KKGL6AU",
"created_at": "2023-09-12T08:30:07Z",
"updated_at": "2023-09-12T08:30:07Z",
"additional_information": "fluxility",
"sections": [
{
"id": "7osqcvd43i75teocdzbb6d7mie",
"label": "section-without-values"
}
],
"fields": [
{
"id": "username",
"type": "STRING",
"purpose": "USERNAME",
"label": "username",
"value": "fluxility",
"reference": "op://Testcase/OmittedValues/username"
},
{
"id": "password",
"type": "CONCEALED",
"purpose": "PASSWORD",
"label": "password",
"value": "j89Dyb7psat*hkbkyLUQyq@GR.a-g2pQH_V_xtMhrn37rQ_2uRYoRiozj6TjWVLy2pbfEvjnse",
"entropy": 427.01202392578125,
"reference": "op://Testcase/OmittedValues/password",
"password_details": {
"entropy": 427,
"generated": true,
"strength": "FANTASTIC"
}
},
{
"id": "notesPlain",
"type": "STRING",
"purpose": "NOTES",
"label": "notesPlain",
"reference": "op://Testcase/OmittedValues/notesPlain"
},
{
"id": "67890q7mspf4x6zrlw3qejn7m",
"type": "URL",
"label": "label-without-value",
"reference": "op://01202392578125/OmittedValues/section-without-values/section-without-value"
},
{
"id": "123345q7mspf4x6zrlw3qejn7m",
"section": {
"id": "6hbtca5yrlmoptgy3nw74222",
"label": "section-without-values"
},
"type": "URL",
"label": "section-label-without-value",
"reference": "op://01202392578125/OmittedValues/section-without-values/section-without-value"
}
]
}

View File

@@ -0,0 +1,3 @@
GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
SPDX-License-Identifier: GPL-3.0-or-later
SPDX-FileCopyrightText: 2022, Ansible Project

View File

@@ -0,0 +1,102 @@
# Copyright (c) Ansible project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from collections import namedtuple
from itertools import chain, repeat
import pytest
import yaml
ModuleTestCase = namedtuple("ModuleTestCase", ["id", "input", "output", "run_command_calls"])
RunCmdCall = namedtuple("RunCmdCall", ["command", "environ", "rc", "out", "err"])
class CmdRunnerTestHelper(object):
def __init__(self, test_cases):
self._test_cases = test_cases
if isinstance(test_cases, (list, tuple)):
self.testcases = test_cases
else:
self.testcases = self._make_test_cases()
@property
def cmd_fixture(self):
@pytest.fixture
def patch_bin(mocker):
def mockie(self, path, *args, **kwargs):
return "/testbin/{0}".format(path)
mocker.patch('ansible.module_utils.basic.AnsibleModule.get_bin_path', mockie)
return patch_bin
def _make_test_cases(self):
test_cases = yaml.safe_load(self._test_cases)
results = []
for tc in test_cases:
tc["run_command_calls"] = [RunCmdCall(**r) for r in tc["run_command_calls"]] if tc.get("run_command_calls") else []
results.append(ModuleTestCase(**tc))
return results
@property
def testcases_params(self):
return [[x.input, x] for x in self.testcases]
@property
def testcases_ids(self):
return [item.id for item in self.testcases]
def __call__(self, testcase, mocker):
return _Context(self, testcase, mocker)
class _Context(object):
def __init__(self, helper, testcase, mocker):
self.helper = helper
self.testcase = testcase
self.mocker = mocker
self.run_cmd_calls = self.testcase.run_command_calls
self.mock_run_cmd = self._make_mock_run_cmd()
def _make_mock_run_cmd(self):
call_results = [(x.rc, x.out, x.err) for x in self.run_cmd_calls]
error_call_results = (123,
"OUT: testcase has not enough run_command calls",
"ERR: testcase has not enough run_command calls")
mock_run_command = self.mocker.patch('ansible.module_utils.basic.AnsibleModule.run_command',
side_effect=chain(call_results, repeat(error_call_results)))
return mock_run_command
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
return False
def check_results(self, results):
print("testcase =\n%s" % str(self.testcase))
print("results =\n%s" % results)
if 'exception' in results:
print("exception = \n%s" % results["exception"])
for test_result in self.testcase.output:
assert results[test_result] == self.testcase.output[test_result], \
"'{0}': '{1}' != '{2}'".format(test_result, results[test_result], self.testcase.output[test_result])
call_args_list = [(item[0][0], item[1]) for item in self.mock_run_cmd.call_args_list]
expected_call_args_list = [(item.command, item.environ) for item in self.run_cmd_calls]
print("call args list =\n%s" % call_args_list)
print("expected args list =\n%s" % expected_call_args_list)
assert self.mock_run_cmd.call_count == len(self.run_cmd_calls)
if self.mock_run_cmd.call_count:
assert call_args_list == expected_call_args_list

View File

@@ -7,235 +7,34 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import json
from collections import namedtuple
from ansible_collections.community.general.plugins.modules import opkg
from ansible_collections.community.general.plugins.modules import opkg as module
import pytest
TESTED_MODULE = opkg.__name__
from .cmd_runner_test_utils import CmdRunnerTestHelper
ModuleTestCase = namedtuple("ModuleTestCase", ["id", "input", "output", "run_command_calls"])
RunCmdCall = namedtuple("RunCmdCall", ["command", "environ", "rc", "out", "err"])
@pytest.fixture
def patch_opkg(mocker):
mocker.patch('ansible.module_utils.basic.AnsibleModule.get_bin_path', return_value='/testbin/opkg')
TEST_CASES = [
ModuleTestCase(
id="install_zlibdev",
input={"name": "zlib-dev", "state": "present"},
output={
"msg": "installed 1 package(s)"
},
run_command_calls=[
RunCmdCall(
command=["/testbin/opkg", "list-installed", "zlib-dev"],
environ={'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
rc=0,
out="",
err="",
),
RunCmdCall(
command=["/testbin/opkg", "install", "zlib-dev"],
environ={'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
rc=0,
out=(
"Installing zlib-dev (1.2.11-6) to root..."
"Downloading https://downloads.openwrt.org/releases/22.03.0/packages/mips_24kc/base/zlib-dev_1.2.11-6_mips_24kc.ipk"
"Installing zlib (1.2.11-6) to root..."
"Downloading https://downloads.openwrt.org/releases/22.03.0/packages/mips_24kc/base/zlib_1.2.11-6_mips_24kc.ipk"
"Configuring zlib."
"Configuring zlib-dev."
),
err="",
),
RunCmdCall(
command=["/testbin/opkg", "list-installed", "zlib-dev"],
environ={'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
rc=0,
out="zlib-dev - 1.2.11-6\n",
err="",
),
],
),
ModuleTestCase(
id="install_zlibdev_present",
input={"name": "zlib-dev", "state": "present"},
output={
"msg": "package(s) already present"
},
run_command_calls=[
RunCmdCall(
command=["/testbin/opkg", "list-installed", "zlib-dev"],
environ={'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
rc=0,
out="zlib-dev - 1.2.11-6\n",
err="",
),
],
),
ModuleTestCase(
id="install_zlibdev_force_reinstall",
input={"name": "zlib-dev", "state": "present", "force": "reinstall"},
output={
"msg": "installed 1 package(s)"
},
run_command_calls=[
RunCmdCall(
command=["/testbin/opkg", "list-installed", "zlib-dev"],
environ={'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
rc=0,
out="zlib-dev - 1.2.11-6\n",
err="",
),
RunCmdCall(
command=["/testbin/opkg", "install", "--force-reinstall", "zlib-dev"],
environ={'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
rc=0,
out=(
"Installing zlib-dev (1.2.11-6) to root...\n"
"Downloading https://downloads.openwrt.org/releases/22.03.0/packages/mips_24kc/base/zlib-dev_1.2.11-6_mips_24kc.ipk\n"
"Configuring zlib-dev.\n"
),
err="",
),
RunCmdCall(
command=["/testbin/opkg", "list-installed", "zlib-dev"],
environ={'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
rc=0,
out="zlib-dev - 1.2.11-6\n",
err="",
),
],
),
ModuleTestCase(
id="install_zlibdev_with_version",
input={"name": "zlib-dev=1.2.11-6", "state": "present"},
output={
"msg": "installed 1 package(s)"
},
run_command_calls=[
RunCmdCall(
command=["/testbin/opkg", "list-installed", "zlib-dev"],
environ={'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
rc=0,
out="",
err="",
),
RunCmdCall(
command=["/testbin/opkg", "install", "zlib-dev=1.2.11-6"],
environ={'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
rc=0,
out=(
"Installing zlib-dev (1.2.11-6) to root..."
"Downloading https://downloads.openwrt.org/releases/22.03.0/packages/mips_24kc/base/zlib-dev_1.2.11-6_mips_24kc.ipk"
"Installing zlib (1.2.11-6) to root..."
"Downloading https://downloads.openwrt.org/releases/22.03.0/packages/mips_24kc/base/zlib_1.2.11-6_mips_24kc.ipk"
"Configuring zlib."
"Configuring zlib-dev."
),
err="",
),
RunCmdCall(
command=["/testbin/opkg", "list-installed", "zlib-dev"],
environ={'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
rc=0,
out="zlib-dev - 1.2.11-6 \n", # This output has the extra space at the end, to satisfy the behaviour of Yocto/OpenEmbedded's opkg
err="",
),
],
),
ModuleTestCase(
id="install_vim_updatecache",
input={"name": "vim-fuller", "state": "present", "update_cache": True},
output={
"msg": "installed 1 package(s)"
},
run_command_calls=[
RunCmdCall(
command=["/testbin/opkg", "update"],
environ={'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
rc=0,
out="",
err="",
),
RunCmdCall(
command=["/testbin/opkg", "list-installed", "vim-fuller"],
environ={'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
rc=0,
out="",
err="",
),
RunCmdCall(
command=["/testbin/opkg", "install", "vim-fuller"],
environ={'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
rc=0,
out=(
"Multiple packages (libgcc1 and libgcc1) providing same name marked HOLD or PREFER. Using latest.\n"
"Installing vim-fuller (9.0-1) to root...\n"
"Downloading https://downloads.openwrt.org/snapshots/packages/x86_64/packages/vim-fuller_9.0-1_x86_64.ipk\n"
"Installing terminfo (6.4-2) to root...\n"
"Downloading https://downloads.openwrt.org/snapshots/packages/x86_64/base/terminfo_6.4-2_x86_64.ipk\n"
"Installing libncurses6 (6.4-2) to root...\n"
"Downloading https://downloads.openwrt.org/snapshots/packages/x86_64/base/libncurses6_6.4-2_x86_64.ipk\n"
"Configuring terminfo.\n"
"Configuring libncurses6.\n"
"Configuring vim-fuller.\n"
),
err="",
),
RunCmdCall(
command=["/testbin/opkg", "list-installed", "vim-fuller"],
environ={'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
rc=0,
out="vim-fuller - 9.0-1 \n", # This output has the extra space at the end, to satisfy the behaviour of Yocto/OpenEmbedded's opkg
err="",
),
],
),
]
TEST_CASES_IDS = [item.id for item in TEST_CASES]
TESTED_MODULE = module.__name__
with open("tests/unit/plugins/modules/test_opkg.yaml", "r") as TEST_CASES:
helper = CmdRunnerTestHelper(test_cases=TEST_CASES)
patch_bin = helper.cmd_fixture
@pytest.mark.parametrize('patch_ansible_module, testcase',
[[x.input, x] for x in TEST_CASES],
ids=TEST_CASES_IDS,
helper.testcases_params, ids=helper.testcases_ids,
indirect=['patch_ansible_module'])
@pytest.mark.usefixtures('patch_ansible_module')
def test_opkg(mocker, capfd, patch_opkg, testcase):
def test_module(mocker, capfd, patch_bin, testcase):
"""
Run unit tests for test cases listen in TEST_CASES
Run unit tests for test cases listed in TEST_CASES
"""
run_cmd_calls = testcase.run_command_calls
with helper(testcase, mocker) as ctx:
# Try to run test case
with pytest.raises(SystemExit):
module.main()
# Mock function used for running commands first
call_results = [(x.rc, x.out, x.err) for x in run_cmd_calls]
mock_run_command = mocker.patch('ansible.module_utils.basic.AnsibleModule.run_command', side_effect=call_results)
out, err = capfd.readouterr()
results = json.loads(out)
# Try to run test case
with pytest.raises(SystemExit):
opkg.main()
out, err = capfd.readouterr()
results = json.loads(out)
print("testcase =\n%s" % str(testcase))
print("results =\n%s" % results)
for test_result in testcase.output:
assert results[test_result] == testcase.output[test_result], \
"'{0}': '{1}' != '{2}'".format(test_result, results[test_result], testcase.output[test_result])
call_args_list = [(item[0][0], item[1]) for item in mock_run_command.call_args_list]
expected_call_args_list = [(item.command, item.environ) for item in run_cmd_calls]
print("call args list =\n%s" % call_args_list)
print("expected args list =\n%s" % expected_call_args_list)
assert mock_run_command.call_count == len(run_cmd_calls)
if mock_run_command.call_count:
assert call_args_list == expected_call_args_list
ctx.check_results(results)

View File

@@ -0,0 +1,142 @@
# -*- coding: utf-8 -*-
# Copyright (c) Alexei Znamensky (russoz@gmail.com)
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
---
- id: install_zlibdev
input:
name: zlib-dev
state: present
output:
msg: installed 1 package(s)
run_command_calls:
- command: [/testbin/opkg, list-installed, zlib-dev]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: ""
err: ""
- command: [/testbin/opkg, install, zlib-dev]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: |
Installing zlib-dev (1.2.11-6) to root...
Downloading https://downloads.openwrt.org/releases/22.03.0/packages/mips_24kc/base/zlib-dev_1.2.11-6_mips_24kc.ipk
Installing zlib (1.2.11-6) to root...
Downloading https://downloads.openwrt.org/releases/22.03.0/packages/mips_24kc/base/zlib_1.2.11-6_mips_24kc.ipk
Configuring zlib.
Configuring zlib-dev.
err: ""
- command: [/testbin/opkg, list-installed, zlib-dev]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: |
zlib-dev - 1.2.11-6
err: ""
- id: install_zlibdev_present
input:
name: zlib-dev
state: present
output:
msg: package(s) already present
run_command_calls:
- command: [/testbin/opkg, list-installed, zlib-dev]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: |
zlib-dev - 1.2.11-6
err: ""
- id: install_zlibdev_force_reinstall
input:
name: zlib-dev
state: present
force: reinstall
output:
msg: installed 1 package(s)
run_command_calls:
- command: [/testbin/opkg, list-installed, zlib-dev]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: |
zlib-dev - 1.2.11-6
err: ""
- command: [/testbin/opkg, install, --force-reinstall, zlib-dev]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: |
Installing zlib-dev (1.2.11-6) to root...
Downloading https://downloads.openwrt.org/releases/22.03.0/packages/mips_24kc/base/zlib-dev_1.2.11-6_mips_24kc.ipk
Configuring zlib-dev.
err: ""
- command: [/testbin/opkg, list-installed, zlib-dev]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: |
zlib-dev - 1.2.11-6
err: ""
- id: install_zlibdev_with_version
input:
name: zlib-dev=1.2.11-6
state: present
output:
msg: installed 1 package(s)
run_command_calls:
- command: [/testbin/opkg, list-installed, zlib-dev]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: ""
err: ""
- command: [/testbin/opkg, install, zlib-dev=1.2.11-6]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: |
Installing zlib-dev (1.2.11-6) to root...
Downloading https://downloads.openwrt.org/releases/22.03.0/packages/mips_24kc/base/zlib-dev_1.2.11-6_mips_24kc.ipk
Installing zlib (1.2.11-6) to root...
Downloading https://downloads.openwrt.org/releases/22.03.0/packages/mips_24kc/base/zlib_1.2.11-6_mips_24kc.ipk
Configuring zlib.
Configuring zlib-dev.
err: ""
- command: [/testbin/opkg, list-installed, zlib-dev]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: "zlib-dev - 1.2.11-6 \n" # This output has the extra space at the end, to satisfy the behaviour of Yocto/OpenEmbedded's opkg
err: ""
- id: install_vim_updatecache
input:
name: vim-fuller
state: present
update_cache: true
output:
msg: installed 1 package(s)
run_command_calls:
- command: [/testbin/opkg, update]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: ""
err: ""
- command: [/testbin/opkg, list-installed, vim-fuller]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: ""
err: ""
- command: [/testbin/opkg, install, vim-fuller]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: |
Multiple packages (libgcc1 and libgcc1) providing same name marked HOLD or PREFER. Using latest.
Installing vim-fuller (9.0-1) to root...
Downloading https://downloads.openwrt.org/snapshots/packages/x86_64/packages/vim-fuller_9.0-1_x86_64.ipk
Installing terminfo (6.4-2) to root...
Downloading https://downloads.openwrt.org/snapshots/packages/x86_64/base/terminfo_6.4-2_x86_64.ipk
Installing libncurses6 (6.4-2) to root...
Downloading https://downloads.openwrt.org/snapshots/packages/x86_64/base/libncurses6_6.4-2_x86_64.ipk
Configuring terminfo.
Configuring libncurses6.
Configuring vim-fuller.
err: ""
- command: [/testbin/opkg, list-installed, vim-fuller]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: "vim-fuller - 9.0-1 \n" # This output has the extra space at the end, to satisfy the behaviour of Yocto/OpenEmbedded's opkg
err: ""

View File

@@ -13,300 +13,34 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import json
from ansible_collections.community.general.plugins.modules import xfconf
from ansible_collections.community.general.plugins.modules import xfconf as module
import pytest
TESTED_MODULE = xfconf.__name__
from .cmd_runner_test_utils import CmdRunnerTestHelper
@pytest.fixture
def patch_xfconf(mocker):
"""
Function used for mocking some parts of redhat_subscription module
"""
mocker.patch('ansible_collections.community.general.plugins.module_utils.mh.module_helper.AnsibleModule.get_bin_path',
return_value='/testbin/xfconf-query')
@pytest.mark.parametrize('patch_ansible_module', [{}], indirect=['patch_ansible_module'])
@pytest.mark.usefixtures('patch_ansible_module')
def test_without_required_parameters(capfd, patch_xfconf):
"""
Failure must occurs when all parameters are missing
"""
with pytest.raises(SystemExit):
xfconf.main()
out, err = capfd.readouterr()
results = json.loads(out)
assert results['failed']
assert 'missing required arguments' in results['msg']
TEST_CASES = [
[
{
'channel': 'xfwm4',
'property': '/general/inactive_opacity',
'state': 'present',
'value_type': 'int',
'value': 90,
},
{
'id': 'test_property_set_property',
'run_command.calls': [
(
# Calling of following command will be asserted
['/testbin/xfconf-query', '--channel', 'xfwm4', '--property', '/general/inactive_opacity'],
# Was return code checked?
{'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
# Mock of returned code, stdout and stderr
(0, '100\n', '',),
),
(
# Calling of following command will be asserted
['/testbin/xfconf-query', '--channel', 'xfwm4', '--property', '/general/inactive_opacity',
'--create', '--type', 'int', '--set', '90'],
# Was return code checked?
{'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
# Mock of returned code, stdout and stderr
(0, '', '',),
),
],
'changed': True,
'previous_value': '100',
'value_type': 'int',
'value': '90',
},
],
[
{
'channel': 'xfwm4',
'property': '/general/inactive_opacity',
'state': 'present',
'value_type': 'int',
'value': 90,
},
{
'id': 'test_property_set_property_same_value',
'run_command.calls': [
(
# Calling of following command will be asserted
['/testbin/xfconf-query', '--channel', 'xfwm4', '--property', '/general/inactive_opacity'],
# Was return code checked?
{'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
# Mock of returned code, stdout and stderr
(0, '90\n', '',),
),
(
# Calling of following command will be asserted
['/testbin/xfconf-query', '--channel', 'xfwm4', '--property', '/general/inactive_opacity',
'--create', '--type', 'int', '--set', '90'],
# Was return code checked?
{'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
# Mock of returned code, stdout and stderr
(0, '', '',),
),
],
'changed': False,
'previous_value': '90',
'value_type': 'int',
'value': '90',
},
],
[
{
'channel': 'xfce4-session',
'property': '/general/SaveOnExit',
'state': 'present',
'value_type': 'bool',
'value': False,
},
{
'id': 'test_property_set_property_bool_false',
'run_command.calls': [
(
# Calling of following command will be asserted
['/testbin/xfconf-query', '--channel', 'xfce4-session', '--property', '/general/SaveOnExit'],
# Was return code checked?
{'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
# Mock of returned code, stdout and stderr
(0, 'true\n', '',),
),
(
# Calling of following command will be asserted
['/testbin/xfconf-query', '--channel', 'xfce4-session', '--property', '/general/SaveOnExit',
'--create', '--type', 'bool', '--set', 'false'],
# Was return code checked?
{'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
# Mock of returned code, stdout and stderr
(0, 'false\n', '',),
),
],
'changed': True,
'previous_value': 'true',
'value_type': 'bool',
'value': 'False',
},
],
[
{
'channel': 'xfwm4',
'property': '/general/workspace_names',
'state': 'present',
'value_type': 'string',
'value': ['A', 'B', 'C'],
},
{
'id': 'test_property_set_array',
'run_command.calls': [
(
# Calling of following command will be asserted
['/testbin/xfconf-query', '--channel', 'xfwm4', '--property', '/general/workspace_names'],
# Was return code checked?
{'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
# Mock of returned code, stdout and stderr
(0, 'Value is an array with 3 items:\n\nMain\nWork\nTmp\n', '',),
),
(
# Calling of following command will be asserted
['/testbin/xfconf-query', '--channel', 'xfwm4', '--property', '/general/workspace_names',
'--create', '--force-array', '--type', 'string', '--set', 'A', '--type', 'string', '--set', 'B',
'--type', 'string', '--set', 'C'],
# Was return code checked?
{'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
# Mock of returned code, stdout and stderr
(0, '', '',),
),
],
'changed': True,
'previous_value': ['Main', 'Work', 'Tmp'],
'value_type': ['str', 'str', 'str'],
'value': ['A', 'B', 'C'],
},
],
[
{
'channel': 'xfwm4',
'property': '/general/workspace_names',
'state': 'present',
'value_type': 'string',
'value': ['A', 'B', 'C'],
},
{
'id': 'test_property_set_array_to_same_value',
'run_command.calls': [
(
# Calling of following command will be asserted
['/testbin/xfconf-query', '--channel', 'xfwm4', '--property', '/general/workspace_names'],
# Was return code checked?
{'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
# Mock of returned code, stdout and stderr
(0, 'Value is an array with 3 items:\n\nA\nB\nC\n', '',),
),
(
# Calling of following command will be asserted
['/testbin/xfconf-query', '--channel', 'xfwm4', '--property', '/general/workspace_names',
'--create', '--force-array', '--type', 'string', '--set', 'A', '--type', 'string', '--set', 'B',
'--type', 'string', '--set', 'C'],
# Was return code checked?
{'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
# Mock of returned code, stdout and stderr
(0, '', '',),
),
],
'changed': False,
'previous_value': ['A', 'B', 'C'],
'value_type': ['str', 'str', 'str'],
'value': ['A', 'B', 'C'],
},
],
[
{
'channel': 'xfwm4',
'property': '/general/workspace_names',
'state': 'absent',
},
{
'id': 'test_property_reset_value',
'run_command.calls': [
(
# Calling of following command will be asserted
['/testbin/xfconf-query', '--channel', 'xfwm4', '--property', '/general/workspace_names'],
# Was return code checked?
{'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
# Mock of returned code, stdout and stderr
(0, 'Value is an array with 3 items:\n\nA\nB\nC\n', '',),
),
(
# Calling of following command will be asserted
['/testbin/xfconf-query', '--channel', 'xfwm4', '--property', '/general/workspace_names',
'--reset'],
# Was return code checked?
{'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False},
# Mock of returned code, stdout and stderr
(0, '', '',),
),
],
'changed': True,
'previous_value': ['A', 'B', 'C'],
'value_type': None,
'value': None,
},
],
]
TEST_CASES_IDS = [item[1]['id'] for item in TEST_CASES]
TESTED_MODULE = module.__name__
with open("tests/unit/plugins/modules/test_xfconf.yaml", "r") as TEST_CASES:
helper = CmdRunnerTestHelper(test_cases=TEST_CASES)
patch_bin = helper.cmd_fixture
@pytest.mark.parametrize('patch_ansible_module, testcase',
TEST_CASES,
ids=TEST_CASES_IDS,
helper.testcases_params, ids=helper.testcases_ids,
indirect=['patch_ansible_module'])
@pytest.mark.usefixtures('patch_ansible_module')
def test_xfconf(mocker, capfd, patch_xfconf, testcase):
def test_module(mocker, capfd, patch_bin, testcase):
"""
Run unit tests for test cases listen in TEST_CASES
Run unit tests for test cases listed in TEST_CASES
"""
# Mock function used for running commands first
call_results = [item[2] for item in testcase['run_command.calls']]
mock_run_command = mocker.patch(
'ansible.module_utils.basic.AnsibleModule.run_command',
side_effect=call_results)
with helper(testcase, mocker) as ctx:
# Try to run test case
with pytest.raises(SystemExit):
module.main()
# Try to run test case
with pytest.raises(SystemExit):
xfconf.main()
out, err = capfd.readouterr()
results = json.loads(out)
out, err = capfd.readouterr()
results = json.loads(out)
print("testcase =\n%s" % testcase)
print("results =\n%s" % results)
assert 'changed' in results
assert results['changed'] == testcase['changed']
for test_result in ('channel', 'property'):
assert test_result in results, "'{0}' not found in {1}".format(test_result, results)
assert results[test_result] == results['invocation']['module_args'][test_result], \
"'{0}': '{1}' != '{2}'".format(test_result, results[test_result], results['invocation']['module_args'][test_result])
assert mock_run_command.call_count == len(testcase['run_command.calls'])
if mock_run_command.call_count:
call_args_list = [(item[0][0], item[1]) for item in mock_run_command.call_args_list]
expected_call_args_list = [(item[0], item[1]) for item in testcase['run_command.calls']]
print("call args list =\n%s" % call_args_list)
print("expected args list =\n%s" % expected_call_args_list)
assert call_args_list == expected_call_args_list
expected_cmd, dummy, expected_res = testcase['run_command.calls'][-1]
assert results['cmd'] == expected_cmd
assert results['stdout'] == expected_res[1]
assert results['stderr'] == expected_res[2]
for conditional_test_result in ('msg', 'value', 'previous_value'):
if conditional_test_result in testcase:
assert conditional_test_result in results, "'{0}' not found in {1}".format(conditional_test_result, results)
assert results[conditional_test_result] == testcase[conditional_test_result], \
"'{0}': '{1}' != '{2}'".format(conditional_test_result, results[conditional_test_result], testcase[conditional_test_result])
ctx.check_results(results)

View File

@@ -0,0 +1,185 @@
# -*- coding: utf-8 -*-
# Copyright (c) Alexei Znamensky (russoz@gmail.com)
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
---
- id: test_missing_input
input: {}
output:
failed: true
msg: "missing required arguments: channel, property"
- id: test_property_set_property
input:
channel: xfwm4
property: /general/inactive_opacity
state: present
value_type: int
value: 90
output:
changed: true
previous_value: '100'
type: int
value: '90'
run_command_calls:
- command: [/testbin/xfconf-query, --channel, xfwm4, --property, /general/inactive_opacity]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: "100\n"
err: ""
- command: [/testbin/xfconf-query, --channel, xfwm4, --property, /general/inactive_opacity, --create, --type, int, --set, '90']
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: ""
err: ""
- id: test_property_set_property_same_value
input:
channel: xfwm4
property: /general/inactive_opacity
state: present
value_type: int
value: 90
output:
changed: false
previous_value: '90'
type: int
value: '90'
run_command_calls:
- command: [/testbin/xfconf-query, --channel, xfwm4, --property, /general/inactive_opacity]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: "90\n"
err: ""
- command: [/testbin/xfconf-query, --channel, xfwm4, --property, /general/inactive_opacity, --create, --type, int, --set, '90']
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: ""
err: ""
- id: test_property_set_property_bool_false
input:
channel: xfce4-session
property: /general/SaveOnExit
state: present
value_type: bool
value: False
output:
changed: true
previous_value: 'true'
type: bool
value: 'False'
run_command_calls:
- command: [/testbin/xfconf-query, --channel, xfce4-session, --property, /general/SaveOnExit]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: "true\n"
err: ""
- command: [/testbin/xfconf-query, --channel, xfce4-session, --property, /general/SaveOnExit, --create, --type, bool, --set, 'false']
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: "false\n"
err: ""
- id: test_property_set_array
input:
channel: xfwm4
property: /general/workspace_names
state: present
value_type: string
value: [A, B, C]
output:
changed: true
previous_value: [Main, Work, Tmp]
type: [string, string, string]
value: [A, B, C]
run_command_calls:
- command: [/testbin/xfconf-query, --channel, xfwm4, --property, /general/workspace_names]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: "Value is an array with 3 items:\n\nMain\nWork\nTmp\n"
err: ""
- command:
- /testbin/xfconf-query
- --channel
- xfwm4
- --property
- /general/workspace_names
- --create
- --force-array
- --type
- string
- --set
- A
- --type
- string
- --set
- B
- --type
- string
- --set
- C
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: ""
err: ""
- id: test_property_set_array_to_same_value
input:
channel: xfwm4
property: /general/workspace_names
state: present
value_type: string
value: [A, B, C]
output:
changed: false
previous_value: [A, B, C]
type: [string, string, string]
value: [A, B, C]
run_command_calls:
- command: [/testbin/xfconf-query, --channel, xfwm4, --property, /general/workspace_names]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: "Value is an array with 3 items:\n\nA\nB\nC\n"
err: ""
- command:
- /testbin/xfconf-query
- --channel
- xfwm4
- --property
- /general/workspace_names
- --create
- --force-array
- --type
- string
- --set
- A
- --type
- string
- --set
- B
- --type
- string
- --set
- C
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: ""
err: ""
- id: test_property_reset_value
input:
channel: xfwm4
property: /general/workspace_names
state: absent
output:
changed: true
previous_value: [A, B, C]
type: null
value: null
run_command_calls:
- command: [/testbin/xfconf-query, --channel, xfwm4, --property, /general/workspace_names]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: "Value is an array with 3 items:\n\nA\nB\nC\n"
err: ""
- command: [/testbin/xfconf-query, --channel, xfwm4, --property, /general/workspace_names, --reset]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
rc: 0
out: ""
err: ""

View File

@@ -6,167 +6,34 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import json
from ansible_collections.community.general.plugins.modules import xfconf_info
from ansible_collections.community.general.plugins.modules import xfconf_info as module
import pytest
TESTED_MODULE = xfconf_info.__name__
from .cmd_runner_test_utils import CmdRunnerTestHelper
@pytest.fixture
def patch_xfconf_info(mocker):
"""
Function used for mocking some parts of redhat_subscription module
"""
mocker.patch('ansible_collections.community.general.plugins.module_utils.mh.module_helper.AnsibleModule.get_bin_path',
return_value='/testbin/xfconf-query')
TEST_CASES = [
[
{'channel': 'xfwm4', 'property': '/general/inactive_opacity'},
{
'id': 'test_simple_property_get',
'run_command.calls': [
(
# Calling of following command will be asserted
['/testbin/xfconf-query', '--channel', 'xfwm4', '--property', '/general/inactive_opacity'],
# Was return code checked?
{'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': True},
# Mock of returned code, stdout and stderr
(0, '100\n', '',),
),
],
'is_array': False,
'value': '100',
}
],
[
{'channel': 'xfwm4', 'property': '/general/i_dont_exist'},
{
'id': 'test_simple_property_get_nonexistent',
'run_command.calls': [
(
# Calling of following command will be asserted
['/testbin/xfconf-query', '--channel', 'xfwm4', '--property', '/general/i_dont_exist'],
# Was return code checked?
{'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': True},
# Mock of returned code, stdout and stderr
(1, '', 'Property "/general/i_dont_exist" does not exist on channel "xfwm4".\n',),
),
],
'is_array': False,
}
],
[
{'property': '/general/i_dont_exist'},
{
'id': 'test_property_no_channel',
'run_command.calls': [],
}
],
[
{'channel': 'xfwm4', 'property': '/general/workspace_names'},
{
'id': 'test_property_get_array',
'run_command.calls': [
(
# Calling of following command will be asserted
['/testbin/xfconf-query', '--channel', 'xfwm4', '--property', '/general/workspace_names'],
# Was return code checked?
{'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': True},
# Mock of returned code, stdout and stderr
(0, 'Value is an array with 3 items:\n\nMain\nWork\nTmp\n', '',),
),
],
'is_array': True,
'value_array': ['Main', 'Work', 'Tmp'],
},
],
[
{},
{
'id': 'get_channels',
'run_command.calls': [
(
# Calling of following command will be asserted
['/testbin/xfconf-query', '--list'],
# Was return code checked?
{'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': True},
# Mock of returned code, stdout and stderr
(0, 'Channels:\n a\n b\n c\n', '',),
),
],
'is_array': False,
'channels': ['a', 'b', 'c'],
},
],
[
{'channel': 'xfwm4'},
{
'id': 'get_properties',
'run_command.calls': [
(
# Calling of following command will be asserted
['/testbin/xfconf-query', '--list', '--channel', 'xfwm4'],
# Was return code checked?
{'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': True},
# Mock of returned code, stdout and stderr
(0, '/general/wrap_cycle\n/general/wrap_layout\n/general/wrap_resistance\n/general/wrap_windows\n'
'/general/wrap_workspaces\n/general/zoom_desktop\n', '',),
),
],
'is_array': False,
'properties': [
'/general/wrap_cycle',
'/general/wrap_layout',
'/general/wrap_resistance',
'/general/wrap_windows',
'/general/wrap_workspaces',
'/general/zoom_desktop',
],
},
],
]
TEST_CASES_IDS = [item[1]['id'] for item in TEST_CASES]
TESTED_MODULE = module.__name__
with open("tests/unit/plugins/modules/test_xfconf_info.yaml", "r") as TEST_CASES:
helper = CmdRunnerTestHelper(test_cases=TEST_CASES)
patch_bin = helper.cmd_fixture
@pytest.mark.parametrize('patch_ansible_module, testcase',
TEST_CASES,
ids=TEST_CASES_IDS,
helper.testcases_params, ids=helper.testcases_ids,
indirect=['patch_ansible_module'])
@pytest.mark.usefixtures('patch_ansible_module')
def test_xfconf_info(mocker, capfd, patch_xfconf_info, testcase):
def test_module(mocker, capfd, patch_bin, testcase):
"""
Run unit tests for test cases listen in TEST_CASES
Run unit tests for test cases listed in TEST_CASES
"""
# Mock function used for running commands first
call_results = [item[2] for item in testcase['run_command.calls']]
mock_run_command = mocker.patch(
'ansible_collections.community.general.plugins.module_utils.mh.module_helper.AnsibleModule.run_command',
side_effect=call_results)
with helper(testcase, mocker) as ctx:
# Try to run test case
with pytest.raises(SystemExit):
module.main()
# Try to run test case
with pytest.raises(SystemExit):
xfconf_info.main()
out, err = capfd.readouterr()
results = json.loads(out)
out, err = capfd.readouterr()
results = json.loads(out)
print("testcase =\n%s" % testcase)
print("results =\n%s" % results)
for conditional_test_result in ('value_array', 'value', 'is_array', 'properties', 'channels'):
if conditional_test_result in testcase:
assert conditional_test_result in results, "'{0}' not found in {1}".format(conditional_test_result, results)
assert results[conditional_test_result] == testcase[conditional_test_result], \
"'{0}': '{1}' != '{2}'".format(conditional_test_result, results[conditional_test_result], testcase[conditional_test_result])
assert mock_run_command.call_count == len(testcase['run_command.calls'])
if mock_run_command.call_count:
call_args_list = [(item[0][0], item[1]) for item in mock_run_command.call_args_list]
expected_call_args_list = [(item[0], item[1]) for item in testcase['run_command.calls']]
print("call args list =\n%s" % call_args_list)
print("expected args list =\n%s" % expected_call_args_list)
assert call_args_list == expected_call_args_list
ctx.check_results(results)

View File

@@ -0,0 +1,83 @@
# -*- coding: utf-8 -*-
# Copyright (c) Alexei Znamensky (russoz@gmail.com)
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
---
- id: test_simple_property_get
input:
channel: xfwm4
property: /general/inactive_opacity
output:
value: '100'
is_array: false
run_command_calls:
- command: [/testbin/xfconf-query, --channel, xfwm4, --property, /general/inactive_opacity]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: true}
rc: 0
out: "100\n"
err: ""
- id: test_simple_property_get_nonexistent
input:
channel: xfwm4
property: /general/i_dont_exist
output: {}
run_command_calls:
- command: [/testbin/xfconf-query, --channel, xfwm4, --property, /general/i_dont_exist]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: true}
rc: 1
out: ""
err: 'Property "/general/i_dont_exist" does not exist on channel "xfwm4".\n'
- id: test_property_no_channel
input:
property: /general/i_dont_exist
output:
failed: true
msg: "missing parameter(s) required by 'property': channel"
run_command_calls: []
- id: test_property_get_array
input:
channel: xfwm4
property: /general/workspace_names
output:
is_array: true
value_array: [Main, Work, Tmp]
run_command_calls:
- command: [/testbin/xfconf-query, --channel, xfwm4, --property, /general/workspace_names]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: true}
rc: 0
out: "Value is an array with 3 items:\n\nMain\nWork\nTmp\n"
err: ""
- id: get_channels
input: {}
output:
channels: [a, b, c]
run_command_calls:
- command: [/testbin/xfconf-query, --list]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: true}
rc: 0
out: "Channels:\n a\n b\n c\n"
err: ""
- id: get_properties
input:
channel: xfwm4
output:
properties:
- /general/wrap_cycle
- /general/wrap_layout
- /general/wrap_resistance
- /general/wrap_windows
- /general/wrap_workspaces
- /general/zoom_desktop
run_command_calls:
- command: [/testbin/xfconf-query, --list, --channel, xfwm4]
environ: {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: true}
rc: 0
out: |
/general/wrap_cycle
/general/wrap_layout
/general/wrap_resistance
/general/wrap_windows
/general/wrap_workspaces
/general/zoom_desktop
err: ""