mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-05-01 02:43:16 +00:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
98fede2ba0 | ||
|
|
b6b6e0db94 | ||
|
|
f9ad7304ca | ||
|
|
d0fe612858 | ||
|
|
31b7c8aace | ||
|
|
d017b603ce | ||
|
|
55f8456229 | ||
|
|
c4b3c94092 | ||
|
|
ca32d9f925 | ||
|
|
ee6d8cea9d | ||
|
|
6920a247c2 | ||
|
|
bce61ee785 | ||
|
|
8465e87bdc | ||
|
|
f3ef0bc8e1 | ||
|
|
104d98ef02 | ||
|
|
5251c8b075 | ||
|
|
a151726272 |
145
CHANGELOG.md
145
CHANGELOG.md
@@ -2,82 +2,86 @@
|
||||
|
||||
**Topics**
|
||||
|
||||
- <a href="#v8-6-3">v8\.6\.3</a>
|
||||
- <a href="#v8-6-4">v8\.6\.4</a>
|
||||
- <a href="#release-summary">Release Summary</a>
|
||||
- <a href="#minor-changes">Minor Changes</a>
|
||||
- <a href="#bugfixes">Bugfixes</a>
|
||||
- <a href="#v8-6-2">v8\.6\.2</a>
|
||||
- <a href="#v8-6-3">v8\.6\.3</a>
|
||||
- <a href="#release-summary-1">Release Summary</a>
|
||||
- <a href="#minor-changes-1">Minor Changes</a>
|
||||
- <a href="#bugfixes-1">Bugfixes</a>
|
||||
- <a href="#v8-6-2">v8\.6\.2</a>
|
||||
- <a href="#release-summary-2">Release Summary</a>
|
||||
- <a href="#bugfixes-2">Bugfixes</a>
|
||||
- <a href="#known-issues">Known Issues</a>
|
||||
- <a href="#v8-6-1">v8\.6\.1</a>
|
||||
- <a href="#release-summary-2">Release Summary</a>
|
||||
- <a href="#security-fixes">Security Fixes</a>
|
||||
- <a href="#bugfixes-2">Bugfixes</a>
|
||||
- <a href="#v8-6-0">v8\.6\.0</a>
|
||||
- <a href="#release-summary-3">Release Summary</a>
|
||||
- <a href="#minor-changes-1">Minor Changes</a>
|
||||
- <a href="#deprecated-features">Deprecated Features</a>
|
||||
- <a href="#security-fixes">Security Fixes</a>
|
||||
- <a href="#bugfixes-3">Bugfixes</a>
|
||||
- <a href="#new-modules">New Modules</a>
|
||||
- <a href="#v8-5-0">v8\.5\.0</a>
|
||||
- <a href="#v8-6-0">v8\.6\.0</a>
|
||||
- <a href="#release-summary-4">Release Summary</a>
|
||||
- <a href="#minor-changes-2">Minor Changes</a>
|
||||
- <a href="#security-fixes-1">Security Fixes</a>
|
||||
- <a href="#deprecated-features">Deprecated Features</a>
|
||||
- <a href="#bugfixes-4">Bugfixes</a>
|
||||
- <a href="#new-modules-1">New Modules</a>
|
||||
- <a href="#v8-4-0">v8\.4\.0</a>
|
||||
- <a href="#new-modules">New Modules</a>
|
||||
- <a href="#v8-5-0">v8\.5\.0</a>
|
||||
- <a href="#release-summary-5">Release Summary</a>
|
||||
- <a href="#minor-changes-3">Minor Changes</a>
|
||||
- <a href="#security-fixes-1">Security Fixes</a>
|
||||
- <a href="#bugfixes-5">Bugfixes</a>
|
||||
- <a href="#new-modules-1">New Modules</a>
|
||||
- <a href="#v8-4-0">v8\.4\.0</a>
|
||||
- <a href="#release-summary-6">Release Summary</a>
|
||||
- <a href="#minor-changes-4">Minor Changes</a>
|
||||
- <a href="#bugfixes-6">Bugfixes</a>
|
||||
- <a href="#new-plugins">New Plugins</a>
|
||||
- <a href="#callback">Callback</a>
|
||||
- <a href="#filter">Filter</a>
|
||||
- <a href="#new-modules-2">New Modules</a>
|
||||
- <a href="#v8-3-0">v8\.3\.0</a>
|
||||
- <a href="#release-summary-6">Release Summary</a>
|
||||
- <a href="#minor-changes-4">Minor Changes</a>
|
||||
- <a href="#deprecated-features-1">Deprecated Features</a>
|
||||
- <a href="#bugfixes-6">Bugfixes</a>
|
||||
- <a href="#new-modules-3">New Modules</a>
|
||||
- <a href="#v8-2-0">v8\.2\.0</a>
|
||||
- <a href="#release-summary-7">Release Summary</a>
|
||||
- <a href="#minor-changes-5">Minor Changes</a>
|
||||
- <a href="#deprecated-features-1">Deprecated Features</a>
|
||||
- <a href="#bugfixes-7">Bugfixes</a>
|
||||
- <a href="#new-modules-3">New Modules</a>
|
||||
- <a href="#v8-2-0">v8\.2\.0</a>
|
||||
- <a href="#release-summary-8">Release Summary</a>
|
||||
- <a href="#minor-changes-6">Minor Changes</a>
|
||||
- <a href="#bugfixes-8">Bugfixes</a>
|
||||
- <a href="#new-plugins-1">New Plugins</a>
|
||||
- <a href="#connection">Connection</a>
|
||||
- <a href="#filter-1">Filter</a>
|
||||
- <a href="#lookup">Lookup</a>
|
||||
- <a href="#new-modules-4">New Modules</a>
|
||||
- <a href="#v8-1-0">v8\.1\.0</a>
|
||||
- <a href="#release-summary-8">Release Summary</a>
|
||||
- <a href="#minor-changes-6">Minor Changes</a>
|
||||
- <a href="#bugfixes-8">Bugfixes</a>
|
||||
- <a href="#release-summary-9">Release Summary</a>
|
||||
- <a href="#minor-changes-7">Minor Changes</a>
|
||||
- <a href="#bugfixes-9">Bugfixes</a>
|
||||
- <a href="#new-plugins-2">New Plugins</a>
|
||||
- <a href="#lookup-1">Lookup</a>
|
||||
- <a href="#test">Test</a>
|
||||
- <a href="#new-modules-5">New Modules</a>
|
||||
- <a href="#v8-0-2">v8\.0\.2</a>
|
||||
- <a href="#release-summary-9">Release Summary</a>
|
||||
- <a href="#bugfixes-9">Bugfixes</a>
|
||||
- <a href="#v8-0-1">v8\.0\.1</a>
|
||||
- <a href="#release-summary-10">Release Summary</a>
|
||||
- <a href="#bugfixes-10">Bugfixes</a>
|
||||
- <a href="#v8-0-0">v8\.0\.0</a>
|
||||
- <a href="#v8-0-1">v8\.0\.1</a>
|
||||
- <a href="#release-summary-11">Release Summary</a>
|
||||
- <a href="#minor-changes-7">Minor Changes</a>
|
||||
- <a href="#bugfixes-11">Bugfixes</a>
|
||||
- <a href="#v8-0-0">v8\.0\.0</a>
|
||||
- <a href="#release-summary-12">Release Summary</a>
|
||||
- <a href="#minor-changes-8">Minor Changes</a>
|
||||
- <a href="#breaking-changes--porting-guide">Breaking Changes / Porting Guide</a>
|
||||
- <a href="#deprecated-features-2">Deprecated Features</a>
|
||||
- <a href="#removed-features-previously-deprecated">Removed Features \(previously deprecated\)</a>
|
||||
- <a href="#bugfixes-11">Bugfixes</a>
|
||||
- <a href="#bugfixes-12">Bugfixes</a>
|
||||
- <a href="#known-issues-1">Known Issues</a>
|
||||
- <a href="#new-plugins-3">New Plugins</a>
|
||||
- <a href="#lookup-2">Lookup</a>
|
||||
- <a href="#new-modules-6">New Modules</a>
|
||||
This changelog describes changes after version 7\.0\.0\.
|
||||
|
||||
<a id="v8-6-3"></a>
|
||||
## v8\.6\.3
|
||||
<a id="v8-6-4"></a>
|
||||
## v8\.6\.4
|
||||
|
||||
<a id="release-summary"></a>
|
||||
### Release Summary
|
||||
@@ -87,11 +91,32 @@ Regular bugfix release\.
|
||||
<a id="minor-changes"></a>
|
||||
### Minor Changes
|
||||
|
||||
* wdc\_redfish\_command \- minor change to handle upgrade file for Redfish WD platforms \([https\://github\.com/ansible\-collections/community\.general/pull/8444](https\://github\.com/ansible\-collections/community\.general/pull/8444)\)\.
|
||||
* passwordstore lookup plugin \- add the current user to the lockfile file name to address issues on multi\-user systems \([https\://github\.com/ansible\-collections/community\.general/pull/8689](https\://github\.com/ansible\-collections/community\.general/pull/8689)\)\.
|
||||
|
||||
<a id="bugfixes"></a>
|
||||
### Bugfixes
|
||||
|
||||
* gitlab\_runner \- fix <code>paused</code> parameter being ignored \([https\://github\.com/ansible\-collections/community\.general/pull/8648](https\://github\.com/ansible\-collections/community\.general/pull/8648)\)\.
|
||||
* homebrew\_cask \- fix <code>upgrade\_all</code> returns <code>changed</code> when nothing upgraded \([https\://github\.com/ansible\-collections/community\.general/issues/8707](https\://github\.com/ansible\-collections/community\.general/issues/8707)\, [https\://github\.com/ansible\-collections/community\.general/pull/8708](https\://github\.com/ansible\-collections/community\.general/pull/8708)\)\.
|
||||
* keycloak\_user\_federation \- get cleartext IDP <code>clientSecret</code> from full realm info to detect changes to it \([https\://github\.com/ansible\-collections/community\.general/issues/8294](https\://github\.com/ansible\-collections/community\.general/issues/8294)\, [https\://github\.com/ansible\-collections/community\.general/pull/8735](https\://github\.com/ansible\-collections/community\.general/pull/8735)\)\.
|
||||
* keycloak\_user\_federation \- remove existing user federation mappers if they are not present in the federation configuration and will not be updated \([https\://github\.com/ansible\-collections/community\.general/issues/7169](https\://github\.com/ansible\-collections/community\.general/issues/7169)\, [https\://github\.com/ansible\-collections/community\.general/pull/8695](https\://github\.com/ansible\-collections/community\.general/pull/8695)\)\.
|
||||
|
||||
<a id="v8-6-3"></a>
|
||||
## v8\.6\.3
|
||||
|
||||
<a id="release-summary-1"></a>
|
||||
### Release Summary
|
||||
|
||||
Regular bugfix release\.
|
||||
|
||||
<a id="minor-changes-1"></a>
|
||||
### Minor Changes
|
||||
|
||||
* wdc\_redfish\_command \- minor change to handle upgrade file for Redfish WD platforms \([https\://github\.com/ansible\-collections/community\.general/pull/8444](https\://github\.com/ansible\-collections/community\.general/pull/8444)\)\.
|
||||
|
||||
<a id="bugfixes-1"></a>
|
||||
### Bugfixes
|
||||
|
||||
* bitwarden lookup plugin \- fix <code>KeyError</code> in <code>search\_field</code> \([https\://github\.com/ansible\-collections/community\.general/issues/8549](https\://github\.com/ansible\-collections/community\.general/issues/8549)\, [https\://github\.com/ansible\-collections/community\.general/pull/8557](https\://github\.com/ansible\-collections/community\.general/pull/8557)\)\.
|
||||
* keycloak\_clientscope \- remove IDs from clientscope and its protocol mappers on comparison for changed check \([https\://github\.com/ansible\-collections/community\.general/pull/8545](https\://github\.com/ansible\-collections/community\.general/pull/8545)\)\.
|
||||
* nsupdate \- fix \'index out of range\' error when changing NS records by falling back to authority section of the response \([https\://github\.com/ansible\-collections/community\.general/issues/8612](https\://github\.com/ansible\-collections/community\.general/issues/8612)\, [https\://github\.com/ansible\-collections/community\.general/pull/8614](https\://github\.com/ansible\-collections/community\.general/pull/8614)\)\.
|
||||
@@ -100,12 +125,12 @@ Regular bugfix release\.
|
||||
<a id="v8-6-2"></a>
|
||||
## v8\.6\.2
|
||||
|
||||
<a id="release-summary-1"></a>
|
||||
<a id="release-summary-2"></a>
|
||||
### Release Summary
|
||||
|
||||
Regular bugfix release\.
|
||||
|
||||
<a id="bugfixes-1"></a>
|
||||
<a id="bugfixes-2"></a>
|
||||
### Bugfixes
|
||||
|
||||
* git\_config \- fix behavior of <code>state\=absent</code> if <code>value</code> is present \([https\://github\.com/ansible\-collections/community\.general/issues/8436](https\://github\.com/ansible\-collections/community\.general/issues/8436)\, [https\://github\.com/ansible\-collections/community\.general/pull/8452](https\://github\.com/ansible\-collections/community\.general/pull/8452)\)\.
|
||||
@@ -127,7 +152,7 @@ Regular bugfix release\.
|
||||
<a id="v8-6-1"></a>
|
||||
## v8\.6\.1
|
||||
|
||||
<a id="release-summary-2"></a>
|
||||
<a id="release-summary-3"></a>
|
||||
### Release Summary
|
||||
|
||||
Regular bugfix release\.
|
||||
@@ -137,7 +162,7 @@ Regular bugfix release\.
|
||||
|
||||
* keycloak\_identity\_provider \- the client secret was not correctly sanitized by the module\. The return values <code>proposed</code>\, <code>existing</code>\, and <code>end\_state</code>\, as well as the diff\, did contain the client secret unmasked \([https\://github\.com/ansible\-collections/community\.general/pull/8355](https\://github\.com/ansible\-collections/community\.general/pull/8355)\)\.
|
||||
|
||||
<a id="bugfixes-2"></a>
|
||||
<a id="bugfixes-3"></a>
|
||||
### Bugfixes
|
||||
|
||||
* keycloak\_user\_federation \- fix diff of empty <code>krbPrincipalAttribute</code> \([https\://github\.com/ansible\-collections/community\.general/pull/8320](https\://github\.com/ansible\-collections/community\.general/pull/8320)\)\.
|
||||
@@ -148,12 +173,12 @@ Regular bugfix release\.
|
||||
<a id="v8-6-0"></a>
|
||||
## v8\.6\.0
|
||||
|
||||
<a id="release-summary-3"></a>
|
||||
<a id="release-summary-4"></a>
|
||||
### Release Summary
|
||||
|
||||
Regular bugfix and features release\.
|
||||
|
||||
<a id="minor-changes-1"></a>
|
||||
<a id="minor-changes-2"></a>
|
||||
### Minor Changes
|
||||
|
||||
* Use offset\-aware <code>datetime\.datetime</code> objects \(with timezone UTC\) instead of offset\-naive UTC timestamps\, which are deprecated in Python 3\.12 \([https\://github\.com/ansible\-collections/community\.general/pull/8222](https\://github\.com/ansible\-collections/community\.general/pull/8222)\)\.
|
||||
@@ -176,7 +201,7 @@ Regular bugfix and features release\.
|
||||
|
||||
* hipchat callback plugin \- the hipchat service has been discontinued and the self\-hosted variant has been End of Life since 2020\. The callback plugin is therefore deprecated and will be removed from community\.general 10\.0\.0 if nobody provides compelling reasons to still keep it \([https\://github\.com/ansible\-collections/community\.general/issues/8184](https\://github\.com/ansible\-collections/community\.general/issues/8184)\, [https\://github\.com/ansible\-collections/community\.general/pull/8189](https\://github\.com/ansible\-collections/community\.general/pull/8189)\)\.
|
||||
|
||||
<a id="bugfixes-3"></a>
|
||||
<a id="bugfixes-4"></a>
|
||||
### Bugfixes
|
||||
|
||||
* aix\_filesystem \- fix <code>\_validate\_vg</code> not passing VG name to <code>lsvg\_cmd</code> \([https\://github\.com/ansible\-collections/community\.general/issues/8151](https\://github\.com/ansible\-collections/community\.general/issues/8151)\)\.
|
||||
@@ -202,12 +227,12 @@ Regular bugfix and features release\.
|
||||
<a id="v8-5-0"></a>
|
||||
## v8\.5\.0
|
||||
|
||||
<a id="release-summary-4"></a>
|
||||
<a id="release-summary-5"></a>
|
||||
### Release Summary
|
||||
|
||||
Regular feature and bugfix release with security fixes\.
|
||||
|
||||
<a id="minor-changes-2"></a>
|
||||
<a id="minor-changes-3"></a>
|
||||
### Minor Changes
|
||||
|
||||
* bitwarden lookup plugin \- allows to fetch all records of a given collection ID\, by allowing to pass an empty value for <code>search\_value</code> when <code>collection\_id</code> is provided \([https\://github\.com/ansible\-collections/community\.general/pull/8013](https\://github\.com/ansible\-collections/community\.general/pull/8013)\)\.
|
||||
@@ -225,7 +250,7 @@ Regular feature and bugfix release with security fixes\.
|
||||
|
||||
* cobbler\, gitlab\_runners\, icinga2\, linode\, lxd\, nmap\, online\, opennebula\, proxmox\, scaleway\, stackpath\_compute\, virtualbox\, and xen\_orchestra inventory plugin \- make sure all data received from the remote servers is marked as unsafe\, so remote code execution by obtaining texts that can be evaluated as templates is not possible \([https\://www\.die\-welt\.net/2024/03/remote\-code\-execution\-in\-ansible\-dynamic\-inventory\-plugins/](https\://www\.die\-welt\.net/2024/03/remote\-code\-execution\-in\-ansible\-dynamic\-inventory\-plugins/)\, [https\://github\.com/ansible\-collections/community\.general/pull/8098](https\://github\.com/ansible\-collections/community\.general/pull/8098)\)\.
|
||||
|
||||
<a id="bugfixes-4"></a>
|
||||
<a id="bugfixes-5"></a>
|
||||
### Bugfixes
|
||||
|
||||
* aix\_filesystem \- fix issue with empty list items in crfs logic and option order \([https\://github\.com/ansible\-collections/community\.general/pull/8052](https\://github\.com/ansible\-collections/community\.general/pull/8052)\)\.
|
||||
@@ -247,12 +272,12 @@ Regular feature and bugfix release with security fixes\.
|
||||
<a id="v8-4-0"></a>
|
||||
## v8\.4\.0
|
||||
|
||||
<a id="release-summary-5"></a>
|
||||
<a id="release-summary-6"></a>
|
||||
### Release Summary
|
||||
|
||||
Regular bugfix and feature release\.
|
||||
|
||||
<a id="minor-changes-3"></a>
|
||||
<a id="minor-changes-4"></a>
|
||||
### Minor Changes
|
||||
|
||||
* bitwarden lookup plugin \- add <code>bw\_session</code> option\, to pass session key instead of reading from env \([https\://github\.com/ansible\-collections/community\.general/pull/7994](https\://github\.com/ansible\-collections/community\.general/pull/7994)\)\.
|
||||
@@ -265,7 +290,7 @@ Regular bugfix and feature release\.
|
||||
* sudoers \- add support for the <code>NOEXEC</code> tag in sudoers rules \([https\://github\.com/ansible\-collections/community\.general/pull/7983](https\://github\.com/ansible\-collections/community\.general/pull/7983)\)\.
|
||||
* terraform \- fix <code>diff\_mode</code> in state <code>absent</code> and when terraform <code>resource\_changes</code> does not exist \([https\://github\.com/ansible\-collections/community\.general/pull/7963](https\://github\.com/ansible\-collections/community\.general/pull/7963)\)\.
|
||||
|
||||
<a id="bugfixes-5"></a>
|
||||
<a id="bugfixes-6"></a>
|
||||
### Bugfixes
|
||||
|
||||
* cargo \- fix idempotency issues when using a custom installation path for packages \(using the <code>\-\-path</code> parameter\)\. The initial installation runs fine\, but subsequent runs use the <code>get\_installed\(\)</code> function which did not check the given installation location\, before running <code>cargo install</code>\. This resulted in a false <code>changed</code> state\. Also the removal of packeges using <code>state\: absent</code> failed\, as the installation check did not use the given parameter \([https\://github\.com/ansible\-collections/community\.general/pull/7970](https\://github\.com/ansible\-collections/community\.general/pull/7970)\)\.
|
||||
@@ -303,12 +328,12 @@ Regular bugfix and feature release\.
|
||||
<a id="v8-3-0"></a>
|
||||
## v8\.3\.0
|
||||
|
||||
<a id="release-summary-6"></a>
|
||||
<a id="release-summary-7"></a>
|
||||
### Release Summary
|
||||
|
||||
Regular bugfix and feature release\.
|
||||
|
||||
<a id="minor-changes-4"></a>
|
||||
<a id="minor-changes-5"></a>
|
||||
### Minor Changes
|
||||
|
||||
* consul\_auth\_method\, consul\_binding\_rule\, consul\_policy\, consul\_role\, consul\_session\, consul\_token \- added action group <code>community\.general\.consul</code> \([https\://github\.com/ansible\-collections/community\.general/pull/7897](https\://github\.com/ansible\-collections/community\.general/pull/7897)\)\.
|
||||
@@ -326,7 +351,7 @@ Regular bugfix and feature release\.
|
||||
|
||||
* consul\_acl \- the module has been deprecated and will be removed in community\.general 10\.0\.0\. <code>consul\_token</code> and <code>consul\_policy</code> can be used instead \([https\://github\.com/ansible\-collections/community\.general/pull/7901](https\://github\.com/ansible\-collections/community\.general/pull/7901)\)\.
|
||||
|
||||
<a id="bugfixes-6"></a>
|
||||
<a id="bugfixes-7"></a>
|
||||
### Bugfixes
|
||||
|
||||
* homebrew \- detect already installed formulae and casks using JSON output from <code>brew info</code> \([https\://github\.com/ansible\-collections/community\.general/issues/864](https\://github\.com/ansible\-collections/community\.general/issues/864)\)\.
|
||||
@@ -350,12 +375,12 @@ Regular bugfix and feature release\.
|
||||
<a id="v8-2-0"></a>
|
||||
## v8\.2\.0
|
||||
|
||||
<a id="release-summary-7"></a>
|
||||
<a id="release-summary-8"></a>
|
||||
### Release Summary
|
||||
|
||||
Regular bugfix and feature release\.
|
||||
|
||||
<a id="minor-changes-5"></a>
|
||||
<a id="minor-changes-6"></a>
|
||||
### Minor Changes
|
||||
|
||||
* ipa\_dnsrecord \- adds ability to manage NS record types \([https\://github\.com/ansible\-collections/community\.general/pull/7737](https\://github\.com/ansible\-collections/community\.general/pull/7737)\)\.
|
||||
@@ -371,7 +396,7 @@ Regular bugfix and feature release\.
|
||||
* ssh\_config \- new feature to set <code>IdentitiesOnly</code> option to <code>yes</code> or <code>no</code> \([https\://github\.com/ansible\-collections/community\.general/pull/7704](https\://github\.com/ansible\-collections/community\.general/pull/7704)\)\.
|
||||
* xcc\_redfish\_command \- added support for raw POSTs \(<code>command\=PostResource</code> in <code>category\=Raw</code>\) without a specific action info \([https\://github\.com/ansible\-collections/community\.general/pull/7746](https\://github\.com/ansible\-collections/community\.general/pull/7746)\)\.
|
||||
|
||||
<a id="bugfixes-7"></a>
|
||||
<a id="bugfixes-8"></a>
|
||||
### Bugfixes
|
||||
|
||||
* keycloak\_identity\_provider \- <code>mappers</code> processing was not idempotent if the mappers configuration list had not been sorted by name \(in ascending order\)\. Fix resolves the issue by sorting mappers in the desired state using the same key which is used for obtaining existing state \([https\://github\.com/ansible\-collections/community\.general/pull/7418](https\://github\.com/ansible\-collections/community\.general/pull/7418)\)\.
|
||||
@@ -411,12 +436,12 @@ Regular bugfix and feature release\.
|
||||
<a id="v8-1-0"></a>
|
||||
## v8\.1\.0
|
||||
|
||||
<a id="release-summary-8"></a>
|
||||
<a id="release-summary-9"></a>
|
||||
### Release Summary
|
||||
|
||||
Regular bugfix and feature release\.
|
||||
|
||||
<a id="minor-changes-6"></a>
|
||||
<a id="minor-changes-7"></a>
|
||||
### Minor Changes
|
||||
|
||||
* bitwarden lookup plugin \- when looking for items using an item ID\, the item is now accessed directly with <code>bw get item</code> instead of searching through all items\. This doubles the lookup speed \([https\://github\.com/ansible\-collections/community\.general/pull/7468](https\://github\.com/ansible\-collections/community\.general/pull/7468)\)\.
|
||||
@@ -453,7 +478,7 @@ Regular bugfix and feature release\.
|
||||
* redfish\_info \- adding the <code>BootProgress</code> property when getting <code>Systems</code> info \([https\://github\.com/ansible\-collections/community\.general/pull/7626](https\://github\.com/ansible\-collections/community\.general/pull/7626)\)\.
|
||||
* ssh\_config \- adds <code>controlmaster</code>\, <code>controlpath</code> and <code>controlpersist</code> parameters \([https\://github\.com/ansible\-collections/community\.general/pull/7456](https\://github\.com/ansible\-collections/community\.general/pull/7456)\)\.
|
||||
|
||||
<a id="bugfixes-8"></a>
|
||||
<a id="bugfixes-9"></a>
|
||||
### Bugfixes
|
||||
|
||||
* apt\-rpm \- the module did not upgrade packages if a newer version exists\. Now the package will be reinstalled if the candidate is newer than the installed version \([https\://github\.com/ansible\-collections/community\.general/issues/7414](https\://github\.com/ansible\-collections/community\.general/issues/7414)\)\.
|
||||
@@ -494,12 +519,12 @@ Regular bugfix and feature release\.
|
||||
<a id="v8-0-2"></a>
|
||||
## v8\.0\.2
|
||||
|
||||
<a id="release-summary-9"></a>
|
||||
<a id="release-summary-10"></a>
|
||||
### Release Summary
|
||||
|
||||
Bugfix release for inclusion in Ansible 9\.0\.0rc1\.
|
||||
|
||||
<a id="bugfixes-9"></a>
|
||||
<a id="bugfixes-10"></a>
|
||||
### Bugfixes
|
||||
|
||||
* ocapi\_utils\, oci\_utils\, redfish\_utils module utils \- replace <code>type\(\)</code> calls with <code>isinstance\(\)</code> calls \([https\://github\.com/ansible\-collections/community\.general/pull/7501](https\://github\.com/ansible\-collections/community\.general/pull/7501)\)\.
|
||||
@@ -508,12 +533,12 @@ Bugfix release for inclusion in Ansible 9\.0\.0rc1\.
|
||||
<a id="v8-0-1"></a>
|
||||
## v8\.0\.1
|
||||
|
||||
<a id="release-summary-10"></a>
|
||||
<a id="release-summary-11"></a>
|
||||
### Release Summary
|
||||
|
||||
Bugfix release for inclusion in Ansible 9\.0\.0b1\.
|
||||
|
||||
<a id="bugfixes-10"></a>
|
||||
<a id="bugfixes-11"></a>
|
||||
### Bugfixes
|
||||
|
||||
* gitlab\_group\_members \- fix gitlab constants call in <code>gitlab\_group\_members</code> module \([https\://github\.com/ansible\-collections/community\.general/issues/7467](https\://github\.com/ansible\-collections/community\.general/issues/7467)\)\.
|
||||
@@ -526,12 +551,12 @@ Bugfix release for inclusion in Ansible 9\.0\.0b1\.
|
||||
<a id="v8-0-0"></a>
|
||||
## v8\.0\.0
|
||||
|
||||
<a id="release-summary-11"></a>
|
||||
<a id="release-summary-12"></a>
|
||||
### Release Summary
|
||||
|
||||
This is release 8\.0\.0 of <code>community\.general</code>\, released on 2023\-11\-01\.
|
||||
|
||||
<a id="minor-changes-7"></a>
|
||||
<a id="minor-changes-8"></a>
|
||||
### Minor Changes
|
||||
|
||||
* The collection will start using semantic markup \([https\://github\.com/ansible\-collections/community\.general/pull/6539](https\://github\.com/ansible\-collections/community\.general/pull/6539)\)\.
|
||||
@@ -730,7 +755,7 @@ This is release 8\.0\.0 of <code>community\.general</code>\, released on 2023\-1
|
||||
* proxmox module utils \- removed unused imports \([https\://github\.com/ansible\-collections/community\.general/pull/6873](https\://github\.com/ansible\-collections/community\.general/pull/6873)\)\.
|
||||
* xfconf \- the deprecated <code>disable\_facts</code> option was removed \([https\://github\.com/ansible\-collections/community\.general/pull/7358](https\://github\.com/ansible\-collections/community\.general/pull/7358)\)\.
|
||||
|
||||
<a id="bugfixes-11"></a>
|
||||
<a id="bugfixes-12"></a>
|
||||
### 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](https\://github\.com/ansible\-collections/community\.general/pull/7200)\)\.
|
||||
|
||||
@@ -6,6 +6,27 @@ Community General Release Notes
|
||||
|
||||
This changelog describes changes after version 7.0.0.
|
||||
|
||||
v8.6.4
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Regular bugfix release.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- passwordstore lookup plugin - add the current user to the lockfile file name to address issues on multi-user systems (https://github.com/ansible-collections/community.general/pull/8689).
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- gitlab_runner - fix ``paused`` parameter being ignored (https://github.com/ansible-collections/community.general/pull/8648).
|
||||
- homebrew_cask - fix ``upgrade_all`` returns ``changed`` when nothing upgraded (https://github.com/ansible-collections/community.general/issues/8707, https://github.com/ansible-collections/community.general/pull/8708).
|
||||
- keycloak_user_federation - get cleartext IDP ``clientSecret`` from full realm info to detect changes to it (https://github.com/ansible-collections/community.general/issues/8294, https://github.com/ansible-collections/community.general/pull/8735).
|
||||
- keycloak_user_federation - remove existing user federation mappers if they are not present in the federation configuration and will not be updated (https://github.com/ansible-collections/community.general/issues/7169, https://github.com/ansible-collections/community.general/pull/8695).
|
||||
|
||||
v8.6.3
|
||||
======
|
||||
|
||||
|
||||
@@ -56,6 +56,8 @@ cd ~/dev/ansible_collections/community/general
|
||||
|
||||
Then you can run `ansible-test` (which is a part of [ansible-core](https://pypi.org/project/ansible-core/)) inside the checkout. The following example commands expect that you have installed Docker or Podman. Note that Podman has only been supported by more recent ansible-core releases. If you are using Docker, the following will work with Ansible 2.9+.
|
||||
|
||||
### Sanity tests
|
||||
|
||||
The following commands show how to run sanity tests:
|
||||
|
||||
```.bash
|
||||
@@ -66,6 +68,8 @@ ansible-test sanity --docker -v
|
||||
ansible-test sanity --docker -v plugins/modules/system/pids.py tests/integration/targets/pids/
|
||||
```
|
||||
|
||||
### Unit tests
|
||||
|
||||
The following commands show how to run unit tests:
|
||||
|
||||
```.bash
|
||||
@@ -79,13 +83,32 @@ ansible-test units --docker -v --python 3.8
|
||||
ansible-test units --docker -v --python 3.8 tests/unit/plugins/modules/net_tools/test_nmcli.py
|
||||
```
|
||||
|
||||
### Integration tests
|
||||
|
||||
The following commands show how to run integration tests:
|
||||
|
||||
```.bash
|
||||
# Run integration tests for the interfaces_files module in a Docker container using the
|
||||
# fedora35 operating system image (the supported images depend on your ansible-core version):
|
||||
ansible-test integration --docker fedora35 -v interfaces_file
|
||||
#### In Docker
|
||||
|
||||
Integration tests on Docker have the following parameters:
|
||||
- `image_name` (required): The name of the Docker image. To get the list of supported Docker images, run
|
||||
`ansible-test integration --help` and look for _target docker images_.
|
||||
- `test_name` (optional): The name of the integration test.
|
||||
For modules, this equals the short name of the module; for example, `pacman` in case of `community.general.pacman`.
|
||||
For plugins, the plugin type is added before the plugin's short name, for example `callback_yaml` for the `community.general.yaml` callback.
|
||||
```.bash
|
||||
# Test all plugins/modules on fedora40
|
||||
ansible-test integration -v --docker fedora40
|
||||
|
||||
# Template
|
||||
ansible-test integration -v --docker image_name test_name
|
||||
|
||||
# Example community.general.ini_file module on fedora40 Docker image:
|
||||
ansible-test integration -v --docker fedora40 ini_file
|
||||
```
|
||||
|
||||
#### Without isolation
|
||||
|
||||
```.bash
|
||||
# Run integration tests for the flattened lookup **without any isolation**:
|
||||
ansible-test integration -v lookup_flattened
|
||||
```
|
||||
|
||||
@@ -1541,3 +1541,27 @@ releases:
|
||||
- 8613-redfish_utils-language.yaml
|
||||
- 8614-nsupdate-index-out-of-range.yml
|
||||
release_date: '2024-07-14'
|
||||
8.6.4:
|
||||
changes:
|
||||
bugfixes:
|
||||
- gitlab_runner - fix ``paused`` parameter being ignored (https://github.com/ansible-collections/community.general/pull/8648).
|
||||
- homebrew_cask - fix ``upgrade_all`` returns ``changed`` when nothing upgraded
|
||||
(https://github.com/ansible-collections/community.general/issues/8707, https://github.com/ansible-collections/community.general/pull/8708).
|
||||
- keycloak_user_federation - get cleartext IDP ``clientSecret`` from full
|
||||
realm info to detect changes to it (https://github.com/ansible-collections/community.general/issues/8294,
|
||||
https://github.com/ansible-collections/community.general/pull/8735).
|
||||
- keycloak_user_federation - remove existing user federation mappers if they
|
||||
are not present in the federation configuration and will not be updated
|
||||
(https://github.com/ansible-collections/community.general/issues/7169, https://github.com/ansible-collections/community.general/pull/8695).
|
||||
minor_changes:
|
||||
- passwordstore lookup plugin - add the current user to the lockfile file
|
||||
name to address issues on multi-user systems (https://github.com/ansible-collections/community.general/pull/8689).
|
||||
release_summary: Regular bugfix release.
|
||||
fragments:
|
||||
- 8.6.4.yml
|
||||
- 8648-fix-gitlab-runner-paused.yaml
|
||||
- 8689-passwordstore-lock-naming.yml
|
||||
- 8695-keycloak_user_federation-mapper-removal.yml
|
||||
- 8708-homebrew_cask-fix-upgrade-all.yml
|
||||
- 8735-keycloak_identity_provider-get-cleartext-secret-from-realm-info.yml
|
||||
release_date: '2024-08-12'
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
namespace: community
|
||||
name: general
|
||||
version: 8.6.3
|
||||
version: 8.6.4
|
||||
readme: README.md
|
||||
authors:
|
||||
- Ansible (https://github.com/ansible)
|
||||
|
||||
@@ -88,6 +88,10 @@ class ActionModule(ActionBase):
|
||||
max_timeout = self._connection._play_context.timeout
|
||||
module_args = self._task.args
|
||||
|
||||
async_status_args = {}
|
||||
starter_cmd = None
|
||||
confirm_cmd = None
|
||||
|
||||
if module_args.get('state', None) == 'restored':
|
||||
if not wrap_async:
|
||||
if not check_mode:
|
||||
|
||||
@@ -304,6 +304,7 @@ class OpenTelemetrySource(object):
|
||||
status = Status(status_code=StatusCode.OK)
|
||||
if host_data.status != 'included':
|
||||
# Support loops
|
||||
enriched_error_message = None
|
||||
if 'results' in host_data.result._result:
|
||||
if host_data.status == 'failed':
|
||||
message = self.get_error_message_from_results(host_data.result._result['results'], task_data.action)
|
||||
|
||||
@@ -468,7 +468,8 @@ class LookupModule(LookupBase):
|
||||
def opt_lock(self, type):
|
||||
if self.get_option('lock') == type:
|
||||
tmpdir = os.environ.get('TMPDIR', '/tmp')
|
||||
lockfile = os.path.join(tmpdir, '.passwordstore.lock')
|
||||
user = os.environ.get('USER')
|
||||
lockfile = os.path.join(tmpdir, '.{0}.passwordstore.lock'.format(user))
|
||||
with FileLock().lock_file(lockfile, tmpdir, self.lock_timeout):
|
||||
self.locked = type
|
||||
yield
|
||||
|
||||
@@ -29,6 +29,7 @@ class iLORedfishUtils(RedfishUtils):
|
||||
result['ret'] = True
|
||||
data = response['data']
|
||||
|
||||
current_session = None
|
||||
if 'Oem' in data:
|
||||
if data["Oem"]["Hpe"]["Links"]["MySession"]["@odata.id"]:
|
||||
current_session = data["Oem"]["Hpe"]["Links"]["MySession"]["@odata.id"]
|
||||
|
||||
@@ -192,6 +192,7 @@ def main():
|
||||
rmitab = module.get_bin_path('rmitab')
|
||||
chitab = module.get_bin_path('chitab')
|
||||
rc = 0
|
||||
err = None
|
||||
|
||||
# check if the new entry exists
|
||||
current_entry = check_current_entry(module)
|
||||
|
||||
@@ -183,6 +183,7 @@ class CronVar(object):
|
||||
fileh = open(backup_file, 'w')
|
||||
elif self.cron_file:
|
||||
fileh = open(self.cron_file, 'w')
|
||||
path = None
|
||||
else:
|
||||
filed, path = tempfile.mkstemp(prefix='crontab')
|
||||
fileh = os.fdopen(filed, 'w')
|
||||
|
||||
@@ -466,6 +466,7 @@ def main():
|
||||
state = module.params['state']
|
||||
runner_description = module.params['description']
|
||||
runner_active = module.params['active']
|
||||
runner_paused = module.params['paused']
|
||||
tag_list = module.params['tag_list']
|
||||
run_untagged = module.params['run_untagged']
|
||||
runner_locked = module.params['locked']
|
||||
@@ -500,7 +501,7 @@ def main():
|
||||
module.exit_json(changed=False, msg="Runner deleted or does not exists")
|
||||
|
||||
if state == 'present':
|
||||
if gitlab_runner.create_or_update_runner(runner_description, {
|
||||
runner_values = {
|
||||
"active": runner_active,
|
||||
"tag_list": tag_list,
|
||||
"run_untagged": run_untagged,
|
||||
@@ -510,7 +511,11 @@ def main():
|
||||
"registration_token": registration_token,
|
||||
"group": group,
|
||||
"project": project,
|
||||
}):
|
||||
}
|
||||
if LooseVersion(gitlab_runner._gitlab.version()[0]) >= LooseVersion("14.8.0"):
|
||||
# the paused attribute for runners is available since 14.8
|
||||
runner_values["paused"] = runner_paused
|
||||
if gitlab_runner.create_or_update_runner(runner_description, runner_values):
|
||||
module.exit_json(changed=True, runner=gitlab_runner.runner_object._attrs,
|
||||
msg="Successfully created or updated the runner %s" % runner_description)
|
||||
else:
|
||||
|
||||
@@ -598,7 +598,12 @@ class HomebrewCask(object):
|
||||
rc, out, err = self.module.run_command(cmd)
|
||||
|
||||
if rc == 0:
|
||||
if re.search(r'==> No Casks to upgrade', out.strip(), re.IGNORECASE):
|
||||
# 'brew upgrade --cask' does not output anything if no casks are upgraded
|
||||
if not out.strip():
|
||||
self.message = 'Homebrew casks already upgraded.'
|
||||
|
||||
# handle legacy 'brew cask upgrade'
|
||||
elif re.search(r'==> No Casks to upgrade', out.strip(), re.IGNORECASE):
|
||||
self.message = 'Homebrew casks already upgraded.'
|
||||
|
||||
else:
|
||||
|
||||
@@ -459,6 +459,7 @@ def main():
|
||||
if not os.access(b_path, os.R_OK):
|
||||
module.fail_json(msg="Source %s not readable" % path)
|
||||
state_to_restore = read_state(b_path)
|
||||
cmd = None
|
||||
else:
|
||||
cmd = ' '.join(SAVECOMMAND)
|
||||
|
||||
|
||||
@@ -445,6 +445,15 @@ def get_identity_provider_with_mappers(kc, alias, realm):
|
||||
idp = kc.get_identity_provider(alias, realm)
|
||||
if idp is not None:
|
||||
idp['mappers'] = sorted(kc.get_identity_provider_mappers(alias, realm), key=lambda x: x.get('name'))
|
||||
# clientSecret returned by API when using `get_identity_provider(alias, realm)` is always **********
|
||||
# to detect changes to the secret, we get the actual cleartext secret from the full realm info
|
||||
if 'config' in idp:
|
||||
if 'clientSecret' in idp['config']:
|
||||
for idp_from_realm in kc.get_realm_by_id(realm).get('identityProviders', []):
|
||||
if idp_from_realm['internalId'] == idp['internalId']:
|
||||
cleartext_secret = idp_from_realm.get('config', {}).get('clientSecret')
|
||||
if cleartext_secret:
|
||||
idp['config']['clientSecret'] = cleartext_secret
|
||||
if idp is None:
|
||||
idp = {}
|
||||
return idp
|
||||
|
||||
@@ -892,11 +892,11 @@ def main():
|
||||
if cid is None:
|
||||
old_mapper = {}
|
||||
elif change.get('id') is not None:
|
||||
old_mapper = kc.get_component(change['id'], realm)
|
||||
old_mapper = next((before_mapper for before_mapper in before_mapper.get('mappers', []) if before_mapper["id"] == change['id']), None)
|
||||
if old_mapper is None:
|
||||
old_mapper = {}
|
||||
else:
|
||||
found = kc.get_components(urlencode(dict(parent=cid, name=change['name'])), realm)
|
||||
found = [before_mapper for before_mapper in before_comp.get('mappers', []) if before_mapper['name'] == change['name']]
|
||||
if len(found) > 1:
|
||||
module.fail_json(msg='Found multiple mappers with name `{name}`. Cannot continue.'.format(name=change['name']))
|
||||
if len(found) == 1:
|
||||
@@ -905,10 +905,10 @@ def main():
|
||||
old_mapper = {}
|
||||
new_mapper = old_mapper.copy()
|
||||
new_mapper.update(change)
|
||||
if new_mapper != old_mapper:
|
||||
if changeset.get('mappers') is None:
|
||||
changeset['mappers'] = list()
|
||||
changeset['mappers'].append(new_mapper)
|
||||
# changeset contains all desired mappers: those existing, to update or to create
|
||||
if changeset.get('mappers') is None:
|
||||
changeset['mappers'] = list()
|
||||
changeset['mappers'].append(new_mapper)
|
||||
|
||||
# Prepare the desired values using the existing values (non-existence results in a dict that is save to use as a basis)
|
||||
desired_comp = before_comp.copy()
|
||||
@@ -931,42 +931,51 @@ def main():
|
||||
# Process a creation
|
||||
result['changed'] = True
|
||||
|
||||
if module._diff:
|
||||
result['diff'] = dict(before='', after=sanitize(desired_comp))
|
||||
|
||||
if module.check_mode:
|
||||
if module._diff:
|
||||
result['diff'] = dict(before='', after=sanitize(desired_comp))
|
||||
module.exit_json(**result)
|
||||
|
||||
# create it
|
||||
desired_comp = desired_comp.copy()
|
||||
updated_mappers = desired_comp.pop('mappers', [])
|
||||
desired_mappers = desired_comp.pop('mappers', [])
|
||||
after_comp = kc.create_component(desired_comp, realm)
|
||||
|
||||
cid = after_comp['id']
|
||||
updated_mappers = []
|
||||
# when creating a user federation, keycloak automatically creates default mappers
|
||||
default_mappers = kc.get_components(urlencode(dict(parent=cid)), realm)
|
||||
|
||||
for mapper in updated_mappers:
|
||||
found = kc.get_components(urlencode(dict(parent=cid, name=mapper['name'])), realm)
|
||||
# create new mappers or update existing default mappers
|
||||
for desired_mapper in desired_mappers:
|
||||
found = [default_mapper for default_mapper in default_mappers if default_mapper['name'] == desired_mapper['name']]
|
||||
if len(found) > 1:
|
||||
module.fail_json(msg='Found multiple mappers with name `{name}`. Cannot continue.'.format(name=mapper['name']))
|
||||
module.fail_json(msg='Found multiple mappers with name `{name}`. Cannot continue.'.format(name=desired_mapper['name']))
|
||||
if len(found) == 1:
|
||||
old_mapper = found[0]
|
||||
else:
|
||||
old_mapper = {}
|
||||
|
||||
new_mapper = old_mapper.copy()
|
||||
new_mapper.update(mapper)
|
||||
new_mapper.update(desired_mapper)
|
||||
|
||||
if new_mapper.get('id') is not None:
|
||||
kc.update_component(new_mapper, realm)
|
||||
updated_mappers.append(new_mapper)
|
||||
else:
|
||||
if new_mapper.get('parentId') is None:
|
||||
new_mapper['parentId'] = after_comp['id']
|
||||
mapper = kc.create_component(new_mapper, realm)
|
||||
new_mapper['parentId'] = cid
|
||||
updated_mappers.append(kc.create_component(new_mapper, realm))
|
||||
|
||||
after_comp['mappers'] = updated_mappers
|
||||
# we remove all unwanted default mappers
|
||||
# we use ids so we dont accidently remove one of the previously updated default mapper
|
||||
for default_mapper in default_mappers:
|
||||
if not default_mapper['id'] in [x['id'] for x in updated_mappers]:
|
||||
kc.delete_component(default_mapper['id'], realm)
|
||||
|
||||
after_comp['mappers'] = kc.get_components(urlencode(dict(parent=cid)), realm)
|
||||
if module._diff:
|
||||
result['diff'] = dict(before='', after=sanitize(after_comp))
|
||||
result['end_state'] = sanitize(after_comp)
|
||||
|
||||
result['msg'] = "User federation {id} has been created".format(id=after_comp['id'])
|
||||
result['msg'] = "User federation {id} has been created".format(id=cid)
|
||||
module.exit_json(**result)
|
||||
|
||||
else:
|
||||
@@ -990,22 +999,32 @@ def main():
|
||||
module.exit_json(**result)
|
||||
|
||||
# do the update
|
||||
desired_comp = desired_comp.copy()
|
||||
updated_mappers = desired_comp.pop('mappers', [])
|
||||
desired_mappers = desired_comp.pop('mappers', [])
|
||||
kc.update_component(desired_comp, realm)
|
||||
after_comp = kc.get_component(cid, realm)
|
||||
|
||||
for mapper in updated_mappers:
|
||||
for before_mapper in before_comp.get('mappers', []):
|
||||
# remove unwanted existing mappers that will not be updated
|
||||
if not before_mapper['id'] in [x['id'] for x in desired_mappers]:
|
||||
kc.delete_component(before_mapper['id'], realm)
|
||||
|
||||
for mapper in desired_mappers:
|
||||
if mapper in before_comp.get('mappers', []):
|
||||
continue
|
||||
if mapper.get('id') is not None:
|
||||
kc.update_component(mapper, realm)
|
||||
else:
|
||||
if mapper.get('parentId') is None:
|
||||
mapper['parentId'] = desired_comp['id']
|
||||
mapper = kc.create_component(mapper, realm)
|
||||
|
||||
after_comp['mappers'] = updated_mappers
|
||||
result['end_state'] = sanitize(after_comp)
|
||||
kc.create_component(mapper, realm)
|
||||
|
||||
after_comp = kc.get_component(cid, realm)
|
||||
after_comp['mappers'] = kc.get_components(urlencode(dict(parent=cid)), realm)
|
||||
after_comp_sanitized = sanitize(after_comp)
|
||||
before_comp_sanitized = sanitize(before_comp)
|
||||
result['end_state'] = after_comp_sanitized
|
||||
if module._diff:
|
||||
result['diff'] = dict(before=before_comp_sanitized, after=after_comp_sanitized)
|
||||
result['changed'] = before_comp_sanitized != after_comp_sanitized
|
||||
result['msg'] = "User federation {id} has been updated".format(id=cid)
|
||||
module.exit_json(**result)
|
||||
|
||||
|
||||
@@ -181,6 +181,7 @@ def api_validation(args=None):
|
||||
https://www.memset.com/apidocs/methods_dns.html#dns.zone_record_create)
|
||||
'''
|
||||
failed_validation = False
|
||||
error = None
|
||||
|
||||
# priority can only be integer 0 > 999
|
||||
if not 0 <= args['priority'] <= 999:
|
||||
|
||||
@@ -27,6 +27,7 @@ options:
|
||||
type: list
|
||||
elements: path
|
||||
requirements:
|
||||
- pip >= 20.3b1 (necessary for the C(--format) option)
|
||||
- The requested pip executables must be installed on the target.
|
||||
author:
|
||||
- Matthew Jones (@matburt)
|
||||
|
||||
@@ -326,7 +326,8 @@ EXAMPLES = r'''
|
||||
password: 123456
|
||||
hostname: example.org
|
||||
ostemplate: 'local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
|
||||
netif: '{"net0":"name=eth0,ip=dhcp,ip6=dhcp,bridge=vmbr0"}'
|
||||
netif:
|
||||
net0: "name=eth0,ip=dhcp,ip6=dhcp,bridge=vmbr0"
|
||||
|
||||
- name: Create new container with minimal options defining network interface with static ip
|
||||
community.general.proxmox:
|
||||
@@ -338,7 +339,21 @@ EXAMPLES = r'''
|
||||
password: 123456
|
||||
hostname: example.org
|
||||
ostemplate: 'local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
|
||||
netif: '{"net0":"name=eth0,gw=192.168.0.1,ip=192.168.0.2/24,bridge=vmbr0"}'
|
||||
netif:
|
||||
net0: "name=eth0,gw=192.168.0.1,ip=192.168.0.2/24,bridge=vmbr0"
|
||||
|
||||
- name: Create new container with more options defining network interface with static ip4 and ip6 with vlan-tag and mtu
|
||||
community.general.proxmox:
|
||||
vmid: 100
|
||||
node: uk-mc02
|
||||
api_user: root@pam
|
||||
api_password: 1q2w3e
|
||||
api_host: node1
|
||||
password: 123456
|
||||
hostname: example.org
|
||||
ostemplate: 'local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
|
||||
netif:
|
||||
net0: "name=eth0,gw=192.168.0.1,ip=192.168.0.2/24,ip6=fe80::1227/64,gw6=fe80::1,bridge=vmbr0,firewall=1,tag=934,mtu=1500"
|
||||
|
||||
- name: Create new container with minimal options defining a mount with 8GB
|
||||
community.general.proxmox:
|
||||
@@ -350,7 +365,8 @@ EXAMPLES = r'''
|
||||
password: 123456
|
||||
hostname: example.org
|
||||
ostemplate: 'local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
|
||||
mounts: '{"mp0":"local:8,mp=/mnt/test/"}'
|
||||
mounts:
|
||||
mp0: "local:8,mp=/mnt/test/"
|
||||
|
||||
- name: Create new container with minimal options defining a cpu core limit
|
||||
community.general.proxmox:
|
||||
@@ -420,7 +436,8 @@ EXAMPLES = r'''
|
||||
api_user: root@pam
|
||||
api_password: 1q2w3e
|
||||
api_host: node1
|
||||
netif: '{"net0":"name=eth0,gw=192.168.0.1,ip=192.168.0.3/24,bridge=vmbr0"}'
|
||||
netif:
|
||||
net0: "name=eth0,gw=192.168.0.1,ip=192.168.0.3/24,bridge=vmbr0"
|
||||
update: true
|
||||
|
||||
- name: Start container
|
||||
|
||||
@@ -541,6 +541,7 @@ class ProxmoxDiskAnsible(ProxmoxAnsible):
|
||||
# NOOP
|
||||
return False, "Disk %s not found in VM %s and creation was disabled in parameters." % (disk, vmid)
|
||||
|
||||
timeout_str = "Reached timeout. Last line in task before timeout: %s"
|
||||
if (create == 'regular' and disk not in vm_config) or (create == 'forced'):
|
||||
# CREATE
|
||||
playbook_config = self.get_create_attributes()
|
||||
|
||||
@@ -307,6 +307,8 @@ def main():
|
||||
if m_args['community'] is None:
|
||||
module.fail_json(msg='Community not set when using snmp version 2')
|
||||
|
||||
integrity_proto = None
|
||||
privacy_proto = None
|
||||
if m_args['version'] == "v3":
|
||||
if m_args['username'] is None:
|
||||
module.fail_json(msg='Username not set when using snmp version 3')
|
||||
|
||||
@@ -49,7 +49,8 @@ options:
|
||||
aliases: [ rtc ]
|
||||
choices: [ local, UTC ]
|
||||
notes:
|
||||
- On SmartOS the C(sm-set-timezone) utility (part of the smtools package) is required to set the zone timezone
|
||||
- On Ubuntu 24.04 the C(util-linux-extra) package is required to provide the C(hwclock) command.
|
||||
- On SmartOS the C(sm-set-timezone) utility (part of the smtools package) is required to set the zone timezone.
|
||||
- On AIX only Olson/tz database timezones are usable (POSIX is not supported).
|
||||
An OS reboot is also required on AIX for the new timezone setting to take effect.
|
||||
Note that AIX 6.1+ is needed (OS level 61 or newer).
|
||||
@@ -75,6 +76,7 @@ diff:
|
||||
|
||||
EXAMPLES = r'''
|
||||
- name: Set timezone to Asia/Tokyo
|
||||
become: true
|
||||
community.general.timezone:
|
||||
name: Asia/Tokyo
|
||||
'''
|
||||
|
||||
@@ -5,3 +5,4 @@
|
||||
|
||||
dependencies:
|
||||
- setup_pkg_mgr
|
||||
- setup_os_pkg_name
|
||||
|
||||
@@ -9,17 +9,10 @@
|
||||
suffix: .django_manage
|
||||
register: tmp_django_root
|
||||
|
||||
- name: Install virtualenv on CentOS 8
|
||||
- name: Install virtualenv
|
||||
package:
|
||||
name: virtualenv
|
||||
name: "{{ os_package_name.virtualenv }}"
|
||||
state: present
|
||||
when: ansible_distribution == 'CentOS' and ansible_distribution_major_version == '8'
|
||||
|
||||
- name: Install virtualenv on Arch Linux
|
||||
pip:
|
||||
name: virtualenv
|
||||
state: present
|
||||
when: ansible_os_family == 'Archlinux'
|
||||
|
||||
- name: Install required library
|
||||
pip:
|
||||
|
||||
@@ -2,5 +2,4 @@
|
||||
# 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
|
||||
|
||||
cloud/gandi
|
||||
unsupported
|
||||
|
||||
@@ -6,4 +6,3 @@ azp/posix/2
|
||||
destructive
|
||||
skip/python2
|
||||
skip/python3.5
|
||||
disabled # TODO
|
||||
|
||||
@@ -217,76 +217,76 @@
|
||||
- "'tox' not in uninstall_tox_again.application"
|
||||
|
||||
##############################################################################
|
||||
- name: ensure application ansible-lint is uninstalled
|
||||
- name: ensure application pylint is uninstalled
|
||||
community.general.pipx:
|
||||
name: ansible-lint
|
||||
name: pylint
|
||||
state: absent
|
||||
|
||||
- name: install application ansible-lint
|
||||
- name: install application pylint
|
||||
community.general.pipx:
|
||||
name: ansible-lint
|
||||
register: install_ansible_lint
|
||||
name: pylint
|
||||
register: install_pylint
|
||||
|
||||
- name: inject packages
|
||||
community.general.pipx:
|
||||
state: inject
|
||||
name: ansible-lint
|
||||
name: pylint
|
||||
inject_packages:
|
||||
- licenses
|
||||
register: inject_pkgs_ansible_lint
|
||||
register: inject_pkgs_pylint
|
||||
|
||||
- name: inject packages with apps
|
||||
community.general.pipx:
|
||||
state: inject
|
||||
name: ansible-lint
|
||||
name: pylint
|
||||
inject_packages:
|
||||
- black
|
||||
install_apps: true
|
||||
register: inject_pkgs_apps_ansible_lint
|
||||
register: inject_pkgs_apps_pylint
|
||||
|
||||
- name: cleanup ansible-lint
|
||||
- name: cleanup pylint
|
||||
community.general.pipx:
|
||||
state: absent
|
||||
name: ansible-lint
|
||||
register: uninstall_ansible_lint
|
||||
name: pylint
|
||||
register: uninstall_pylint
|
||||
|
||||
- name: check assertions inject_packages
|
||||
assert:
|
||||
that:
|
||||
- install_ansible_lint is changed
|
||||
- inject_pkgs_ansible_lint is changed
|
||||
- '"ansible-lint" in inject_pkgs_ansible_lint.application'
|
||||
- '"licenses" in inject_pkgs_ansible_lint.application["ansible-lint"]["injected"]'
|
||||
- inject_pkgs_apps_ansible_lint is changed
|
||||
- '"ansible-lint" in inject_pkgs_apps_ansible_lint.application'
|
||||
- '"black" in inject_pkgs_apps_ansible_lint.application["ansible-lint"]["injected"]'
|
||||
- uninstall_ansible_lint is changed
|
||||
- install_pylint is changed
|
||||
- inject_pkgs_pylint is changed
|
||||
- '"pylint" in inject_pkgs_pylint.application'
|
||||
- '"licenses" in inject_pkgs_pylint.application["pylint"]["injected"]'
|
||||
- inject_pkgs_apps_pylint is changed
|
||||
- '"pylint" in inject_pkgs_apps_pylint.application'
|
||||
- '"black" in inject_pkgs_apps_pylint.application["pylint"]["injected"]'
|
||||
- uninstall_pylint is changed
|
||||
|
||||
##############################################################################
|
||||
- name: install jupyter - not working smoothly in freebsd
|
||||
when: ansible_system != 'FreeBSD'
|
||||
# when: ansible_system != 'FreeBSD'
|
||||
block:
|
||||
- name: ensure application jupyter is uninstalled
|
||||
- name: ensure application mkdocs is uninstalled
|
||||
community.general.pipx:
|
||||
name: jupyter
|
||||
name: mkdocs
|
||||
state: absent
|
||||
|
||||
- name: install application jupyter
|
||||
- name: install application mkdocs
|
||||
community.general.pipx:
|
||||
name: jupyter
|
||||
name: mkdocs
|
||||
install_deps: true
|
||||
register: install_jupyter
|
||||
register: install_mkdocs
|
||||
|
||||
- name: cleanup jupyter
|
||||
- name: cleanup mkdocs
|
||||
community.general.pipx:
|
||||
state: absent
|
||||
name: jupyter
|
||||
name: mkdocs
|
||||
|
||||
- name: check assertions
|
||||
assert:
|
||||
that:
|
||||
- install_jupyter is changed
|
||||
- '"ipython" in install_jupyter.stdout'
|
||||
- install_mkdocs is changed
|
||||
- '"markdown_py" in install_mkdocs.stdout'
|
||||
|
||||
##############################################################################
|
||||
- name: ensure /opt/pipx
|
||||
|
||||
@@ -6,4 +6,3 @@ azp/posix/3
|
||||
destructive
|
||||
skip/python2
|
||||
skip/python3.5
|
||||
disabled # TODO
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
apps:
|
||||
- name: tox
|
||||
source: tox==3.24.0
|
||||
- name: ansible-lint
|
||||
- name: pylint
|
||||
inject_packages:
|
||||
- licenses
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
- name: install applications
|
||||
community.general.pipx:
|
||||
name: "{{ item.name }}"
|
||||
source: "{{ item.source|default(omit) }}"
|
||||
source: "{{ item.source | default(omit) }}"
|
||||
loop: "{{ apps }}"
|
||||
|
||||
- name: inject packages
|
||||
@@ -102,9 +102,9 @@
|
||||
include_injected: true
|
||||
register: info2_all_deps
|
||||
|
||||
- name: retrieve application ansible-lint
|
||||
- name: retrieve application pylint
|
||||
community.general.pipx_info:
|
||||
name: ansible-lint
|
||||
name: pylint
|
||||
include_deps: true
|
||||
include_injected: true
|
||||
register: info2_lint
|
||||
@@ -131,10 +131,10 @@
|
||||
- "'injected' in all_apps_deps[0]"
|
||||
- "'licenses' in all_apps_deps[0].injected"
|
||||
|
||||
- lint|length == 1
|
||||
- lint | length == 1
|
||||
- all_apps_deps|length == 2
|
||||
- lint[0] == all_apps_deps[0]
|
||||
vars:
|
||||
all_apps: "{{ info2_all.application|sort(attribute='name') }}"
|
||||
all_apps_deps: "{{ info2_all_deps.application|sort(attribute='name') }}"
|
||||
lint: "{{ info2_lint.application|sort(attribute='name') }}"
|
||||
all_apps_deps: "{{ info2_all_deps.application | sort(attribute='name') }}"
|
||||
lint: "{{ info2_lint.application | sort(attribute='name') }}"
|
||||
|
||||
11
tests/integration/targets/setup_os_pkg_name/tasks/alpine.yml
Normal file
11
tests/integration/targets/setup_os_pkg_name/tasks/alpine.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
# 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
|
||||
|
||||
- name: Update OS Package name fact (alpine)
|
||||
ansible.builtin.set_fact:
|
||||
os_package_name: "{{ os_package_name | combine(specific_package_names) }}"
|
||||
vars:
|
||||
specific_package_names:
|
||||
virtualenv: py3-virtualenv
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
# 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
|
||||
|
||||
- name: Update OS Package name fact (archlinux)
|
||||
ansible.builtin.set_fact:
|
||||
os_package_name: "{{ os_package_name | combine(specific_package_names) }}"
|
||||
vars:
|
||||
specific_package_names:
|
||||
virtualenv: python-virtualenv
|
||||
10
tests/integration/targets/setup_os_pkg_name/tasks/debian.yml
Normal file
10
tests/integration/targets/setup_os_pkg_name/tasks/debian.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
# 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
|
||||
|
||||
- name: Update OS Package name fact (debian)
|
||||
ansible.builtin.set_fact:
|
||||
os_package_name: "{{ os_package_name | combine(specific_package_names) }}"
|
||||
vars:
|
||||
specific_package_names: {}
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
# 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
|
||||
|
||||
- name: Update OS Package name fact (default)
|
||||
ansible.builtin.set_fact:
|
||||
os_package_name: "{{ os_package_name | combine(specific_package_names) }}"
|
||||
vars:
|
||||
specific_package_names:
|
||||
virtualenv: virtualenv
|
||||
26
tests/integration/targets/setup_os_pkg_name/tasks/main.yml
Normal file
26
tests/integration/targets/setup_os_pkg_name/tasks/main.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
####################################################################
|
||||
# WARNING: These are designed specifically for Ansible tests #
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
# 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
|
||||
|
||||
- name: Make sure we have the ansible_os_family and ansible_distribution_version facts
|
||||
ansible.builtin.setup:
|
||||
gather_subset: distribution
|
||||
when: ansible_facts == {}
|
||||
|
||||
- name: Create OS Package name fact
|
||||
ansible.builtin.set_fact:
|
||||
os_package_name: {}
|
||||
|
||||
- name: Include the files setting the package names
|
||||
ansible.builtin.include_tasks: "{{ file }}"
|
||||
loop_control:
|
||||
loop_var: file
|
||||
loop:
|
||||
- "default.yml"
|
||||
- "{{ ansible_os_family | lower }}.yml"
|
||||
10
tests/integration/targets/setup_os_pkg_name/tasks/redhat.yml
Normal file
10
tests/integration/targets/setup_os_pkg_name/tasks/redhat.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
# 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
|
||||
|
||||
- name: Update OS Package name fact (redhat)
|
||||
ansible.builtin.set_fact:
|
||||
os_package_name: "{{ os_package_name | combine(specific_package_names) }}"
|
||||
vars:
|
||||
specific_package_names: {}
|
||||
11
tests/integration/targets/setup_os_pkg_name/tasks/suse.yml
Normal file
11
tests/integration/targets/setup_os_pkg_name/tasks/suse.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
# 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
|
||||
|
||||
- name: Update OS Package name fact (suse)
|
||||
ansible.builtin.set_fact:
|
||||
os_package_name: "{{ os_package_name | combine(specific_package_names) }}"
|
||||
vars:
|
||||
specific_package_names:
|
||||
virtualenv: python3-virtualenv
|
||||
@@ -60,6 +60,14 @@
|
||||
state: present
|
||||
when: ansible_distribution == 'Alpine'
|
||||
|
||||
- name: make sure hwclock is installed in Ubuntu 24.04
|
||||
package:
|
||||
name: util-linux-extra
|
||||
state: present
|
||||
when:
|
||||
- ansible_distribution == 'Ubuntu'
|
||||
- ansible_facts.distribution_major_version is version('24', '>=')
|
||||
|
||||
- name: make sure the dbus service is started under systemd
|
||||
systemd:
|
||||
name: dbus
|
||||
|
||||
@@ -146,7 +146,7 @@ def serialize_groups(groups):
|
||||
return list(map(str, groups))
|
||||
|
||||
|
||||
@ pytest.fixture(scope="module")
|
||||
@pytest.fixture(scope="module")
|
||||
def inventory():
|
||||
r = InventoryModule()
|
||||
r.inventory = InventoryData()
|
||||
|
||||
@@ -23,7 +23,7 @@ from ansible.module_utils.six import StringIO
|
||||
@contextmanager
|
||||
def patch_keycloak_api(get_identity_provider, create_identity_provider=None, update_identity_provider=None, delete_identity_provider=None,
|
||||
get_identity_provider_mappers=None, create_identity_provider_mapper=None, update_identity_provider_mapper=None,
|
||||
delete_identity_provider_mapper=None):
|
||||
delete_identity_provider_mapper=None, get_realm_by_id=None):
|
||||
"""Mock context manager for patching the methods in PwPolicyIPAClient that contact the IPA server
|
||||
|
||||
Patches the `login` and `_post_json` methods
|
||||
@@ -55,9 +55,11 @@ def patch_keycloak_api(get_identity_provider, create_identity_provider=None, upd
|
||||
as mock_update_identity_provider_mapper:
|
||||
with patch.object(obj, 'delete_identity_provider_mapper', side_effect=delete_identity_provider_mapper) \
|
||||
as mock_delete_identity_provider_mapper:
|
||||
yield mock_get_identity_provider, mock_create_identity_provider, mock_update_identity_provider, \
|
||||
mock_delete_identity_provider, mock_get_identity_provider_mappers, mock_create_identity_provider_mapper, \
|
||||
mock_update_identity_provider_mapper, mock_delete_identity_provider_mapper
|
||||
with patch.object(obj, 'get_realm_by_id', side_effect=get_realm_by_id) \
|
||||
as mock_get_realm_by_id:
|
||||
yield mock_get_identity_provider, mock_create_identity_provider, mock_update_identity_provider, \
|
||||
mock_delete_identity_provider, mock_get_identity_provider_mappers, mock_create_identity_provider_mapper, \
|
||||
mock_update_identity_provider_mapper, mock_delete_identity_provider_mapper, mock_get_realm_by_id
|
||||
|
||||
|
||||
def get_response(object_with_future_response, method, get_id_call_count):
|
||||
@@ -200,6 +202,38 @@ class TestKeycloakIdentityProvider(ModuleTestCase):
|
||||
"name": "last_name"
|
||||
}]
|
||||
]
|
||||
return_value_realm_get = [
|
||||
{
|
||||
'id': 'realm-name',
|
||||
'realm': 'realm-name',
|
||||
'enabled': True,
|
||||
'identityProviders': [
|
||||
{
|
||||
"addReadTokenRoleOnCreate": False,
|
||||
"alias": "oidc-idp",
|
||||
"authenticateByDefault": False,
|
||||
"config": {
|
||||
"authorizationUrl": "https://idp.example.com/auth",
|
||||
"clientAuthMethod": "client_secret_post",
|
||||
"clientId": "my-client",
|
||||
"clientSecret": "secret",
|
||||
"issuer": "https://idp.example.com",
|
||||
"syncMode": "FORCE",
|
||||
"tokenUrl": "https://idp.example.com/token",
|
||||
"userInfoUrl": "https://idp.example.com/userinfo"
|
||||
},
|
||||
"displayName": "OpenID Connect IdP",
|
||||
"enabled": True,
|
||||
"firstBrokerLoginFlowAlias": "first broker login",
|
||||
"internalId": "7ab437d5-f2bb-4ecc-91a8-315349454da6",
|
||||
"linkOnly": False,
|
||||
"providerId": "oidc",
|
||||
"storeToken": False,
|
||||
"trustEmail": False,
|
||||
}
|
||||
]
|
||||
},
|
||||
]
|
||||
return_value_idp_created = [None]
|
||||
return_value_mapper_created = [None, None]
|
||||
changed = True
|
||||
@@ -210,15 +244,17 @@ class TestKeycloakIdentityProvider(ModuleTestCase):
|
||||
|
||||
with mock_good_connection():
|
||||
with patch_keycloak_api(get_identity_provider=return_value_idp_get, get_identity_provider_mappers=return_value_mappers_get,
|
||||
create_identity_provider=return_value_idp_created, create_identity_provider_mapper=return_value_mapper_created) \
|
||||
create_identity_provider=return_value_idp_created, create_identity_provider_mapper=return_value_mapper_created,
|
||||
get_realm_by_id=return_value_realm_get) \
|
||||
as (mock_get_identity_provider, mock_create_identity_provider, mock_update_identity_provider, mock_delete_identity_provider,
|
||||
mock_get_identity_provider_mappers, mock_create_identity_provider_mapper, mock_update_identity_provider_mapper,
|
||||
mock_delete_identity_provider_mapper):
|
||||
mock_delete_identity_provider_mapper, mock_get_realm_by_id):
|
||||
with self.assertRaises(AnsibleExitJson) as exec_info:
|
||||
self.module.main()
|
||||
|
||||
self.assertEqual(len(mock_get_identity_provider.mock_calls), 2)
|
||||
self.assertEqual(len(mock_get_identity_provider_mappers.mock_calls), 1)
|
||||
self.assertEqual(len(mock_get_realm_by_id.mock_calls), 1)
|
||||
self.assertEqual(len(mock_create_identity_provider.mock_calls), 1)
|
||||
self.assertEqual(len(mock_create_identity_provider_mapper.mock_calls), 2)
|
||||
|
||||
@@ -444,6 +480,68 @@ class TestKeycloakIdentityProvider(ModuleTestCase):
|
||||
"name": "last_name"
|
||||
}]
|
||||
]
|
||||
return_value_realm_get = [
|
||||
{
|
||||
'id': 'realm-name',
|
||||
'realm': 'realm-name',
|
||||
'enabled': True,
|
||||
'identityProviders': [
|
||||
{
|
||||
"addReadTokenRoleOnCreate": False,
|
||||
"alias": "oidc-idp",
|
||||
"authenticateByDefault": False,
|
||||
"config": {
|
||||
"authorizationUrl": "https://idp.example.com/auth",
|
||||
"clientAuthMethod": "client_secret_post",
|
||||
"clientId": "my-client",
|
||||
"clientSecret": "secret",
|
||||
"issuer": "https://idp.example.com",
|
||||
"syncMode": "FORCE",
|
||||
"tokenUrl": "https://idp.example.com/token",
|
||||
"userInfoUrl": "https://idp.example.com/userinfo"
|
||||
},
|
||||
"displayName": "OpenID Connect IdP",
|
||||
"enabled": True,
|
||||
"firstBrokerLoginFlowAlias": "first broker login",
|
||||
"internalId": "7ab437d5-f2bb-4ecc-91a8-315349454da6",
|
||||
"linkOnly": False,
|
||||
"providerId": "oidc",
|
||||
"storeToken": False,
|
||||
"trustEmail": False,
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
'id': 'realm-name',
|
||||
'realm': 'realm-name',
|
||||
'enabled': True,
|
||||
'identityProviders': [
|
||||
{
|
||||
"addReadTokenRoleOnCreate": False,
|
||||
"alias": "oidc-idp",
|
||||
"authenticateByDefault": False,
|
||||
"config": {
|
||||
"authorizationUrl": "https://idp.example.com/auth",
|
||||
"clientAuthMethod": "client_secret_post",
|
||||
"clientId": "my-client",
|
||||
"clientSecret": "secret",
|
||||
"issuer": "https://idp.example.com",
|
||||
"syncMode": "FORCE",
|
||||
"tokenUrl": "https://idp.example.com/token",
|
||||
"userInfoUrl": "https://idp.example.com/userinfo"
|
||||
},
|
||||
"displayName": "OpenID Connect IdP",
|
||||
"enabled": True,
|
||||
"firstBrokerLoginFlowAlias": "first broker login",
|
||||
"internalId": "7ab437d5-f2bb-4ecc-91a8-315349454da6",
|
||||
"linkOnly": False,
|
||||
"providerId": "oidc",
|
||||
"storeToken": False,
|
||||
"trustEmail": False,
|
||||
}
|
||||
]
|
||||
},
|
||||
]
|
||||
return_value_idp_updated = [None]
|
||||
return_value_mapper_updated = [None]
|
||||
return_value_mapper_created = [None]
|
||||
@@ -456,15 +554,16 @@ class TestKeycloakIdentityProvider(ModuleTestCase):
|
||||
with mock_good_connection():
|
||||
with patch_keycloak_api(get_identity_provider=return_value_idp_get, get_identity_provider_mappers=return_value_mappers_get,
|
||||
update_identity_provider=return_value_idp_updated, update_identity_provider_mapper=return_value_mapper_updated,
|
||||
create_identity_provider_mapper=return_value_mapper_created) \
|
||||
create_identity_provider_mapper=return_value_mapper_created, get_realm_by_id=return_value_realm_get) \
|
||||
as (mock_get_identity_provider, mock_create_identity_provider, mock_update_identity_provider, mock_delete_identity_provider,
|
||||
mock_get_identity_provider_mappers, mock_create_identity_provider_mapper, mock_update_identity_provider_mapper,
|
||||
mock_delete_identity_provider_mapper):
|
||||
mock_delete_identity_provider_mapper, mock_get_realm_by_id):
|
||||
with self.assertRaises(AnsibleExitJson) as exec_info:
|
||||
self.module.main()
|
||||
|
||||
self.assertEqual(len(mock_get_identity_provider.mock_calls), 2)
|
||||
self.assertEqual(len(mock_get_identity_provider_mappers.mock_calls), 5)
|
||||
self.assertEqual(len(mock_get_realm_by_id.mock_calls), 2)
|
||||
self.assertEqual(len(mock_update_identity_provider.mock_calls), 1)
|
||||
self.assertEqual(len(mock_update_identity_provider_mapper.mock_calls), 1)
|
||||
self.assertEqual(len(mock_create_identity_provider_mapper.mock_calls), 1)
|
||||
@@ -472,6 +571,156 @@ class TestKeycloakIdentityProvider(ModuleTestCase):
|
||||
# Verify that the module's changed status matches what is expected
|
||||
self.assertIs(exec_info.exception.args[0]['changed'], changed)
|
||||
|
||||
def test_no_change_when_present(self):
|
||||
"""Update existing identity provider"""
|
||||
|
||||
module_args = {
|
||||
'auth_keycloak_url': 'http://keycloak.url/auth',
|
||||
'auth_password': 'admin',
|
||||
'auth_realm': 'master',
|
||||
'auth_username': 'admin',
|
||||
'auth_client_id': 'admin-cli',
|
||||
"addReadTokenRoleOnCreate": False,
|
||||
"alias": "oidc-idp",
|
||||
"authenticateByDefault": False,
|
||||
"config": {
|
||||
"authorizationUrl": "https://idp.example.com/auth",
|
||||
"clientAuthMethod": "client_secret_post",
|
||||
"clientId": "my-client",
|
||||
"clientSecret": "secret",
|
||||
"issuer": "https://idp.example.com",
|
||||
"syncMode": "FORCE",
|
||||
"tokenUrl": "https://idp.example.com/token",
|
||||
"userInfoUrl": "https://idp.example.com/userinfo"
|
||||
},
|
||||
"displayName": "OpenID Connect IdP changeme",
|
||||
"enabled": True,
|
||||
"firstBrokerLoginFlowAlias": "first broker login",
|
||||
"linkOnly": False,
|
||||
"providerId": "oidc",
|
||||
"storeToken": False,
|
||||
"trustEmail": False,
|
||||
'mappers': [{
|
||||
'name': "username",
|
||||
'identityProviderAlias': "oidc-idp",
|
||||
'identityProviderMapper': "oidc-user-attribute-idp-mapper",
|
||||
'config': {
|
||||
'claim': "username",
|
||||
'user.attribute': "username",
|
||||
'syncMode': "INHERIT",
|
||||
}
|
||||
}]
|
||||
}
|
||||
return_value_idp_get = [
|
||||
{
|
||||
"addReadTokenRoleOnCreate": False,
|
||||
"alias": "oidc-idp",
|
||||
"authenticateByDefault": False,
|
||||
"config": {
|
||||
"authorizationUrl": "https://idp.example.com/auth",
|
||||
"clientAuthMethod": "client_secret_post",
|
||||
"clientId": "my-client",
|
||||
"clientSecret": "**********",
|
||||
"issuer": "https://idp.example.com",
|
||||
"syncMode": "FORCE",
|
||||
"tokenUrl": "https://idp.example.com/token",
|
||||
"userInfoUrl": "https://idp.example.com/userinfo"
|
||||
},
|
||||
"displayName": "OpenID Connect IdP changeme",
|
||||
"enabled": True,
|
||||
"firstBrokerLoginFlowAlias": "first broker login",
|
||||
"internalId": "7ab437d5-f2bb-4ecc-91a8-315349454da6",
|
||||
"linkOnly": False,
|
||||
"providerId": "oidc",
|
||||
"storeToken": False,
|
||||
"trustEmail": False,
|
||||
},
|
||||
]
|
||||
return_value_mappers_get = [
|
||||
[{
|
||||
'config': {
|
||||
'claim': "username",
|
||||
'syncMode': "INHERIT",
|
||||
'user.attribute': "username"
|
||||
},
|
||||
"id": "616f11ba-b9ae-42ae-bd1b-bc618741c10b",
|
||||
'identityProviderAlias': "oidc-idp",
|
||||
'identityProviderMapper': "oidc-user-attribute-idp-mapper",
|
||||
'name': "username"
|
||||
}],
|
||||
[{
|
||||
'config': {
|
||||
'claim': "username",
|
||||
'syncMode': "INHERIT",
|
||||
'user.attribute': "username"
|
||||
},
|
||||
"id": "616f11ba-b9ae-42ae-bd1b-bc618741c10b",
|
||||
'identityProviderAlias': "oidc-idp",
|
||||
'identityProviderMapper': "oidc-user-attribute-idp-mapper",
|
||||
'name': "username"
|
||||
}]
|
||||
]
|
||||
return_value_realm_get = [
|
||||
{
|
||||
'id': 'realm-name',
|
||||
'realm': 'realm-name',
|
||||
'enabled': True,
|
||||
'identityProviders': [
|
||||
{
|
||||
"addReadTokenRoleOnCreate": False,
|
||||
"alias": "oidc-idp",
|
||||
"authenticateByDefault": False,
|
||||
"config": {
|
||||
"authorizationUrl": "https://idp.example.com/auth",
|
||||
"clientAuthMethod": "client_secret_post",
|
||||
"clientId": "my-client",
|
||||
"clientSecret": "secret",
|
||||
"issuer": "https://idp.example.com",
|
||||
"syncMode": "FORCE",
|
||||
"tokenUrl": "https://idp.example.com/token",
|
||||
"userInfoUrl": "https://idp.example.com/userinfo"
|
||||
},
|
||||
"displayName": "OpenID Connect IdP",
|
||||
"enabled": True,
|
||||
"firstBrokerLoginFlowAlias": "first broker login",
|
||||
"internalId": "7ab437d5-f2bb-4ecc-91a8-315349454da6",
|
||||
"linkOnly": False,
|
||||
"providerId": "oidc",
|
||||
"storeToken": False,
|
||||
"trustEmail": False,
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
return_value_idp_updated = [None]
|
||||
return_value_mapper_updated = [None]
|
||||
return_value_mapper_created = [None]
|
||||
changed = False
|
||||
|
||||
set_module_args(module_args)
|
||||
|
||||
# Run the module
|
||||
|
||||
with mock_good_connection():
|
||||
with patch_keycloak_api(get_identity_provider=return_value_idp_get, get_identity_provider_mappers=return_value_mappers_get,
|
||||
update_identity_provider=return_value_idp_updated, update_identity_provider_mapper=return_value_mapper_updated,
|
||||
create_identity_provider_mapper=return_value_mapper_created, get_realm_by_id=return_value_realm_get) \
|
||||
as (mock_get_identity_provider, mock_create_identity_provider, mock_update_identity_provider, mock_delete_identity_provider,
|
||||
mock_get_identity_provider_mappers, mock_create_identity_provider_mapper, mock_update_identity_provider_mapper,
|
||||
mock_delete_identity_provider_mapper, mock_get_realm_by_id):
|
||||
with self.assertRaises(AnsibleExitJson) as exec_info:
|
||||
self.module.main()
|
||||
|
||||
self.assertEqual(len(mock_get_identity_provider.mock_calls), 1)
|
||||
self.assertEqual(len(mock_get_identity_provider_mappers.mock_calls), 2)
|
||||
self.assertEqual(len(mock_get_realm_by_id.mock_calls), 1)
|
||||
self.assertEqual(len(mock_update_identity_provider.mock_calls), 0)
|
||||
self.assertEqual(len(mock_update_identity_provider_mapper.mock_calls), 0)
|
||||
self.assertEqual(len(mock_create_identity_provider_mapper.mock_calls), 0)
|
||||
|
||||
# Verify that the module's changed status matches what is expected
|
||||
self.assertIs(exec_info.exception.args[0]['changed'], changed)
|
||||
|
||||
def test_delete_when_absent(self):
|
||||
"""Remove an absent identity provider"""
|
||||
|
||||
@@ -497,7 +746,7 @@ class TestKeycloakIdentityProvider(ModuleTestCase):
|
||||
with patch_keycloak_api(get_identity_provider=return_value_idp_get) \
|
||||
as (mock_get_identity_provider, mock_create_identity_provider, mock_update_identity_provider, mock_delete_identity_provider,
|
||||
mock_get_identity_provider_mappers, mock_create_identity_provider_mapper, mock_update_identity_provider_mapper,
|
||||
mock_delete_identity_provider_mapper):
|
||||
mock_delete_identity_provider_mapper, mock_get_realm_by_id):
|
||||
with self.assertRaises(AnsibleExitJson) as exec_info:
|
||||
self.module.main()
|
||||
|
||||
@@ -560,6 +809,38 @@ class TestKeycloakIdentityProvider(ModuleTestCase):
|
||||
"name": "email"
|
||||
}]
|
||||
]
|
||||
return_value_realm_get = [
|
||||
{
|
||||
'id': 'realm-name',
|
||||
'realm': 'realm-name',
|
||||
'enabled': True,
|
||||
'identityProviders': [
|
||||
{
|
||||
"alias": "oidc",
|
||||
"displayName": "",
|
||||
"internalId": "2bca4192-e816-4beb-bcba-190164eb55b8",
|
||||
"providerId": "oidc",
|
||||
"enabled": True,
|
||||
"updateProfileFirstLoginMode": "on",
|
||||
"trustEmail": False,
|
||||
"storeToken": False,
|
||||
"addReadTokenRoleOnCreate": False,
|
||||
"authenticateByDefault": False,
|
||||
"linkOnly": False,
|
||||
"config": {
|
||||
"validateSignature": "false",
|
||||
"pkceEnabled": "false",
|
||||
"tokenUrl": "https://localhost:8000",
|
||||
"clientId": "asdf",
|
||||
"authorizationUrl": "https://localhost:8000",
|
||||
"clientAuthMethod": "client_secret_post",
|
||||
"clientSecret": "real_secret",
|
||||
"guiOrder": "0"
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
return_value_idp_deleted = [None]
|
||||
changed = True
|
||||
|
||||
@@ -569,15 +850,16 @@ class TestKeycloakIdentityProvider(ModuleTestCase):
|
||||
|
||||
with mock_good_connection():
|
||||
with patch_keycloak_api(get_identity_provider=return_value_idp_get, get_identity_provider_mappers=return_value_mappers_get,
|
||||
delete_identity_provider=return_value_idp_deleted) \
|
||||
delete_identity_provider=return_value_idp_deleted, get_realm_by_id=return_value_realm_get) \
|
||||
as (mock_get_identity_provider, mock_create_identity_provider, mock_update_identity_provider, mock_delete_identity_provider,
|
||||
mock_get_identity_provider_mappers, mock_create_identity_provider_mapper, mock_update_identity_provider_mapper,
|
||||
mock_delete_identity_provider_mapper):
|
||||
mock_delete_identity_provider_mapper, mock_get_realm_by_id):
|
||||
with self.assertRaises(AnsibleExitJson) as exec_info:
|
||||
self.module.main()
|
||||
|
||||
self.assertEqual(len(mock_get_identity_provider.mock_calls), 1)
|
||||
self.assertEqual(len(mock_get_identity_provider_mappers.mock_calls), 1)
|
||||
self.assertEqual(len(mock_get_realm_by_id.mock_calls), 1)
|
||||
self.assertEqual(len(mock_delete_identity_provider.mock_calls), 1)
|
||||
|
||||
# Verify that the module's changed status matches what is expected
|
||||
|
||||
@@ -144,8 +144,9 @@ class TestKeycloakUserFederation(ModuleTestCase):
|
||||
}
|
||||
}
|
||||
]
|
||||
# get before_comp, get default_mapper, get after_mapper
|
||||
return_value_components_get = [
|
||||
[], []
|
||||
[], [], []
|
||||
]
|
||||
changed = True
|
||||
|
||||
@@ -159,7 +160,7 @@ class TestKeycloakUserFederation(ModuleTestCase):
|
||||
with self.assertRaises(AnsibleExitJson) as exec_info:
|
||||
self.module.main()
|
||||
|
||||
self.assertEqual(len(mock_get_components.mock_calls), 1)
|
||||
self.assertEqual(len(mock_get_components.mock_calls), 3)
|
||||
self.assertEqual(len(mock_get_component.mock_calls), 0)
|
||||
self.assertEqual(len(mock_create_component.mock_calls), 1)
|
||||
self.assertEqual(len(mock_update_component.mock_calls), 0)
|
||||
@@ -228,6 +229,7 @@ class TestKeycloakUserFederation(ModuleTestCase):
|
||||
}
|
||||
}
|
||||
],
|
||||
[],
|
||||
[]
|
||||
]
|
||||
return_value_component_get = [
|
||||
@@ -281,7 +283,7 @@ class TestKeycloakUserFederation(ModuleTestCase):
|
||||
with self.assertRaises(AnsibleExitJson) as exec_info:
|
||||
self.module.main()
|
||||
|
||||
self.assertEqual(len(mock_get_components.mock_calls), 2)
|
||||
self.assertEqual(len(mock_get_components.mock_calls), 3)
|
||||
self.assertEqual(len(mock_get_component.mock_calls), 1)
|
||||
self.assertEqual(len(mock_create_component.mock_calls), 0)
|
||||
self.assertEqual(len(mock_update_component.mock_calls), 1)
|
||||
@@ -344,7 +346,47 @@ class TestKeycloakUserFederation(ModuleTestCase):
|
||||
]
|
||||
}
|
||||
return_value_components_get = [
|
||||
[], []
|
||||
[],
|
||||
# exemplary default mapper created by keylocak
|
||||
[
|
||||
{
|
||||
"config": {
|
||||
"always.read.value.from.ldap": "false",
|
||||
"is.mandatory.in.ldap": "false",
|
||||
"ldap.attribute": "mail",
|
||||
"read.only": "true",
|
||||
"user.model.attribute": "email"
|
||||
},
|
||||
"id": "77e1763f-c51a-4286-bade-75577d64803c",
|
||||
"name": "email",
|
||||
"parentId": "e5f48aa3-b56b-4983-a8ad-2c7b8b5e77cb",
|
||||
"providerId": "user-attribute-ldap-mapper",
|
||||
"providerType": "org.keycloak.storage.ldap.mappers.LDAPStorageMapper"
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
"id": "2dfadafd-8b34-495f-a98b-153e71a22311",
|
||||
"name": "full name",
|
||||
"providerId": "full-name-ldap-mapper",
|
||||
"providerType": "org.keycloak.storage.ldap.mappers.LDAPStorageMapper",
|
||||
"parentId": "eb691537-b73c-4cd8-b481-6031c26499d8",
|
||||
"config": {
|
||||
"ldap.full.name.attribute": [
|
||||
"cn"
|
||||
],
|
||||
"read.only": [
|
||||
"true"
|
||||
],
|
||||
"write.only": [
|
||||
"false"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
return_value_component_delete = [
|
||||
None
|
||||
]
|
||||
return_value_component_create = [
|
||||
{
|
||||
@@ -462,11 +504,11 @@ class TestKeycloakUserFederation(ModuleTestCase):
|
||||
with self.assertRaises(AnsibleExitJson) as exec_info:
|
||||
self.module.main()
|
||||
|
||||
self.assertEqual(len(mock_get_components.mock_calls), 2)
|
||||
self.assertEqual(len(mock_get_components.mock_calls), 3)
|
||||
self.assertEqual(len(mock_get_component.mock_calls), 0)
|
||||
self.assertEqual(len(mock_create_component.mock_calls), 2)
|
||||
self.assertEqual(len(mock_update_component.mock_calls), 0)
|
||||
self.assertEqual(len(mock_delete_component.mock_calls), 0)
|
||||
self.assertEqual(len(mock_delete_component.mock_calls), 1)
|
||||
|
||||
# Verify that the module's changed status matches what is expected
|
||||
self.assertIs(exec_info.exception.args[0]['changed'], changed)
|
||||
|
||||
Reference in New Issue
Block a user