mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-04-29 09:56:53 +00:00
Compare commits
339 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4aeb322bb | ||
|
|
165da11731 | ||
|
|
88f7b5a675 | ||
|
|
ca3beb68de | ||
|
|
aa6b5e4a60 | ||
|
|
c740f89df3 | ||
|
|
9708561131 | ||
|
|
6558c9981f | ||
|
|
c949f3a834 | ||
|
|
9f3c86a589 | ||
|
|
febe7a2fb4 | ||
|
|
165182cdbf | ||
|
|
61a0dc4370 | ||
|
|
4e57240e9f | ||
|
|
ca388f064a | ||
|
|
fe224a6537 | ||
|
|
9c11230824 | ||
|
|
be1a905f6f | ||
|
|
57cfd1b46d | ||
|
|
737d37e019 | ||
|
|
3c20261264 | ||
|
|
d254372d37 | ||
|
|
fab717bb2d | ||
|
|
27a3d6d85d | ||
|
|
91376f7989 | ||
|
|
9a4e77384d | ||
|
|
f09b1e7f4c | ||
|
|
cb81abc636 | ||
|
|
c411e12555 | ||
|
|
24efe6b9db | ||
|
|
b4628e27b2 | ||
|
|
c58dda14c2 | ||
|
|
6e913a3b28 | ||
|
|
d4df585370 | ||
|
|
0a26b6d48d | ||
|
|
f0fcc91ac7 | ||
|
|
69d7f19c74 | ||
|
|
0edc3e820e | ||
|
|
6861450243 | ||
|
|
e49c6a339e | ||
|
|
486c47f922 | ||
|
|
c1b16d534f | ||
|
|
eab39ffc23 | ||
|
|
bc228d82be | ||
|
|
e7cc996470 | ||
|
|
3e338a1cca | ||
|
|
ad6ff9b0c5 | ||
|
|
0eb33c2839 | ||
|
|
114eb67f58 | ||
|
|
1f2c7b1731 | ||
|
|
f4dd4d5ace | ||
|
|
9b493d53a9 | ||
|
|
484f642c23 | ||
|
|
4171418e37 | ||
|
|
996fc8c18e | ||
|
|
ae5090d90e | ||
|
|
76dd465e08 | ||
|
|
fe798e22a6 | ||
|
|
6e0bc4f45c | ||
|
|
087c5a53d5 | ||
|
|
1aa94a5a1d | ||
|
|
2bac3bb8b2 | ||
|
|
0524d70805 | ||
|
|
91ecb8042d | ||
|
|
0cfd43be2c | ||
|
|
f8823211c7 | ||
|
|
59cb5b2d6f | ||
|
|
ee11847c7e | ||
|
|
67b921e4e6 | ||
|
|
86042b726a | ||
|
|
64e797d077 | ||
|
|
a35542d0d1 | ||
|
|
cb3ca05bd1 | ||
|
|
29a7d24d75 | ||
|
|
d7340945a4 | ||
|
|
f95b8ab9cd | ||
|
|
42bc2cb4d8 | ||
|
|
83994c0a2d | ||
|
|
bf780ea738 | ||
|
|
a5765143f1 | ||
|
|
86f9a657e7 | ||
|
|
6c5c05dfdc | ||
|
|
ea8720f572 | ||
|
|
14b19afc9a | ||
|
|
aa77a88f4b | ||
|
|
f93a1bf5ec | ||
|
|
28bdf1ed74 | ||
|
|
08f14f3eb0 | ||
|
|
37cddb8c02 | ||
|
|
a64e36820f | ||
|
|
7d19eca8bf | ||
|
|
cee5f31b70 | ||
|
|
c280b793de | ||
|
|
9bb768ae62 | ||
|
|
c9e11e5c0c | ||
|
|
33093e9f3e | ||
|
|
f3ea3e0da5 | ||
|
|
5e1e8d06ef | ||
|
|
05824a0754 | ||
|
|
f52dd194f9 | ||
|
|
be7f11bf39 | ||
|
|
997761878c | ||
|
|
59e58079cb | ||
|
|
cd706454ec | ||
|
|
81b16a88ee | ||
|
|
5ee687049f | ||
|
|
d4f272ba52 | ||
|
|
6fa833feed | ||
|
|
33ccabed13 | ||
|
|
e96552396e | ||
|
|
7059789f35 | ||
|
|
f3be0076af | ||
|
|
b1d94385ae | ||
|
|
ed8049a220 | ||
|
|
bbd68e26a2 | ||
|
|
9f67cbbe36 | ||
|
|
512bf4b77f | ||
|
|
f66cc7c933 | ||
|
|
3fb1ff0b72 | ||
|
|
bf8f2950b4 | ||
|
|
e8a7c27cab | ||
|
|
1dd86bcb55 | ||
|
|
b97bee3fd6 | ||
|
|
df34569fad | ||
|
|
e939cd07ef | ||
|
|
a49ad340af | ||
|
|
3862de3f15 | ||
|
|
1ddcdc63ff | ||
|
|
abcba9dbbe | ||
|
|
6b8a1cd8e6 | ||
|
|
6d003ca7fc | ||
|
|
6cf674485f | ||
|
|
11c7611ced | ||
|
|
627371e2d8 | ||
|
|
733e31c85f | ||
|
|
c077818c5d | ||
|
|
3d67f51824 | ||
|
|
2dee3464dd | ||
|
|
9a97bc7c11 | ||
|
|
c0cb7958cb | ||
|
|
345a69304a | ||
|
|
03084d1133 | ||
|
|
d209466985 | ||
|
|
38adbec483 | ||
|
|
681fad92c2 | ||
|
|
e8bdec2733 | ||
|
|
29f5033737 | ||
|
|
617be6e124 | ||
|
|
c8a2ac3a47 | ||
|
|
094dc6b69c | ||
|
|
810f3b50fc | ||
|
|
3db0fcf1bd | ||
|
|
b64929118e | ||
|
|
7d3e6d1bb7 | ||
|
|
1877ef1510 | ||
|
|
53f729730b | ||
|
|
f0529dcb0e | ||
|
|
682c6fc967 | ||
|
|
92544993c0 | ||
|
|
95b8afdea3 | ||
|
|
2c762c4753 | ||
|
|
de1f0ff419 | ||
|
|
b72b7d4936 | ||
|
|
0307fd12eb | ||
|
|
18a6bdd6aa | ||
|
|
3ec2fde2c6 | ||
|
|
3b97fad577 | ||
|
|
51394b55a0 | ||
|
|
673c79f6d9 | ||
|
|
5b9ee78610 | ||
|
|
1f1ae558f9 | ||
|
|
bad4b4b086 | ||
|
|
e944a67c18 | ||
|
|
cc3a79bc48 | ||
|
|
cc29b16536 | ||
|
|
50d7597ddc | ||
|
|
6bd131f2fb | ||
|
|
490899f87f | ||
|
|
c168f9c3be | ||
|
|
a7e8e95b50 | ||
|
|
e348d28559 | ||
|
|
5648e0e2af | ||
|
|
78297e44b7 | ||
|
|
cb7a970f6f | ||
|
|
7e3c73ceb2 | ||
|
|
867aee606e | ||
|
|
4b262e39f0 | ||
|
|
d03ae532ed | ||
|
|
b4a500103a | ||
|
|
0ef805699d | ||
|
|
9de145482b | ||
|
|
755a49692d | ||
|
|
ed79a68553 | ||
|
|
3186a944e9 | ||
|
|
1b2c2af9a8 | ||
|
|
71d74a7960 | ||
|
|
49e3da3646 | ||
|
|
33df7b61c0 | ||
|
|
24efe9ee9a | ||
|
|
4c4ef80ca9 | ||
|
|
cd0a414e9f | ||
|
|
c587c09df1 | ||
|
|
f0fd6aa97d | ||
|
|
68d0cac310 | ||
|
|
9f87989e7f | ||
|
|
2b8ac3c629 | ||
|
|
de193ac1bf | ||
|
|
b1d9507cd2 | ||
|
|
a64df658c5 | ||
|
|
868699dc5f | ||
|
|
84dbb286eb | ||
|
|
ea5cbe2553 | ||
|
|
31ff3f662d | ||
|
|
dcc3d4f508 | ||
|
|
393f2d6153 | ||
|
|
451c90251a | ||
|
|
3da24d50cd | ||
|
|
6c6de8fb90 | ||
|
|
8818a6f242 | ||
|
|
7b8b73f17f | ||
|
|
855cbd67ae | ||
|
|
fe520a6b09 | ||
|
|
f38bfaddf0 | ||
|
|
bf117c839c | ||
|
|
6781dd1918 | ||
|
|
0ca41dedce | ||
|
|
098912c229 | ||
|
|
59a9d34250 | ||
|
|
c4b18361b9 | ||
|
|
1430ed000c | ||
|
|
a35b2eda4c | ||
|
|
b92542dea2 | ||
|
|
4a40f99cd6 | ||
|
|
5ad703ac64 | ||
|
|
44172ddaa6 | ||
|
|
937dea6af3 | ||
|
|
f05f8bb49a | ||
|
|
756c0776d6 | ||
|
|
3985ade3fc | ||
|
|
6ec049734e | ||
|
|
08b0ea700d | ||
|
|
cc79c24c01 | ||
|
|
58eb495797 | ||
|
|
317f79ff1f | ||
|
|
b9ac2dcda5 | ||
|
|
682bb4b88a | ||
|
|
4caa6574de | ||
|
|
6fb212b104 | ||
|
|
3b73e7ed2a | ||
|
|
759ca9a0ab | ||
|
|
0ff003d312 | ||
|
|
9e3a729da9 | ||
|
|
2670215c8a | ||
|
|
e3f02cb161 | ||
|
|
fc2b1aac4a | ||
|
|
dc531b183d | ||
|
|
02431341b7 | ||
|
|
217a62aca2 | ||
|
|
4dc897d559 | ||
|
|
84ebda65f1 | ||
|
|
b49bf081f8 | ||
|
|
7c99c53c64 | ||
|
|
06d72dfed9 | ||
|
|
568e18809c | ||
|
|
2d4ce9f219 | ||
|
|
669d0925f7 | ||
|
|
eb1c1210d6 | ||
|
|
2ce3cf91b8 | ||
|
|
6383c82328 | ||
|
|
b3485b8fca | ||
|
|
28969c61ad | ||
|
|
2fc7baecf8 | ||
|
|
488e828f9b | ||
|
|
1f49241481 | ||
|
|
77fde030cd | ||
|
|
2b39470a77 | ||
|
|
fab73a1d1e | ||
|
|
25be366cc3 | ||
|
|
af53271c41 | ||
|
|
f95e0d775d | ||
|
|
c3bc172bf6 | ||
|
|
b5e58a3bcc | ||
|
|
471f523f53 | ||
|
|
50021d6bfb | ||
|
|
b52a7a6b0e | ||
|
|
b22638ba0c | ||
|
|
f0b3bba030 | ||
|
|
7ea544a624 | ||
|
|
fb2833d34d | ||
|
|
632fc07e65 | ||
|
|
be22ca0633 | ||
|
|
23aacc78e1 | ||
|
|
fd436bdbc2 | ||
|
|
da7cba4c12 | ||
|
|
03039a56c0 | ||
|
|
428e181440 | ||
|
|
b8545d10e6 | ||
|
|
f7fa54eed9 | ||
|
|
101c957631 | ||
|
|
53da86c1a5 | ||
|
|
1ca775248f | ||
|
|
3f80aa3c63 | ||
|
|
b1094d840f | ||
|
|
a3b748a15e | ||
|
|
911769d2f3 | ||
|
|
11e1423f60 | ||
|
|
79929830c4 | ||
|
|
5c1c8152ec | ||
|
|
3bf3d6bff4 | ||
|
|
f2a420ead5 | ||
|
|
c7481c5c96 | ||
|
|
83ff4429e8 | ||
|
|
52c28494ca | ||
|
|
8ad43fd774 | ||
|
|
0624951e17 | ||
|
|
5e5af458fb | ||
|
|
6a03108609 | ||
|
|
e87ca10b61 | ||
|
|
801e3d86ef | ||
|
|
270dc133b3 | ||
|
|
9874462abb | ||
|
|
6c7e9116e1 | ||
|
|
6a6bbb6577 | ||
|
|
60c8b9a67f | ||
|
|
672385309c | ||
|
|
27a4ffc293 | ||
|
|
bc0f99386b | ||
|
|
7610501c66 | ||
|
|
6b20572ea1 | ||
|
|
0e9cd5e6b6 | ||
|
|
f683d6a05d | ||
|
|
c604cc5ba9 | ||
|
|
eae33c20f6 | ||
|
|
97b584e261 | ||
|
|
621fb6a619 | ||
|
|
27827cbea4 | ||
|
|
858eaac500 | ||
|
|
df9c5d1d35 | ||
|
|
16cd2ae76e |
@@ -29,13 +29,14 @@ schedules:
|
||||
always: true
|
||||
branches:
|
||||
include:
|
||||
- stable-5
|
||||
- stable-7
|
||||
- stable-6
|
||||
- cron: 0 11 * * 0
|
||||
displayName: Weekly (old stable branches)
|
||||
always: true
|
||||
branches:
|
||||
include:
|
||||
- stable-4
|
||||
- stable-5
|
||||
|
||||
variables:
|
||||
- name: checkoutPath
|
||||
@@ -72,6 +73,19 @@ stages:
|
||||
- test: 3
|
||||
- test: 4
|
||||
- test: extra
|
||||
- stage: Sanity_2_15
|
||||
displayName: Sanity 2.15
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Test {0}
|
||||
testFormat: 2.15/sanity/{0}
|
||||
targets:
|
||||
- test: 1
|
||||
- test: 2
|
||||
- test: 3
|
||||
- test: 4
|
||||
- stage: Sanity_2_14
|
||||
displayName: Sanity 2.14
|
||||
dependsOn: []
|
||||
@@ -111,19 +125,6 @@ stages:
|
||||
- test: 2
|
||||
- test: 3
|
||||
- test: 4
|
||||
- stage: Sanity_2_11
|
||||
displayName: Sanity 2.11
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Test {0}
|
||||
testFormat: 2.11/sanity/{0}
|
||||
targets:
|
||||
- test: 1
|
||||
- test: 2
|
||||
- test: 3
|
||||
- test: 4
|
||||
### Units
|
||||
- stage: Units_devel
|
||||
displayName: Units devel
|
||||
@@ -142,6 +143,16 @@ stages:
|
||||
- test: 3.9
|
||||
- test: '3.10'
|
||||
- test: '3.11'
|
||||
- stage: Units_2_15
|
||||
displayName: Units 2.15
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Python {0}
|
||||
testFormat: 2.15/units/{0}/1
|
||||
targets:
|
||||
- test: "3.10"
|
||||
- stage: Units_2_14
|
||||
displayName: Units 2.14
|
||||
dependsOn: []
|
||||
@@ -151,7 +162,6 @@ stages:
|
||||
nameFormat: Python {0}
|
||||
testFormat: 2.14/units/{0}/1
|
||||
targets:
|
||||
- test: 2.7
|
||||
- test: 3.9
|
||||
- stage: Units_2_13
|
||||
displayName: Units 2.13
|
||||
@@ -175,19 +185,26 @@ stages:
|
||||
targets:
|
||||
- test: 2.6
|
||||
- test: 3.8
|
||||
- stage: Units_2_11
|
||||
displayName: Units 2.11
|
||||
|
||||
## Remote
|
||||
- stage: Remote_devel_extra_vms
|
||||
displayName: Remote devel extra VMs
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Python {0}
|
||||
testFormat: 2.11/units/{0}/1
|
||||
testFormat: devel/{0}
|
||||
targets:
|
||||
- test: 2.7
|
||||
- test: 3.5
|
||||
|
||||
## Remote
|
||||
- name: Alpine 3.17
|
||||
test: alpine/3.17
|
||||
# - name: Fedora 37
|
||||
# test: fedora/37
|
||||
# - name: Ubuntu 20.04
|
||||
# test: ubuntu/20.04
|
||||
- name: Ubuntu 22.04
|
||||
test: ubuntu/22.04
|
||||
groups:
|
||||
- vm
|
||||
- stage: Remote_devel
|
||||
displayName: Remote devel
|
||||
dependsOn: []
|
||||
@@ -196,14 +213,28 @@ stages:
|
||||
parameters:
|
||||
testFormat: devel/{0}
|
||||
targets:
|
||||
- name: macOS 12.0
|
||||
test: macos/12.0
|
||||
- name: macOS 13.2
|
||||
test: macos/13.2
|
||||
- name: RHEL 9.1
|
||||
test: rhel/9.1
|
||||
- name: FreeBSD 13.2
|
||||
test: freebsd/13.2
|
||||
- name: FreeBSD 12.4
|
||||
test: freebsd/12.4
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- stage: Remote_2_15
|
||||
displayName: Remote 2.15
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.15/{0}
|
||||
targets:
|
||||
- name: RHEL 7.9
|
||||
test: rhel/7.9
|
||||
- name: RHEL 9.0
|
||||
test: rhel/9.0
|
||||
- name: FreeBSD 12.3
|
||||
test: freebsd/12.3
|
||||
- name: FreeBSD 13.1
|
||||
test: freebsd/13.1
|
||||
groups:
|
||||
@@ -220,8 +251,8 @@ stages:
|
||||
targets:
|
||||
- name: RHEL 9.0
|
||||
test: rhel/9.0
|
||||
- name: FreeBSD 13.1
|
||||
test: freebsd/13.1
|
||||
- name: FreeBSD 12.3
|
||||
test: freebsd/12.3
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
@@ -260,22 +291,6 @@ stages:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- stage: Remote_2_11
|
||||
displayName: Remote 2.11
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.11/{0}
|
||||
targets:
|
||||
- name: RHEL 7.9
|
||||
test: rhel/7.9
|
||||
- name: RHEL 8.3
|
||||
test: rhel/8.3
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
|
||||
### Docker
|
||||
- stage: Docker_devel
|
||||
@@ -286,10 +301,8 @@ stages:
|
||||
parameters:
|
||||
testFormat: devel/linux/{0}
|
||||
targets:
|
||||
- name: CentOS 7
|
||||
test: centos7
|
||||
- name: Fedora 36
|
||||
test: fedora36
|
||||
- name: Fedora 37
|
||||
test: fedora37
|
||||
- name: openSUSE 15
|
||||
test: opensuse15
|
||||
- name: Ubuntu 20.04
|
||||
@@ -302,6 +315,20 @@ stages:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- stage: Docker_2_15
|
||||
displayName: Docker 2.15
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.15/linux/{0}
|
||||
targets:
|
||||
- name: CentOS 7
|
||||
test: centos7
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- stage: Docker_2_14
|
||||
displayName: Docker 2.14
|
||||
dependsOn: []
|
||||
@@ -310,8 +337,8 @@ stages:
|
||||
parameters:
|
||||
testFormat: 2.14/linux/{0}
|
||||
targets:
|
||||
- name: Ubuntu 20.04
|
||||
test: ubuntu2004
|
||||
- name: Fedora 36
|
||||
test: fedora36
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
@@ -352,24 +379,6 @@ stages:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- stage: Docker_2_11
|
||||
displayName: Docker 2.11
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.11/linux/{0}
|
||||
targets:
|
||||
- name: Fedora 32
|
||||
test: fedora32
|
||||
- name: Fedora 33
|
||||
test: fedora33
|
||||
- name: Alpine 3
|
||||
test: alpine3
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
|
||||
### Community Docker
|
||||
- stage: Docker_community_devel
|
||||
@@ -383,9 +392,9 @@ stages:
|
||||
- name: Debian Bullseye
|
||||
test: debian-bullseye/3.9
|
||||
- name: ArchLinux
|
||||
test: archlinux/3.10
|
||||
test: archlinux/3.11
|
||||
- name: CentOS Stream 8
|
||||
test: centos-stream8/3.8
|
||||
test: centos-stream8/3.9
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
@@ -403,6 +412,16 @@ stages:
|
||||
targets:
|
||||
- test: 2.7
|
||||
- test: '3.11'
|
||||
- stage: Generic_2_15
|
||||
displayName: Generic 2.15
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Python {0}
|
||||
testFormat: 2.15/generic/{0}/1
|
||||
targets:
|
||||
- test: 3.9
|
||||
- stage: Generic_2_14
|
||||
displayName: Generic 2.14
|
||||
dependsOn: []
|
||||
@@ -433,46 +452,37 @@ stages:
|
||||
testFormat: 2.12/generic/{0}/1
|
||||
targets:
|
||||
- test: 3.8
|
||||
- stage: Generic_2_11
|
||||
displayName: Generic 2.11
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Python {0}
|
||||
testFormat: 2.11/generic/{0}/1
|
||||
targets:
|
||||
- test: 2.7
|
||||
- test: 3.5
|
||||
|
||||
- stage: Summary
|
||||
condition: succeededOrFailed()
|
||||
dependsOn:
|
||||
- Sanity_devel
|
||||
- Sanity_2_11
|
||||
- Sanity_2_12
|
||||
- Sanity_2_13
|
||||
- Sanity_2_14
|
||||
- Sanity_2_15
|
||||
- Units_devel
|
||||
- Units_2_11
|
||||
- Units_2_12
|
||||
- Units_2_13
|
||||
- Units_2_14
|
||||
- Units_2_15
|
||||
- Remote_devel_extra_vms
|
||||
- Remote_devel
|
||||
- Remote_2_11
|
||||
- Remote_2_12
|
||||
- Remote_2_13
|
||||
- Remote_2_14
|
||||
- Remote_2_15
|
||||
- Docker_devel
|
||||
- Docker_2_11
|
||||
- Docker_2_12
|
||||
- Docker_2_13
|
||||
- Docker_2_14
|
||||
- Docker_2_15
|
||||
- Docker_community_devel
|
||||
- Generic_devel
|
||||
- Generic_2_11
|
||||
- Generic_2_12
|
||||
- Generic_2_13
|
||||
- Generic_2_14
|
||||
# Right now all generic tests are disabled. Uncomment when at least one of them is re-enabled.
|
||||
# - Generic_devel
|
||||
# - Generic_2_12
|
||||
# - Generic_2_13
|
||||
# - Generic_2_14
|
||||
# - Generic_2_15
|
||||
jobs:
|
||||
- template: templates/coverage.yml
|
||||
|
||||
71
.github/BOTMETA.yml
vendored
71
.github/BOTMETA.yml
vendored
@@ -241,6 +241,8 @@ files:
|
||||
$lookups/manifold.py:
|
||||
labels: manifold
|
||||
maintainers: galanoff
|
||||
$lookups/merge_variables.py:
|
||||
maintainers: rlenferink m-a-r-k-e
|
||||
$lookups/onepass:
|
||||
labels: onepassword
|
||||
maintainers: samdoran
|
||||
@@ -265,6 +267,10 @@ files:
|
||||
maintainers: delineaKrehl tylerezimmerman
|
||||
$module_utils/:
|
||||
labels: module_utils
|
||||
$module_utils/btrfs.py:
|
||||
maintainers: gnfzdz
|
||||
$module_utils/deps.py:
|
||||
maintainers: russoz
|
||||
$module_utils/gconftool2.py:
|
||||
labels: gconftool2
|
||||
maintainers: russoz
|
||||
@@ -279,15 +285,19 @@ files:
|
||||
maintainers: $team_huawei
|
||||
$module_utils/identity/keycloak/keycloak.py:
|
||||
maintainers: $team_keycloak
|
||||
$module_utils/identity/keycloak/keycloak_clientsecret.py:
|
||||
maintainers: $team_keycloak fynncfchen johncant
|
||||
$module_utils/ipa.py:
|
||||
labels: ipa
|
||||
maintainers: $team_ipa
|
||||
$module_utils/jenkins.py:
|
||||
labels: jenkins
|
||||
maintainers: russoz
|
||||
$module_utils/manageiq.py:
|
||||
labels: manageiq
|
||||
maintainers: $team_manageiq
|
||||
$module_utils/memset.py:
|
||||
labels: cloud memset
|
||||
maintainers: glitchcrab
|
||||
$module_utils/mh/:
|
||||
labels: module_helper
|
||||
maintainers: russoz
|
||||
@@ -302,6 +312,9 @@ files:
|
||||
$module_utils/pipx.py:
|
||||
labels: pipx
|
||||
maintainers: russoz
|
||||
$module_utils/puppet.py:
|
||||
labels: puppet
|
||||
maintainers: russoz
|
||||
$module_utils/pure.py:
|
||||
labels: pure pure_storage
|
||||
maintainers: $team_purestorage
|
||||
@@ -313,6 +326,8 @@ files:
|
||||
$module_utils/scaleway.py:
|
||||
labels: cloud scaleway
|
||||
maintainers: $team_scaleway
|
||||
$module_utils/ssh.py:
|
||||
maintainers: russoz
|
||||
$module_utils/storage/hpe3par/hpe3par.py:
|
||||
maintainers: farhan7500 gautamphegde
|
||||
$module_utils/utm_utils.py:
|
||||
@@ -382,6 +397,8 @@ files:
|
||||
maintainers: catcombo
|
||||
$modules/bower.py:
|
||||
maintainers: mwarkentin
|
||||
$modules/btrfs_:
|
||||
maintainers: gnfzdz
|
||||
$modules/bundler.py:
|
||||
maintainers: thoiberg
|
||||
$modules/bzr.py:
|
||||
@@ -428,7 +445,7 @@ files:
|
||||
labels: datadog_event
|
||||
maintainers: n0ts
|
||||
$modules/datadog_monitor.py:
|
||||
maintainers: skornehl
|
||||
ignore: skornehl
|
||||
$modules/dconf.py:
|
||||
maintainers: azaghal
|
||||
$modules/deploy_helper.py:
|
||||
@@ -522,8 +539,6 @@ files:
|
||||
maintainers: zimbatm
|
||||
$modules/gunicorn.py:
|
||||
maintainers: agmezr
|
||||
$modules/hana_query.py:
|
||||
maintainers: rainerleber
|
||||
$modules/haproxy.py:
|
||||
maintainers: ravibhure Normo
|
||||
$modules/heroku_collaborator.py:
|
||||
@@ -576,7 +591,7 @@ files:
|
||||
ignore: jose-delarosa
|
||||
maintainers: $team_redfish
|
||||
$modules/ilo_:
|
||||
ignore: jose-delarosa
|
||||
ignore: jose-delarosa varini-hp
|
||||
maintainers: $team_redfish
|
||||
$modules/imc_rest.py:
|
||||
labels: cisco
|
||||
@@ -608,6 +623,8 @@ files:
|
||||
maintainers: bregman-arie
|
||||
$modules/ipa_:
|
||||
maintainers: $team_ipa
|
||||
$modules/ipbase_info.py:
|
||||
maintainers: dominikkukacka
|
||||
$modules/ipa_pwpolicy.py:
|
||||
maintainers: adralioh
|
||||
$modules/ipa_service.py:
|
||||
@@ -655,16 +672,26 @@ files:
|
||||
ignore: DWSR
|
||||
labels: jira
|
||||
maintainers: Slezhuk tarka pertoft
|
||||
$modules/kdeconfig.py:
|
||||
maintainers: smeso
|
||||
$modules/kernel_blacklist.py:
|
||||
maintainers: matze
|
||||
$modules/keycloak_:
|
||||
maintainers: $team_keycloak
|
||||
$modules/keycloak_authentication.py:
|
||||
maintainers: elfelip Gaetan2907
|
||||
$modules/keycloak_authz_authorization_scope.py:
|
||||
maintainers: mattock
|
||||
$modules/keycloak_client_rolemapping.py:
|
||||
maintainers: Gaetan2907
|
||||
$modules/keycloak_clientscope.py:
|
||||
maintainers: Gaetan2907
|
||||
$modules/keycloak_clientscope_type.py:
|
||||
maintainers: simonpahl
|
||||
$modules/keycloak_clientsecret_info.py:
|
||||
maintainers: fynncfchen johncant
|
||||
$modules/keycloak_clientsecret_regenerate.py:
|
||||
maintainers: fynncfchen johncant
|
||||
$modules/keycloak_group.py:
|
||||
maintainers: adamgoossens
|
||||
$modules/keycloak_identity_provider.py:
|
||||
@@ -769,7 +796,7 @@ files:
|
||||
labels: maven_artifact
|
||||
maintainers: tumbl3w33d turb
|
||||
$modules/memset_:
|
||||
maintainers: glitchcrab
|
||||
ignore: glitchcrab
|
||||
$modules/mksysb.py:
|
||||
labels: aix mksysb
|
||||
maintainers: $team_aix
|
||||
@@ -814,6 +841,10 @@ files:
|
||||
maintainers: shane-walker xcambar
|
||||
$modules/nsupdate.py:
|
||||
maintainers: nerzhul
|
||||
$modules/ocapi_command.py:
|
||||
maintainers: $team_wdc
|
||||
$modules/ocapi_info.py:
|
||||
maintainers: $team_wdc
|
||||
$modules/oci_vcn.py:
|
||||
maintainers: $team_oracle rohitChaware
|
||||
$modules/odbc.py:
|
||||
@@ -822,7 +853,8 @@ files:
|
||||
maintainers: marc-sensenich
|
||||
$modules/ohai.py:
|
||||
labels: ohai
|
||||
maintainers: $team_ansible_core mpdehaan
|
||||
maintainers: $team_ansible_core
|
||||
ignore: mpdehaan
|
||||
$modules/omapi_host.py:
|
||||
maintainers: amasolov nerzhul
|
||||
$modules/one_:
|
||||
@@ -966,7 +998,7 @@ files:
|
||||
maintainers: sysadmind
|
||||
$modules/puppet.py:
|
||||
labels: puppet
|
||||
maintainers: nibalizer emonty
|
||||
maintainers: emonty
|
||||
$modules/pushbullet.py:
|
||||
maintainers: willybarro
|
||||
$modules/pushover.py:
|
||||
@@ -1018,10 +1050,11 @@ files:
|
||||
maintainers: dagwieers
|
||||
$modules/redfish_:
|
||||
ignore: jose-delarosa
|
||||
maintainers: $team_redfish
|
||||
maintainers: $team_redfish TSKushal
|
||||
$modules/redhat_subscription.py:
|
||||
labels: redhat_subscription
|
||||
maintainers: barnabycourt alikins kahowell
|
||||
maintainers: $team_rhsm
|
||||
ignore: barnabycourt alikins kahowell
|
||||
$modules/redis.py:
|
||||
maintainers: slok
|
||||
$modules/redis_data.py:
|
||||
@@ -1044,9 +1077,9 @@ files:
|
||||
labels: rhn_register
|
||||
maintainers: jlaska $team_rhn
|
||||
$modules/rhsm_release.py:
|
||||
maintainers: seandst
|
||||
maintainers: seandst $team_rhsm
|
||||
$modules/rhsm_repository.py:
|
||||
maintainers: giovannisciortino
|
||||
maintainers: giovannisciortino $team_rhsm
|
||||
$modules/riak.py:
|
||||
maintainers: drewkerrigan jsmartin
|
||||
$modules/rocketchat.py:
|
||||
@@ -1067,12 +1100,9 @@ files:
|
||||
maintainers: nerzhul
|
||||
$modules/runit.py:
|
||||
maintainers: jsumners
|
||||
$modules/sap_task_list_execute:
|
||||
maintainers: rainerleber
|
||||
$modules/sapcar_extract.py:
|
||||
maintainers: RainerLeber
|
||||
$modules/say.py:
|
||||
maintainers: $team_ansible_core mpdehaan
|
||||
maintainers: $team_ansible_core
|
||||
ignore: mpdehaan
|
||||
$modules/scaleway_:
|
||||
maintainers: $team_scaleway
|
||||
$modules/scaleway_compute_private_network.py:
|
||||
@@ -1298,7 +1328,7 @@ files:
|
||||
labels: m:xml xml
|
||||
maintainers: dagwieers magnus919 tbielawa cmprescott sm4rk0
|
||||
$modules/yarn.py:
|
||||
maintainers: chrishoffman verkaufer
|
||||
ignore: chrishoffman verkaufer
|
||||
$modules/yum_versionlock.py:
|
||||
maintainers: gyptazy aminvakil
|
||||
$modules/zfs:
|
||||
@@ -1364,7 +1394,7 @@ macros:
|
||||
team_huawei: QijunPan TommyLike edisonxiang freesky-edward hwDCN niuzhenguo xuxiaowei0512 yanzhangi zengchen1024 zhongjun2
|
||||
team_ipa: Akasurde Nosmoht fxfitz justchris1
|
||||
team_jboss: Wolfant jairojunior wbrefvem
|
||||
team_keycloak: eikef ndclt
|
||||
team_keycloak: eikef ndclt mattock
|
||||
team_linode: InTheCloudDan decentral1se displague rmcintosh Charliekenney23 LBGarber
|
||||
team_macos: Akasurde kyleabenson martinm82 danieljaouen indrajitr
|
||||
team_manageiq: abellotti cben gtanzillo yaacov zgalor dkorn evertmulder
|
||||
@@ -1372,8 +1402,9 @@ macros:
|
||||
team_opennebula: ilicmilan meerkampdvv rsmontero xorel nilsding
|
||||
team_oracle: manojmeda mross22 nalsaber
|
||||
team_purestorage: bannaych dnix101 genegr lionmax opslounge raekins sdodsley sile16
|
||||
team_redfish: mraineri tomasg2012 xmadsen renxulei rajeevkallur bhavya06
|
||||
team_redfish: mraineri tomasg2012 xmadsen renxulei rajeevkallur bhavya06 jyundt
|
||||
team_rhn: FlossWare alikins barnabycourt vritant
|
||||
team_rhsm: cnsnyder ptoscano
|
||||
team_scaleway: remyleone abarbare
|
||||
team_solaris: bcoca fishman jasperla jpdasma mator scathatheworm troy2914 xen0l
|
||||
team_suse: commel evrardjp lrupp toabctl AnderEnder alxgu andytom sealor
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -47,7 +47,7 @@ body:
|
||||
label: Component Name
|
||||
description: >-
|
||||
Write the short name of the module, plugin, task or feature below,
|
||||
*use your best guess if unsure*.
|
||||
*use your best guess if unsure*. Do not include `community.general.`!
|
||||
placeholder: dnf, apt, yum, pip, user etc.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -46,8 +46,8 @@ body:
|
||||
attributes:
|
||||
label: Component Name
|
||||
description: >-
|
||||
Write the short name of the rst file, module, plugin, task or
|
||||
feature below, *use your best guess if unsure*.
|
||||
Write the short name of the file, module, plugin, task or feature below,
|
||||
*use your best guess if unsure*. Do not include `community.general.`!
|
||||
placeholder: mysql_user
|
||||
validations:
|
||||
required: true
|
||||
|
||||
4
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
4
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@@ -42,8 +42,8 @@ body:
|
||||
attributes:
|
||||
label: Component Name
|
||||
description: >-
|
||||
Write the short name of the module, plugin, task or feature below,
|
||||
*use your best guess if unsure*.
|
||||
Write the short name of the module or plugin, or which other part(s) of the collection this feature affects.
|
||||
*use your best guess if unsure*. Do not include `community.general.`!
|
||||
placeholder: dnf, apt, yum, pip, user etc.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
32
.github/pull_request_template.md
vendored
Normal file
32
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
##### SUMMARY
|
||||
<!--- Describe the change below, including rationale and design decisions -->
|
||||
|
||||
<!--- HINT: Include "Fixes #nnn" if you are fixing an existing issue -->
|
||||
|
||||
<!--- Please do not forget to include a changelog fragment:
|
||||
https://docs.ansible.com/ansible/devel/community/collection_development_process.html#creating-changelog-fragments
|
||||
No need to include one for docs-only or test-only PR, and for new plugin/module PRs.
|
||||
Read about more details in CONTRIBUTING.md.
|
||||
-->
|
||||
|
||||
##### ISSUE TYPE
|
||||
<!--- Pick one or more below and delete the rest.
|
||||
'Test Pull Request' is for PRs that add/extend tests without code changes. -->
|
||||
- Bugfix Pull Request
|
||||
- Docs Pull Request
|
||||
- Feature Pull Request
|
||||
- New Module/Plugin Pull Request
|
||||
- Refactoring Pull Request
|
||||
- Test Pull Request
|
||||
|
||||
##### COMPONENT NAME
|
||||
<!--- Write the SHORT NAME of the module, plugin, task or feature below. -->
|
||||
|
||||
##### ADDITIONAL INFORMATION
|
||||
<!--- Include additional information to help people understand the change here -->
|
||||
<!--- A step-by-step reproduction of the problem is helpful if there is no related issue -->
|
||||
|
||||
<!--- Paste verbatim command output below, e.g. before and after your change -->
|
||||
```paste below
|
||||
|
||||
```
|
||||
3
.github/pull_request_template.md.license
vendored
Normal file
3
.github/pull_request_template.md.license
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
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
|
||||
193
.github/workflows/ansible-test.yml
vendored
Normal file
193
.github/workflows/ansible-test.yml
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
---
|
||||
# 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
|
||||
|
||||
# For the comprehensive list of the inputs supported by the ansible-community/ansible-test-gh-action GitHub Action, see
|
||||
# https://github.com/marketplace/actions/ansible-test
|
||||
|
||||
name: EOL CI
|
||||
on:
|
||||
# Run EOL CI against all pushes (direct commits, also merged PRs), Pull Requests
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- stable-*
|
||||
pull_request:
|
||||
# Run EOL CI once per day (at 08:00 UTC)
|
||||
schedule:
|
||||
- cron: '0 8 * * *'
|
||||
|
||||
concurrency:
|
||||
# Make sure there is at most one active run per PR, but do not cancel any non-PR runs
|
||||
group: ${{ github.workflow }}-${{ (github.head_ref && github.event.number) || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
sanity:
|
||||
name: EOL Sanity (Ⓐ${{ matrix.ansible }})
|
||||
strategy:
|
||||
matrix:
|
||||
ansible:
|
||||
- '2.11'
|
||||
# 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
|
||||
# shrink over time, check out https://github.com/ansible-collections/news-for-maintainers/issues/28
|
||||
# for the latest list.
|
||||
runs-on: >-
|
||||
${{ contains(fromJson(
|
||||
'["2.9", "2.10", "2.11"]'
|
||||
), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }}
|
||||
steps:
|
||||
- name: Perform sanity testing
|
||||
uses: felixfontein/ansible-test-gh-action@main
|
||||
with:
|
||||
ansible-core-github-repository-slug: felixfontein/ansible
|
||||
ansible-core-version: stable-${{ matrix.ansible }}
|
||||
coverage: ${{ github.event_name == 'schedule' && 'always' || 'never' }}
|
||||
pull-request-change-detection: 'true'
|
||||
testing-type: sanity
|
||||
|
||||
units:
|
||||
# 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
|
||||
# shrink over time, check out https://github.com/ansible-collections/news-for-maintainers/issues/28
|
||||
# for the latest list.
|
||||
runs-on: >-
|
||||
${{ contains(fromJson(
|
||||
'["2.9", "2.10", "2.11"]'
|
||||
), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }}
|
||||
name: EOL Units (Ⓐ${{ matrix.ansible }}+py${{ matrix.python }})
|
||||
strategy:
|
||||
# As soon as the first unit test fails, cancel the others to free up the CI queue
|
||||
fail-fast: true
|
||||
matrix:
|
||||
ansible:
|
||||
- ''
|
||||
python:
|
||||
- ''
|
||||
exclude:
|
||||
- ansible: ''
|
||||
include:
|
||||
- ansible: '2.11'
|
||||
python: '2.7'
|
||||
- ansible: '2.11'
|
||||
python: '3.5'
|
||||
|
||||
steps:
|
||||
- name: >-
|
||||
Perform unit testing against
|
||||
Ansible version ${{ matrix.ansible }}
|
||||
uses: felixfontein/ansible-test-gh-action@main
|
||||
with:
|
||||
ansible-core-github-repository-slug: felixfontein/ansible
|
||||
ansible-core-version: stable-${{ matrix.ansible }}
|
||||
coverage: ${{ github.event_name == 'schedule' && 'always' || 'never' }}
|
||||
pre-test-cmd: >-
|
||||
mkdir -p ../../ansible
|
||||
;
|
||||
git clone --depth=1 --single-branch https://github.com/ansible-collections/community.internal_test_tools.git ../../community/internal_test_tools
|
||||
pull-request-change-detection: 'true'
|
||||
target-python-version: ${{ matrix.python }}
|
||||
testing-type: units
|
||||
|
||||
integration:
|
||||
# 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
|
||||
# shrink over time, check out https://github.com/ansible-collections/news-for-maintainers/issues/28
|
||||
# for the latest list.
|
||||
runs-on: >-
|
||||
${{ contains(fromJson(
|
||||
'["2.9", "2.10", "2.11"]'
|
||||
), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }}
|
||||
name: EOL I (Ⓐ${{ matrix.ansible }}+${{ matrix.docker }}+py${{ matrix.python }}:${{ matrix.target }})
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
ansible:
|
||||
- ''
|
||||
docker:
|
||||
- ''
|
||||
python:
|
||||
- ''
|
||||
target:
|
||||
- ''
|
||||
exclude:
|
||||
- ansible: ''
|
||||
include:
|
||||
# 2.11
|
||||
- ansible: '2.11'
|
||||
docker: fedora32
|
||||
python: ''
|
||||
target: azp/posix/1/
|
||||
- ansible: '2.11'
|
||||
docker: fedora32
|
||||
python: ''
|
||||
target: azp/posix/2/
|
||||
- ansible: '2.11'
|
||||
docker: fedora32
|
||||
python: ''
|
||||
target: azp/posix/3/
|
||||
- ansible: '2.11'
|
||||
docker: fedora33
|
||||
python: ''
|
||||
target: azp/posix/1/
|
||||
- ansible: '2.11'
|
||||
docker: fedora33
|
||||
python: ''
|
||||
target: azp/posix/2/
|
||||
- ansible: '2.11'
|
||||
docker: fedora33
|
||||
python: ''
|
||||
target: azp/posix/3/
|
||||
- ansible: '2.11'
|
||||
docker: alpine3
|
||||
python: ''
|
||||
target: azp/posix/1/
|
||||
- ansible: '2.11'
|
||||
docker: alpine3
|
||||
python: ''
|
||||
target: azp/posix/2/
|
||||
- ansible: '2.11'
|
||||
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.11'
|
||||
# docker: default
|
||||
# python: '2.7'
|
||||
# target: azp/generic/1/
|
||||
# - ansible: '2.11'
|
||||
# docker: default
|
||||
# python: '3.5'
|
||||
# target: azp/generic/2/
|
||||
|
||||
steps:
|
||||
- name: >-
|
||||
Perform integration testing against
|
||||
Ansible version ${{ matrix.ansible }}
|
||||
under Python ${{ matrix.python }}
|
||||
uses: felixfontein/ansible-test-gh-action@main
|
||||
with:
|
||||
ansible-core-github-repository-slug: felixfontein/ansible
|
||||
ansible-core-version: stable-${{ matrix.ansible }}
|
||||
coverage: ${{ github.event_name == 'schedule' && 'always' || 'never' }}
|
||||
docker-image: ${{ matrix.docker }}
|
||||
integration-continue-on-error: 'false'
|
||||
integration-diff: 'false'
|
||||
integration-retry-on-error: 'true'
|
||||
pre-test-cmd: >-
|
||||
mkdir -p ../../ansible
|
||||
;
|
||||
git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.posix.git ../../ansible/posix
|
||||
;
|
||||
git clone --depth=1 --single-branch https://github.com/ansible-collections/community.crypto.git ../../community/crypto
|
||||
;
|
||||
git clone --depth=1 --single-branch https://github.com/ansible-collections/community.internal_test_tools.git ../../community/internal_test_tools
|
||||
pull-request-change-detection: 'true'
|
||||
target: ${{ matrix.target }}
|
||||
target-python-version: ${{ matrix.python }}
|
||||
testing-type: integration
|
||||
31
.github/workflows/codeql-analysis.yml
vendored
31
.github/workflows/codeql-analysis.yml
vendored
@@ -8,6 +8,7 @@ name: "Code scanning - action"
|
||||
on:
|
||||
schedule:
|
||||
- cron: '26 19 * * 1'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -24,38 +25,12 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
fetch-depth: 2
|
||||
|
||||
# If this run was triggered by a pull request event, then checkout
|
||||
# the head of the pull request instead of the merge commit.
|
||||
- run: git checkout HEAD^2
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
# Override language selection by uncommenting this and choosing your languages
|
||||
# with:
|
||||
# languages: go, javascript, csharp, python, cpp, java
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
with:
|
||||
languages: python
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
||||
93
.github/workflows/docs-pr.yml
vendored
93
.github/workflows/docs-pr.yml
vendored
@@ -1,93 +0,0 @@
|
||||
---
|
||||
# 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: Collection Docs
|
||||
concurrency:
|
||||
group: docs-${{ github.head_ref }}
|
||||
cancel-in-progress: true
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, reopened, closed]
|
||||
paths-ignore:
|
||||
- '.azure-pipelines/**'
|
||||
- 'changelogs/**'
|
||||
- 'meta/**'
|
||||
- 'tests/**'
|
||||
|
||||
jobs:
|
||||
build-docs:
|
||||
permissions:
|
||||
contents: read
|
||||
name: Build Ansible Docs
|
||||
uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-pr.yml@main
|
||||
with:
|
||||
init-fail-on-error: true
|
||||
provide-link-targets: |
|
||||
ansible_collections.ansible.builtin.dict2items_filter
|
||||
ansible_collections.ansible.builtin.items_lookup
|
||||
ansible_collections.ansible.builtin.path_join_filter
|
||||
ansible_collections.community.kubevirt.kubevirt_cdi_upload_module
|
||||
ansible_collections.community.kubevirt.kubevirt_inventory
|
||||
ansible_collections.community.kubevirt.kubevirt_preset_module
|
||||
ansible_collections.community.kubevirt.kubevirt_pvc_module
|
||||
ansible_collections.community.kubevirt.kubevirt_rs_module
|
||||
ansible_collections.community.kubevirt.kubevirt_template_module
|
||||
ansible_collections.community.kubevirt.kubevirt_vm_module
|
||||
ansible_collections.infoblox.nios_modules.nios_a_record_module
|
||||
ansible_collections.infoblox.nios_modules.nios_aaaa_record_module
|
||||
ansible_collections.infoblox.nios_modules.nios_cname_record_module
|
||||
ansible_collections.infoblox.nios_modules.nios_dns_view_module
|
||||
ansible_collections.infoblox.nios_modules.nios_fixed_address_module
|
||||
ansible_collections.infoblox.nios_modules.nios_host_record_module
|
||||
ansible_collections.infoblox.nios_modules.nios_lookup_lookup
|
||||
ansible_collections.infoblox.nios_modules.nios_member_module
|
||||
ansible_collections.infoblox.nios_modules.nios_mx_record_module
|
||||
ansible_collections.infoblox.nios_modules.nios_naptr_record_module
|
||||
ansible_collections.infoblox.nios_modules.nios_network_module
|
||||
ansible_collections.infoblox.nios_modules.nios_network_view_module
|
||||
ansible_collections.infoblox.nios_modules.nios_next_ip_lookup
|
||||
ansible_collections.infoblox.nios_modules.nios_next_network_lookup
|
||||
ansible_collections.infoblox.nios_modules.nios_nsgroup_module
|
||||
ansible_collections.infoblox.nios_modules.nios_ptr_record_module
|
||||
ansible_collections.infoblox.nios_modules.nios_srv_record_module
|
||||
ansible_collections.infoblox.nios_modules.nios_txt_record_module
|
||||
ansible_collections.infoblox.nios_modules.nios_zone_module
|
||||
|
||||
comment:
|
||||
permissions:
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-docs
|
||||
name: PR comments
|
||||
steps:
|
||||
- name: PR comment
|
||||
uses: ansible-community/github-docs-build/actions/ansible-docs-build-comment@main
|
||||
with:
|
||||
body-includes: '## Docs Build'
|
||||
reactions: heart
|
||||
action: ${{ needs.build-docs.outputs.changed != 'true' && 'remove' || '' }}
|
||||
on-closed-body: |
|
||||
## Docs Build 📝
|
||||
|
||||
This PR is closed and any previously published docsite has been unpublished.
|
||||
on-merged-body: |
|
||||
## Docs Build 📝
|
||||
|
||||
Thank you for contribution!✨
|
||||
|
||||
This PR has been merged and your docs changes will be incorporated when they are next published.
|
||||
body: |
|
||||
## Docs Build 📝
|
||||
|
||||
Thank you for contribution!✨
|
||||
|
||||
The docsite for **this PR** is available for download as an artifact from this run:
|
||||
${{ needs.build-docs.outputs.artifact-url }}
|
||||
|
||||
File changes:
|
||||
|
||||
${{ needs.build-docs.outputs.diff-files-rendered }}
|
||||
|
||||
${{ needs.build-docs.outputs.diff-rendered }}
|
||||
495
CHANGELOG.rst
495
CHANGELOG.rst
@@ -4,233 +4,326 @@ Community General Release Notes
|
||||
|
||||
.. contents:: Topics
|
||||
|
||||
This changelog describes changes after version 5.0.0.
|
||||
This changelog describes changes after version 6.0.0.
|
||||
|
||||
v6.0.0-a1
|
||||
=========
|
||||
v7.0.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
This is a pre-release for the upcoming 6.0.0 major release. The main objective of this pre-release is to make it possible to test the large stuctural changes by flattening the directory structure. See the corresponding entry in the changelog for details.
|
||||
|
||||
Major Changes
|
||||
-------------
|
||||
|
||||
- The internal structure of the collection was changed for modules and action plugins. These no longer live in a directory hierarchy ordered by topic, but instead are now all in a single (flat) directory. This has no impact on users *assuming they did not use internal FQCNs*. These will still work, but result in deprecation warnings. They were never officially supported and thus the redirects are kept as a courtsey, and this is not labelled as a breaking change. Note that for example the Ansible VScode plugin started recommending these internal names. If you followed its recommendation, you will now have to change back to the short names to avoid deprecation warnings, and potential errors in the future as these redirects will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5461).
|
||||
- newrelic_deployment - removed New Relic v1 API, added support for v2 API (https://github.com/ansible-collections/community.general/pull/5341).
|
||||
This is release 7.0.0 of ``community.general``, released on 2023-05-09.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Added MIT license as ``LICENSES/MIT.txt`` for tests/unit/plugins/modules/packaging/language/test_gem.py (https://github.com/ansible-collections/community.general/pull/5065).
|
||||
- All software licenses are now in the ``LICENSES/`` directory of the collection root (https://github.com/ansible-collections/community.general/pull/5065, https://github.com/ansible-collections/community.general/pull/5079, https://github.com/ansible-collections/community.general/pull/5080, https://github.com/ansible-collections/community.general/pull/5083, https://github.com/ansible-collections/community.general/pull/5087, https://github.com/ansible-collections/community.general/pull/5095, https://github.com/ansible-collections/community.general/pull/5098, https://github.com/ansible-collections/community.general/pull/5106).
|
||||
- ModuleHelper module utils - added property ``verbosity`` to base class (https://github.com/ansible-collections/community.general/pull/5035).
|
||||
- ModuleHelper module utils - improved ``ModuleHelperException``, using ``to_native()`` for the exception message (https://github.com/ansible-collections/community.general/pull/4755).
|
||||
- The collection repository conforms to the `REUSE specification <https://reuse.software/spec/>`__ except for the changelog fragments (https://github.com/ansible-collections/community.general/pull/5138).
|
||||
- ali_instance - minor refactor when checking for installed dependency (https://github.com/ansible-collections/community.general/pull/5240).
|
||||
- ali_instance_info - minor refactor when checking for installed dependency (https://github.com/ansible-collections/community.general/pull/5240).
|
||||
- alternatives - add ``state=absent`` to be able to remove an alternative (https://github.com/ansible-collections/community.general/pull/4654).
|
||||
- alternatives - add ``subcommands`` parameter (https://github.com/ansible-collections/community.general/pull/4654).
|
||||
- ansible_galaxy_install - minor refactoring using latest ``ModuleHelper`` updates (https://github.com/ansible-collections/community.general/pull/4752).
|
||||
- apk - add ``world`` parameter for supporting a custom world file (https://github.com/ansible-collections/community.general/pull/4976).
|
||||
- bitwarden lookup plugin - add option ``search`` to search for other attributes than name (https://github.com/ansible-collections/community.general/pull/5297).
|
||||
- cartesian lookup plugin - start using Ansible's configuration manager to parse options (https://github.com/ansible-collections/community.general/pull/5440).
|
||||
- cmd_runner module util - added parameters ``check_mode_skip`` and ``check_mode_return`` to ``CmdRunner.context()``, so that the command is not executed when ``check_mode=True`` (https://github.com/ansible-collections/community.general/pull/4736).
|
||||
- cmd_runner module utils - add ``__call__`` method to invoke context (https://github.com/ansible-collections/community.general/pull/4791).
|
||||
- consul - adds ``ttl`` parameter for session (https://github.com/ansible-collections/community.general/pull/4996).
|
||||
- consul - minor refactoring (https://github.com/ansible-collections/community.general/pull/5367).
|
||||
- consul_session - adds ``token`` parameter for session (https://github.com/ansible-collections/community.general/pull/5193).
|
||||
- cpanm - using ``do_raise()`` to raise exceptions in ``ModuleHelper`` derived modules (https://github.com/ansible-collections/community.general/pull/4674).
|
||||
- credstash lookup plugin - start using Ansible's configuration manager to parse options (https://github.com/ansible-collections/community.general/pull/5440).
|
||||
- dependent lookup plugin - start using Ansible's configuration manager to parse options (https://github.com/ansible-collections/community.general/pull/5440).
|
||||
- dig lookup plugin - add option ``fail_on_error`` to allow stopping execution on lookup failures (https://github.com/ansible-collections/community.general/pull/4973).
|
||||
- dig lookup plugin - start using Ansible's configuration manager to parse options. All documented options can now also be passed as lookup parameters (https://github.com/ansible-collections/community.general/pull/5440).
|
||||
- dnstxt lookup plugin - start using Ansible's configuration manager to parse options (https://github.com/ansible-collections/community.general/pull/5440).
|
||||
- filetree lookup plugin - start using Ansible's configuration manager to parse options (https://github.com/ansible-collections/community.general/pull/5440).
|
||||
- flattened lookup plugin - start using Ansible's configuration manager to parse options (https://github.com/ansible-collections/community.general/pull/5440).
|
||||
- gitlab module util - minor refactor when checking for installed dependency (https://github.com/ansible-collections/community.general/pull/5259).
|
||||
- gitlab_branch - minor refactor when checking for installed dependency (https://github.com/ansible-collections/community.general/pull/5259).
|
||||
- gitlab_deploy_key - minor refactor when checking for installed dependency (https://github.com/ansible-collections/community.general/pull/5259).
|
||||
- gitlab_group - minor refactor when checking for installed dependency (https://github.com/ansible-collections/community.general/pull/5259).
|
||||
- gitlab_group_members - minor refactor when checking for installed dependency (https://github.com/ansible-collections/community.general/pull/5259).
|
||||
- gitlab_group_variable - minor refactor when checking for installed dependency (https://github.com/ansible-collections/community.general/pull/5259).
|
||||
- gitlab_hook - minor refactor when checking for installed dependency (https://github.com/ansible-collections/community.general/pull/5259).
|
||||
- gitlab_hook - minor refactoring (https://github.com/ansible-collections/community.general/pull/5271).
|
||||
- gitlab_project - minor refactor when checking for installed dependency (https://github.com/ansible-collections/community.general/pull/5259).
|
||||
- gitlab_project_members - minor refactor when checking for installed dependency (https://github.com/ansible-collections/community.general/pull/5259).
|
||||
- gitlab_project_variable - minor refactor when checking for installed dependency (https://github.com/ansible-collections/community.general/pull/5259).
|
||||
- gitlab_protected_branch - minor refactor when checking for installed dependency (https://github.com/ansible-collections/community.general/pull/5259).
|
||||
- gitlab_runner - minor refactor when checking for installed dependency (https://github.com/ansible-collections/community.general/pull/5259).
|
||||
- gitlab_user - minor refactor when checking for installed dependency (https://github.com/ansible-collections/community.general/pull/5259).
|
||||
- hiera lookup plugin - start using Ansible's configuration manager to parse options. The Hiera executable and config file can now also be passed as lookup parameters (https://github.com/ansible-collections/community.general/pull/5440).
|
||||
- homebrew, homebrew_tap - added Homebrew on Linux path to defaults (https://github.com/ansible-collections/community.general/pull/5241).
|
||||
- keycloak_* modules - add ``http_agent`` parameter with default value ``Ansible`` (https://github.com/ansible-collections/community.general/issues/5023).
|
||||
- keyring lookup plugin - start using Ansible's configuration manager to parse options (https://github.com/ansible-collections/community.general/pull/5440).
|
||||
- lastpass - use config manager for handling plugin options (https://github.com/ansible-collections/community.general/pull/5022).
|
||||
- linode inventory plugin - simplify option handling (https://github.com/ansible-collections/community.general/pull/5438).
|
||||
- listen_ports_facts - add new ``include_non_listening`` option which adds ``-a`` option to ``netstat`` and ``ss``. This shows both listening and non-listening (for TCP this means established connections) sockets, and returns ``state`` and ``foreign_address`` (https://github.com/ansible-collections/community.general/issues/4762, https://github.com/ansible-collections/community.general/pull/4953).
|
||||
- lmdb_kv lookup plugin - start using Ansible's configuration manager to parse options (https://github.com/ansible-collections/community.general/pull/5440).
|
||||
- lxc_container - minor refactoring (https://github.com/ansible-collections/community.general/pull/5358).
|
||||
- machinectl become plugin - can now be used with a password from another user than root, if a polkit rule is present (https://github.com/ansible-collections/community.general/pull/4849).
|
||||
- machinectl become plugin - combine the success command when building the become command to be consistent with other become plugins (https://github.com/ansible-collections/community.general/pull/5287).
|
||||
- manifold lookup plugin - start using Ansible's configuration manager to parse options (https://github.com/ansible-collections/community.general/pull/5440).
|
||||
- maven_artifact - add a new ``unredirected_headers`` option that can be used with ansible-core 2.12 and above. The default value is to not use ``Authorization`` and ``Cookie`` headers on redirects for security reasons. With ansible-core 2.11, all headers are still passed on for redirects (https://github.com/ansible-collections/community.general/pull/4812).
|
||||
- mksysb - using ``do_raise()`` to raise exceptions in ``ModuleHelper`` derived modules (https://github.com/ansible-collections/community.general/pull/4674).
|
||||
- nagios - minor refactoring on parameter validation for different actions (https://github.com/ansible-collections/community.general/pull/5239).
|
||||
- netcup_dnsapi - add ``timeout`` parameter (https://github.com/ansible-collections/community.general/pull/5301).
|
||||
- nmcli - add ``transport_mode`` configuration for Infiniband devices (https://github.com/ansible-collections/community.general/pull/5361).
|
||||
- nmcli - add bond option ``xmit_hash_policy`` to bond options (https://github.com/ansible-collections/community.general/issues/5148).
|
||||
- nmcli - adds ``vpn`` type and parameter for supporting VPN with service type L2TP and PPTP (https://github.com/ansible-collections/community.general/pull/4746).
|
||||
- nmcli - honor IP options for VPNs (https://github.com/ansible-collections/community.general/pull/5228).
|
||||
- opentelemetry callback plugin - allow configuring opentelementry callback via config file (https://github.com/ansible-collections/community.general/pull/4916).
|
||||
- opentelemetry callback plugin - send logs. This can be disabled by setting ``disable_logs=false`` (https://github.com/ansible-collections/community.general/pull/4175).
|
||||
- pacman - added parameters ``reason`` and ``reason_for`` to set/change the install reason of packages (https://github.com/ansible-collections/community.general/pull/4956).
|
||||
- passwordstore lookup plugin - allow options to be passed lookup options instead of being part of the term strings (https://github.com/ansible-collections/community.general/pull/5444).
|
||||
- passwordstore lookup plugin - allow using alternative password managers by detecting wrapper scripts, allow explicit configuration of pass and gopass backends (https://github.com/ansible-collections/community.general/issues/4766).
|
||||
- passwordstore lookup plugin - improve error messages to include stderr (https://github.com/ansible-collections/community.general/pull/5436)
|
||||
- pipx - added state ``latest`` to the module (https://github.com/ansible-collections/community.general/pull/5105).
|
||||
- pipx - changed implementation to use ``cmd_runner`` (https://github.com/ansible-collections/community.general/pull/5085).
|
||||
- pipx - module fails faster when ``name`` is missing for states ``upgrade`` and ``reinstall`` (https://github.com/ansible-collections/community.general/pull/5100).
|
||||
- pipx - using ``do_raise()`` to raise exceptions in ``ModuleHelper`` derived modules (https://github.com/ansible-collections/community.general/pull/4674).
|
||||
- pipx module utils - created new module util ``pipx`` providing a ``cmd_runner`` specific for the ``pipx`` module (https://github.com/ansible-collections/community.general/pull/5085).
|
||||
- portage - add knobs for Portage's ``--backtrack`` and ``--with-bdeps`` options (https://github.com/ansible-collections/community.general/pull/5349).
|
||||
- portage - use Portage's python module instead of calling gentoolkit-provided program in shell (https://github.com/ansible-collections/community.general/pull/5349).
|
||||
- proxmox inventory plugin - added new flag ``qemu_extended_statuses`` and new groups ``<group_prefix>prelaunch``, ``<group_prefix>paused``. They will be populated only when ``want_facts=true``, ``qemu_extended_statuses=true`` and only for ``QEMU`` machines (https://github.com/ansible-collections/community.general/pull/4723).
|
||||
- proxmox inventory plugin - simplify option handling code (https://github.com/ansible-collections/community.general/pull/5437).
|
||||
- proxmox module utils, the proxmox* modules - add ``api_task_ok`` helper to standardize API task status checks across all proxmox modules (https://github.com/ansible-collections/community.general/pull/5274).
|
||||
- proxmox_kvm - allow ``agent`` argument to be a string (https://github.com/ansible-collections/community.general/pull/5107).
|
||||
- proxmox_snap - add ``unbind`` param to support snapshotting containers with configured mountpoints (https://github.com/ansible-collections/community.general/pull/5274).
|
||||
- puppet - adds ``confdir`` parameter to configure a custom confir location (https://github.com/ansible-collections/community.general/pull/4740).
|
||||
- redfish - added new command GetVirtualMedia, VirtualMediaInsert and VirtualMediaEject to Systems category due to Redfish spec changes the virtualMedia resource location from Manager to System (https://github.com/ansible-collections/community.general/pull/5124).
|
||||
- redfish_config - add ``SetSessionService`` to set default session timeout policy (https://github.com/ansible-collections/community.general/issues/5008).
|
||||
- redfish_info - add ``GetManagerInventory`` to report list of Manager inventory information (https://github.com/ansible-collections/community.general/issues/4899).
|
||||
- seport - added new argument ``local`` (https://github.com/ansible-collections/community.general/pull/5203)
|
||||
- snap - using ``do_raise()`` to raise exceptions in ``ModuleHelper`` derived modules (https://github.com/ansible-collections/community.general/pull/4674).
|
||||
- sudoers - will attempt to validate the proposed sudoers rule using visudo if available, optionally skipped, or required (https://github.com/ansible-collections/community.general/pull/4794, https://github.com/ansible-collections/community.general/issues/4745).
|
||||
- terraform - adds capability to handle complex variable structures for ``variables`` parameter in the module. This must be enabled with the new ``complex_vars`` parameter (https://github.com/ansible-collections/community.general/pull/4797).
|
||||
- terraform - run ``terraform init`` with ``-no-color`` not to mess up the stdout of the task (https://github.com/ansible-collections/community.general/pull/5147).
|
||||
- wdc_redfish_command - add ``IndicatorLedOn`` and ``IndicatorLedOff`` commands for ``Chassis`` category (https://github.com/ansible-collections/community.general/pull/5059).
|
||||
- wdc_redfish_command - add ``PowerModeLow`` and ``PowerModeNormal`` commands for ``Chassis`` category (https://github.com/ansible-collections/community.general/pull/5145).
|
||||
- xfconf - add ``stdout``, ``stderr`` and ``cmd`` to the module results (https://github.com/ansible-collections/community.general/pull/5037).
|
||||
- xfconf - changed implementation to use ``cmd_runner`` (https://github.com/ansible-collections/community.general/pull/4776).
|
||||
- xfconf - use ``do_raise()`` instead of defining custom exception class (https://github.com/ansible-collections/community.general/pull/4975).
|
||||
- xfconf - using ``do_raise()`` to raise exceptions in ``ModuleHelper`` derived modules (https://github.com/ansible-collections/community.general/pull/4674).
|
||||
- xfconf module utils - created new module util ``xfconf`` providing a ``cmd_runner`` specific for ``xfconf`` modules (https://github.com/ansible-collections/community.general/pull/4776).
|
||||
- xfconf_info - changed implementation to use ``cmd_runner`` (https://github.com/ansible-collections/community.general/pull/4776).
|
||||
- xfconf_info - use ``do_raise()`` instead of defining custom exception class (https://github.com/ansible-collections/community.general/pull/4975).
|
||||
- znode - possibility to use ZooKeeper ACL authentication (https://github.com/ansible-collections/community.general/pull/5306).
|
||||
- apache2_module - add module argument ``warn_mpm_absent`` to control whether warning are raised in some edge cases (https://github.com/ansible-collections/community.general/pull/5793).
|
||||
- apt_rpm - adds ``clean``, ``dist_upgrade`` and ``update_kernel`` parameters for clear caches, complete upgrade system, and upgrade kernel packages (https://github.com/ansible-collections/community.general/pull/5867).
|
||||
- bitwarden lookup plugin - can now retrieve secrets from custom fields (https://github.com/ansible-collections/community.general/pull/5694).
|
||||
- bitwarden lookup plugin - implement filtering results by ``collection_id`` parameter (https://github.com/ansible-collections/community.general/issues/5849).
|
||||
- cmd_runner module utils - ``cmd_runner_fmt.as_bool()`` can now take an extra parameter to format when value is false (https://github.com/ansible-collections/community.general/pull/5647).
|
||||
- cpanm - minor change, use feature from ``ModuleHelper`` (https://github.com/ansible-collections/community.general/pull/6385).
|
||||
- dconf - be forgiving about boolean values: convert them to GVariant booleans automatically (https://github.com/ansible-collections/community.general/pull/6206).
|
||||
- dconf - if ``gi.repository.GLib`` is missing, try to respawn in a Python interpreter that has it (https://github.com/ansible-collections/community.general/pull/6491).
|
||||
- dconf - minor refactoring improving parameters and dependencies validation (https://github.com/ansible-collections/community.general/pull/6336).
|
||||
- dconf - parse GVariants for equality comparison when the Python module ``gi.repository`` is available (https://github.com/ansible-collections/community.general/pull/6049).
|
||||
- deps module utils - add function ``failed()`` providing the ability to check the dependency check result without triggering an exception (https://github.com/ansible-collections/community.general/pull/6383).
|
||||
- dig lookup plugin - Support multiple domains to be queried as indicated in docs (https://github.com/ansible-collections/community.general/pull/6334).
|
||||
- dig lookup plugin - support CAA record type (https://github.com/ansible-collections/community.general/pull/5913).
|
||||
- dnsimple - set custom User-Agent for API requests to DNSimple (https://github.com/ansible-collections/community.general/pull/5927).
|
||||
- dnsimple_info - minor refactor in the code (https://github.com/ansible-collections/community.general/pull/6440).
|
||||
- flatpak_remote - add new boolean option ``enabled``. It controls, whether the remote is enabled or not (https://github.com/ansible-collections/community.general/pull/5926).
|
||||
- gconftool2 - refactor using ``ModuleHelper`` and ``CmdRunner`` (https://github.com/ansible-collections/community.general/pull/5545).
|
||||
- gitlab_group_variable, gitlab_project_variable - refactor function out to module utils (https://github.com/ansible-collections/community.general/pull/6384).
|
||||
- gitlab_project - add ``builds_access_level``, ``container_registry_access_level`` and ``forking_access_level`` options (https://github.com/ansible-collections/community.general/pull/5706).
|
||||
- gitlab_project - add ``releases_access_level``, ``environments_access_level``, ``feature_flags_access_level``, ``infrastructure_access_level``, ``monitor_access_level``, and ``security_and_compliance_access_level`` options (https://github.com/ansible-collections/community.general/pull/5986).
|
||||
- gitlab_project - add new option ``topics`` for adding topics to GitLab projects (https://github.com/ansible-collections/community.general/pull/6278).
|
||||
- gitlab_runner - add new boolean option ``access_level_on_creation``. It controls, whether the value of ``access_level`` is used for runner registration or not. The option ``access_level`` has been ignored on registration so far and was only used on updates (https://github.com/ansible-collections/community.general/issues/5907, https://github.com/ansible-collections/community.general/pull/5908).
|
||||
- gitlab_runner - allow to register group runner (https://github.com/ansible-collections/community.general/pull/3935).
|
||||
- homebrew_cask - allows passing ``--greedy`` option to ``upgrade_all`` (https://github.com/ansible-collections/community.general/pull/6267).
|
||||
- idrac_redfish_command - add ``job_id`` to ``CreateBiosConfigJob`` response (https://github.com/ansible-collections/community.general/issues/5603).
|
||||
- ilo_redfish_utils module utils - change implementation of DNS Server IP and NTP Server IP update (https://github.com/ansible-collections/community.general/pull/5804).
|
||||
- ipa_group - allow to add and remove external users with the ``external_user`` option (https://github.com/ansible-collections/community.general/pull/5897).
|
||||
- ipa_hostgroup - add ``append`` parameter for adding a new hosts to existing hostgroups without changing existing hostgroup members (https://github.com/ansible-collections/community.general/pull/6203).
|
||||
- iptables_state - minor refactoring within the module (https://github.com/ansible-collections/community.general/pull/5844).
|
||||
- java_certs - add more detailed error output when extracting certificate from PKCS12 fails (https://github.com/ansible-collections/community.general/pull/5550).
|
||||
- jc filter plugin - added the ability to use parser plugins (https://github.com/ansible-collections/community.general/pull/6043).
|
||||
- jenkins_plugin - refactor code to module util to fix sanity check (https://github.com/ansible-collections/community.general/pull/5565).
|
||||
- jira - add worklog functionality (https://github.com/ansible-collections/community.general/issues/6209, https://github.com/ansible-collections/community.general/pull/6210).
|
||||
- keycloak_authentication - add flow type option to sub flows to allow the creation of 'form-flow' sub flows like in Keycloak's built-in registration flow (https://github.com/ansible-collections/community.general/pull/6318).
|
||||
- keycloak_group - add new optional module parameter ``parents`` to properly handle keycloak subgroups (https://github.com/ansible-collections/community.general/pull/5814).
|
||||
- keycloak_user_federation - make ``org.keycloak.storage.ldap.mappers.LDAPStorageMapper`` the default value for mappers ``providerType`` (https://github.com/ansible-collections/community.general/pull/5863).
|
||||
- ldap modules - add ``ca_path`` option (https://github.com/ansible-collections/community.general/pull/6185).
|
||||
- ldap modules - add ``xorder_discovery`` option (https://github.com/ansible-collections/community.general/issues/6045, https://github.com/ansible-collections/community.general/pull/6109).
|
||||
- ldap_search - the new ``base64_attributes`` allows to specify which attribute values should be Base64 encoded (https://github.com/ansible-collections/community.general/pull/6473).
|
||||
- lxd_container - add diff and check mode (https://github.com/ansible-collections/community.general/pull/5866).
|
||||
- lxd_project - refactored code out to module utils to clear sanity check (https://github.com/ansible-collections/community.general/pull/5549).
|
||||
- make - add ``command`` return value to the module output (https://github.com/ansible-collections/community.general/pull/6160).
|
||||
- mattermost, rocketchat, slack - replace missing default favicon with docs.ansible.com favicon (https://github.com/ansible-collections/community.general/pull/5928).
|
||||
- mksysb - improved the output of the module in case of errors (https://github.com/ansible-collections/community.general/issues/6263).
|
||||
- modprobe - add ``persistent`` option (https://github.com/ansible-collections/community.general/issues/4028, https://github.com/ansible-collections/community.general/pull/542).
|
||||
- module_helper module utils - updated the imports to make more MH features available at ``plugins/module_utils/module_helper.py`` (https://github.com/ansible-collections/community.general/pull/6464).
|
||||
- mssql_script - allow for ``GO`` statement to be mixed-case for scripts not using strict syntax (https://github.com/ansible-collections/community.general/pull/6457).
|
||||
- mssql_script - handle error condition for empty resultsets to allow for non-returning SQL statements (for example ``UPDATE`` and ``INSERT``) (https://github.com/ansible-collections/community.general/pull/6457).
|
||||
- mssql_script - improve batching logic to allow a wider variety of input scripts. For example, SQL scripts slurped from Windows machines which may contain carriage return (''\r'') characters (https://github.com/ansible-collections/community.general/pull/6457).
|
||||
- nmap inventory plugin - add new option ``open`` for only returning open ports (https://github.com/ansible-collections/community.general/pull/6200).
|
||||
- nmap inventory plugin - add new option ``port`` for port specific scan (https://github.com/ansible-collections/community.general/pull/6165).
|
||||
- nmap inventory plugin - add new options ``udp_scan``, ``icmp_timestamp``, and ``dns_resolve`` for different types of scans (https://github.com/ansible-collections/community.general/pull/5566).
|
||||
- nmap inventory plugin - added environment variables for configure ``address`` and ``exclude`` (https://github.com/ansible-collections/community.general/issues/6351).
|
||||
- nmcli - add ``default`` and ``default-or-eui64`` to the list of valid choices for ``addr_gen_mode6`` parameter (https://github.com/ansible-collections/community.general/pull/5974).
|
||||
- nmcli - add ``macvlan`` connection type (https://github.com/ansible-collections/community.general/pull/6312).
|
||||
- nmcli - add support for ``team.runner-fast-rate`` parameter for ``team`` connections (https://github.com/ansible-collections/community.general/issues/6065).
|
||||
- nmcli - new module option ``slave_type`` added to allow creation of various types of slave devices (https://github.com/ansible-collections/community.general/issues/473, https://github.com/ansible-collections/community.general/pull/6108).
|
||||
- one_vm - add a new ``updateconf`` option which implements the ``one.vm.updateconf`` API call (https://github.com/ansible-collections/community.general/pull/5812).
|
||||
- openbsd_pkg - set ``TERM`` to ``'dumb'`` in ``execute_command()`` to make module less dependant on the ``TERM`` environment variable set on the Ansible controller (https://github.com/ansible-collections/community.general/pull/6149).
|
||||
- opkg - allow installing a package in a certain version (https://github.com/ansible-collections/community.general/pull/5688).
|
||||
- opkg - refactored module to use ``CmdRunner`` for executing ``opkg`` (https://github.com/ansible-collections/community.general/pull/5718).
|
||||
- osx_defaults - include stderr in error messages (https://github.com/ansible-collections/community.general/pull/6011).
|
||||
- pipx - add ``system_site_packages`` parameter to give application access to system-wide packages (https://github.com/ansible-collections/community.general/pull/6308).
|
||||
- pipx - ensure ``include_injected`` parameter works with ``state=upgrade`` and ``state=latest`` (https://github.com/ansible-collections/community.general/pull/6212).
|
||||
- pipx - optional ``install_apps`` parameter added to install applications from injected packages (https://github.com/ansible-collections/community.general/pull/6198).
|
||||
- proxmox - added new module parameter ``tags`` for use with PVE 7+ (https://github.com/ansible-collections/community.general/pull/5714).
|
||||
- proxmox - suppress urllib3 ``InsecureRequestWarnings`` when ``validate_certs`` option is ``false`` (https://github.com/ansible-collections/community.general/pull/5931).
|
||||
- proxmox_kvm - add new ``archive`` parameter. This is needed to create a VM from an archive (backup) (https://github.com/ansible-collections/community.general/pull/6159).
|
||||
- proxmox_kvm - adds ``migrate`` parameter to manage online migrations between hosts (https://github.com/ansible-collections/community.general/pull/6448)
|
||||
- puppet - add new options ``skip_tags`` to exclude certain tagged resources during a puppet agent or apply (https://github.com/ansible-collections/community.general/pull/6293).
|
||||
- puppet - refactored module to use ``CmdRunner`` for executing ``puppet`` (https://github.com/ansible-collections/community.general/pull/5612).
|
||||
- rax_scaling_group - refactored out code to the ``rax`` module utils to clear the sanity check (https://github.com/ansible-collections/community.general/pull/5563).
|
||||
- redfish_command - add ``PerformRequestedOperations`` command to perform any operations necessary to continue the update flow (https://github.com/ansible-collections/community.general/issues/4276).
|
||||
- redfish_command - add ``update_apply_time`` to ``SimpleUpdate`` command (https://github.com/ansible-collections/community.general/issues/3910).
|
||||
- redfish_command - add ``update_status`` to output of ``SimpleUpdate`` command to allow a user monitor the update in progress (https://github.com/ansible-collections/community.general/issues/4276).
|
||||
- redfish_command - adding ``EnableSecureBoot`` functionality (https://github.com/ansible-collections/community.general/pull/5899).
|
||||
- redfish_command - adding ``VerifyBiosAttributes`` functionality (https://github.com/ansible-collections/community.general/pull/5900).
|
||||
- redfish_info - add ``GetUpdateStatus`` command to check the progress of a previous update request (https://github.com/ansible-collections/community.general/issues/4276).
|
||||
- redfish_info - adds commands to retrieve the HPE ThermalConfiguration and FanPercentMinimum settings from iLO (https://github.com/ansible-collections/community.general/pull/6208).
|
||||
- redfish_utils module utils - added PUT (``put_request()``) functionality (https://github.com/ansible-collections/community.general/pull/5490).
|
||||
- redhat_subscription - add a ``server_proxy_scheme`` parameter to configure the scheme for the proxy server (https://github.com/ansible-collections/community.general/pull/5662).
|
||||
- redhat_subscription - adds ``token`` parameter for subscription-manager authentication using Red Hat API token (https://github.com/ansible-collections/community.general/pull/5725).
|
||||
- redhat_subscription - credentials (``username``, ``activationkey``, and so on) are required now only if a system needs to be registered, or ``force_register`` is specified (https://github.com/ansible-collections/community.general/pull/5664).
|
||||
- redhat_subscription - the registration is done using the D-Bus ``rhsm`` service instead of spawning a ``subscription-manager register`` command, if possible; this avoids passing plain-text credentials as arguments to ``subscription-manager register``, which can be seen while that command runs (https://github.com/ansible-collections/community.general/pull/6122).
|
||||
- sefcontext - add support for path substitutions (https://github.com/ansible-collections/community.general/issues/1193).
|
||||
- shutdown - if no shutdown commands are found in the ``search_paths`` then the module will attempt to shutdown the system using ``systemctl shutdown`` (https://github.com/ansible-collections/community.general/issues/4269, https://github.com/ansible-collections/community.general/pull/6171).
|
||||
- slack - add option ``prepend_hash`` which allows to control whether a ``#`` is prepended to ``channel_id``. The current behavior (value ``auto``) is to prepend ``#`` unless some specific prefixes are found. That list of prefixes is incomplete, and there does not seem to exist a documented condition on when exactly ``#`` must not be prepended. We recommend to explicitly set ``prepend_hash=always`` or ``prepend_hash=never`` to avoid any ambiguity (https://github.com/ansible-collections/community.general/pull/5629).
|
||||
- snap - minor refactor when executing module (https://github.com/ansible-collections/community.general/pull/5773).
|
||||
- snap - refactor module to use ``CmdRunner`` to execute external commands (https://github.com/ansible-collections/community.general/pull/6468).
|
||||
- snap_alias - refactor code to module utils (https://github.com/ansible-collections/community.general/pull/6441).
|
||||
- snap_alias - refactored module to use ``CmdRunner`` to execute ``snap`` (https://github.com/ansible-collections/community.general/pull/5486).
|
||||
- spotinst_aws_elastigroup - add ``elements`` attribute when missing in ``list`` parameters (https://github.com/ansible-collections/community.general/pull/5553).
|
||||
- ssh_config - add ``host_key_algorithms`` option (https://github.com/ansible-collections/community.general/pull/5605).
|
||||
- ssh_config - add ``proxyjump`` option (https://github.com/ansible-collections/community.general/pull/5970).
|
||||
- ssh_config - refactor code to module util to fix sanity check (https://github.com/ansible-collections/community.general/pull/5720).
|
||||
- ssh_config - vendored StormSSH's config parser to avoid having to install StormSSH to use the module (https://github.com/ansible-collections/community.general/pull/6117).
|
||||
- sudoers - add ``setenv`` parameters to support passing environment variables via sudo. (https://github.com/ansible-collections/community.general/pull/5883)
|
||||
- sudoers - adds ``host`` parameter for setting hostname restrictions in sudoers rules (https://github.com/ansible-collections/community.general/issues/5702).
|
||||
- terraform - remove state file check condition and error block, because in the native implementation of terraform will not cause errors due to the non-existent file (https://github.com/ansible-collections/community.general/pull/6296).
|
||||
- udm_dns_record - minor refactor to the code (https://github.com/ansible-collections/community.general/pull/6382).
|
||||
- udm_share - added ``elements`` attribute to ``list`` type parameters (https://github.com/ansible-collections/community.general/pull/5557).
|
||||
- udm_user - add ``elements`` attribute when missing in ``list`` parameters (https://github.com/ansible-collections/community.general/pull/5559).
|
||||
- znode module - optional ``use_tls`` parameter added for encrypted communication (https://github.com/ansible-collections/community.general/issues/6154).
|
||||
|
||||
Breaking Changes / Porting Guide
|
||||
--------------------------------
|
||||
|
||||
- newrelic_deployment - ``revision`` is required for v2 API (https://github.com/ansible-collections/community.general/pull/5341).
|
||||
- If you are not using this collection as part of Ansible, but installed (and/or upgraded) community.general manually, you need to make sure to also install ``community.sap_libs`` if you are using any of the ``sapcar_extract``, ``sap_task_list_execute``, and ``hana_query`` modules.
|
||||
Without that collection installed, the redirects for these modules do not work.
|
||||
- ModuleHelper module utils - when the module sets output variables named ``msg``, ``exception``, ``output``, ``vars``, or ``changed``, the actual output will prefix those names with ``_`` (underscore symbol) only when they clash with output variables generated by ModuleHelper itself, which only occurs when handling exceptions. Please note that this breaking change does not require a new major release since before this release, it was not possible to add such variables to the output `due to a bug <https://github.com/ansible-collections/community.general/pull/5755>`__ (https://github.com/ansible-collections/community.general/pull/5765).
|
||||
- gconftool2 - fix processing of ``gconftool-2`` when ``key`` does not exist, returning ``null`` instead of empty string for both ``value`` and ``previous_value`` return values (https://github.com/ansible-collections/community.general/issues/6028).
|
||||
- gitlab_runner - the default of ``access_level_on_creation`` changed from ``false`` to ``true`` (https://github.com/ansible-collections/community.general/pull/6428).
|
||||
- ldap_search - convert all string-like values to UTF-8 (https://github.com/ansible-collections/community.general/issues/5704, https://github.com/ansible-collections/community.general/pull/6473).
|
||||
- nmcli - the default of the ``hairpin`` option changed from ``true`` to ``false`` (https://github.com/ansible-collections/community.general/pull/6428).
|
||||
- proxmox - the default of the ``unprivileged`` option changed from ``false`` to ``true`` (https://github.com/ansible-collections/community.general/pull/6428).
|
||||
|
||||
Deprecated Features
|
||||
-------------------
|
||||
|
||||
- ArgFormat module utils - deprecated along ``CmdMixin``, in favor of the ``cmd_runner_fmt`` module util (https://github.com/ansible-collections/community.general/pull/5370).
|
||||
- CmdMixin module utils - deprecated in favor of the ``CmdRunner`` module util (https://github.com/ansible-collections/community.general/pull/5370).
|
||||
- CmdModuleHelper module utils - deprecated in favor of the ``CmdRunner`` module util (https://github.com/ansible-collections/community.general/pull/5370).
|
||||
- CmdStateModuleHelper module utils - deprecated in favor of the ``CmdRunner`` module util (https://github.com/ansible-collections/community.general/pull/5370).
|
||||
- cmd_runner module utils - deprecated ``fmt`` in favour of ``cmd_runner_fmt`` as the parameter format object (https://github.com/ansible-collections/community.general/pull/4777).
|
||||
- django_manage - support for Django releases older than 4.1 has been deprecated and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5400).
|
||||
- django_manage - support for the commands ``cleanup``, ``syncdb`` and ``validate`` that have been deprecated in Django long time ago will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5400).
|
||||
- django_manage - the behavior of "creating the virtual environment when missing" is being deprecated and will be removed in community.general version 9.0.0 (https://github.com/ansible-collections/community.general/pull/5405).
|
||||
- gconftool2 - deprecates ``state=get`` in favor of using the module ``gconftool2_info`` (https://github.com/ansible-collections/community.general/pull/4778).
|
||||
- lxc_container - the module will no longer make any effort to support Python 2 (https://github.com/ansible-collections/community.general/pull/5304).
|
||||
- newrelic_deployment - ``appname`` and ``environment`` are no longer valid options in the v2 API. They will be removed in community.general 7.0.0 (https://github.com/ansible-collections/community.general/pull/5341).
|
||||
- proxmox - deprecated the current ``unprivileged`` default value, will be changed to ``true`` in community.general 7.0.0 (https://github.com/pull/5224).
|
||||
- xfconf - deprecated parameter ``disable_facts``, as since version 4.0.0 it only allows value ``true`` (https://github.com/ansible-collections/community.general/pull/4520).
|
||||
- ModuleHelper module_utils - ``deps`` mixin for MH classes deprecated in favour of using the ``deps`` module_utils (https://github.com/ansible-collections/community.general/pull/6465).
|
||||
- consul - deprecate using parameters unused for ``state=absent`` (https://github.com/ansible-collections/community.general/pull/5772).
|
||||
- gitlab_runner - the default of the new option ``access_level_on_creation`` will change from ``false`` to ``true`` in community.general 7.0.0. This will cause ``access_level`` to be used during runner registration as well, and not only during updates (https://github.com/ansible-collections/community.general/pull/5908).
|
||||
- gitlab_runner - the option ``access_level`` will lose its default value in community.general 8.0.0. From that version on, you have set this option to ``ref_protected`` explicitly, if you want to have a protected runner (https://github.com/ansible-collections/community.general/issues/5925).
|
||||
- manageiq_policies - deprecate ``state=list`` in favour of using ``community.general.manageiq_policies_info`` (https://github.com/ansible-collections/community.general/pull/5721).
|
||||
- manageiq_tags - deprecate ``state=list`` in favour of using ``community.general.manageiq_tags_info`` (https://github.com/ansible-collections/community.general/pull/5727).
|
||||
- rax - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax module utils - module utils code relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_cbs - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_cbs_attachments - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_cdb - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_cdb_database - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_cdb_user - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_clb - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_clb_nodes - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_clb_ssl - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_dns - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_dns_record - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_facts - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_files - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_files_objects - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_identity - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_keypair - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_meta - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_mon_alarm - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_mon_check - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_mon_entity - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_mon_notification - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_mon_notification_plan - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_network - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_queue - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_scaling_group - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rax_scaling_policy - module relies on deprecated library ``pyrax`` and will be removed in community.general 9.0.0 (https://github.com/ansible-collections/community.general/pull/5752).
|
||||
- rhn_channel, rhn_register - RHN hosted at redhat.com was discontinued years
|
||||
ago, and Spacewalk 5 (which uses RHN) is EOL since 2020, May 31st;
|
||||
while these modules could work on Uyuni / SUSE Manager (fork of Spacewalk 5),
|
||||
we have not heard about anyone using them in those setups. Hence, these
|
||||
modules are deprecated, and will be removed in community.general 10.0.0
|
||||
in case there are no reports about being still useful, and potentially
|
||||
noone that steps up to maintain them
|
||||
(https://github.com/ansible-collections/community.general/pull/6493).
|
||||
|
||||
Removed Features (previously deprecated)
|
||||
----------------------------------------
|
||||
|
||||
- bitbucket* modules - ``username`` is no longer an alias of ``workspace``, but of ``user`` (https://github.com/ansible-collections/community.general/pull/5326).
|
||||
- gem - the default of the ``norc`` option changed from ``false`` to ``true`` (https://github.com/ansible-collections/community.general/pull/5326).
|
||||
- gitlab_group_members - ``gitlab_group`` must now always contain the full path, and no longer just the name or path (https://github.com/ansible-collections/community.general/pull/5326).
|
||||
- keycloak_authentication - the return value ``flow`` has been removed. Use ``end_state`` instead (https://github.com/ansible-collections/community.general/pull/5326).
|
||||
- keycloak_group - the return value ``group`` has been removed. Use ``end_state`` instead (https://github.com/ansible-collections/community.general/pull/5326).
|
||||
- lxd_container - the default of the ``ignore_volatile_options`` option changed from ``true`` to ``false`` (https://github.com/ansible-collections/community.general/pull/5326).
|
||||
- mail callback plugin - the ``sender`` option is now required (https://github.com/ansible-collections/community.general/pull/5326).
|
||||
- module_helper module utils - remove the ``VarDict`` attribute from ``ModuleHelper``. Import ``VarDict`` from ``ansible_collections.community.general.plugins.module_utils.mh.mixins.vars`` instead (https://github.com/ansible-collections/community.general/pull/5326).
|
||||
- proxmox inventory plugin - the default of the ``want_proxmox_nodes_ansible_host`` option changed from ``true`` to ``false`` (https://github.com/ansible-collections/community.general/pull/5326).
|
||||
- vmadm - the ``debug`` option has been removed. It was not used anyway (https://github.com/ansible-collections/community.general/pull/5326).
|
||||
- All ``sap`` modules have been removed from this collection.
|
||||
They have been migrated to the `community.sap_libs <https://galaxy.ansible.com/community/sap_libs>`_ collection.
|
||||
Redirections have been provided.
|
||||
Following modules are affected:
|
||||
- sapcar_extract
|
||||
- sap_task_list_execute
|
||||
- hana_query
|
||||
- cmd_runner module utils - the ``fmt`` alias of ``cmd_runner_fmt`` has been removed. Use ``cmd_runner_fmt`` instead (https://github.com/ansible-collections/community.general/pull/6428).
|
||||
- newrelic_deployment - the ``appname`` and ``environment`` options have been removed. They did not do anything (https://github.com/ansible-collections/community.general/pull/6428).
|
||||
- puppet - the alias ``show-diff`` of the ``show_diff`` option has been removed. Use ``show_diff`` instead (https://github.com/ansible-collections/community.general/pull/6428).
|
||||
- xfconf - generating facts was deprecated in community.general 3.0.0, however three factoids, ``property``, ``channel`` and ``value`` continued to be generated by mistake. This behaviour has been removed and ``xfconf`` generate no facts whatsoever (https://github.com/ansible-collections/community.general/pull/5502).
|
||||
- xfconf - generating facts was deprecated in community.general 3.0.0, however two factoids, ``previous_value`` and ``type`` continued to be generated by mistake. This behaviour has been removed and ``xfconf`` generate no facts whatsoever (https://github.com/ansible-collections/community.general/pull/5502).
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Include ``PSF-license.txt`` file for ``plugins/module_utils/_mount.py``.
|
||||
- Include ``simplified_bsd.txt`` license file for various module utils, the ``lxca_common`` docs fragment, and the ``utm_utils`` unit tests.
|
||||
- alternatives - do not set the priority if the priority was not set by the user (https://github.com/ansible-collections/community.general/pull/4810).
|
||||
- alternatives - only pass subcommands when they are specified as module arguments (https://github.com/ansible-collections/community.general/issues/4803, https://github.com/ansible-collections/community.general/issues/4804, https://github.com/ansible-collections/community.general/pull/4836).
|
||||
- alternatives - when ``subcommands`` is specified, ``link`` must be given for every subcommand. This was already mentioned in the documentation, but not enforced by the code (https://github.com/ansible-collections/community.general/pull/4836).
|
||||
- apache2_mod_proxy - avoid crash when reporting inability to parse balancer_member_page HTML caused by using an undefined variable in the error message (https://github.com/ansible-collections/community.general/pull/5111).
|
||||
- archive - avoid crash when ``lzma`` is not present and ``format`` is not ``xz`` (https://github.com/ansible-collections/community.general/pull/5393).
|
||||
- cmd_runner module utils - fix bug caused by using the ``command`` variable instead of ``self.command`` when looking for binary path (https://github.com/ansible-collections/community.general/pull/4903).
|
||||
- consul - fixed bug introduced in PR 4590 (https://github.com/ansible-collections/community.general/issues/4680).
|
||||
- credstash lookup plugin - pass plugin options to credstash for all terms, not just for the first (https://github.com/ansible-collections/community.general/pull/5440).
|
||||
- dig lookup plugin - add option to return empty result without empty strings, and return empty list instead of ``NXDOMAIN`` (https://github.com/ansible-collections/community.general/pull/5439, https://github.com/ansible-collections/community.general/issues/5428).
|
||||
- dig lookup plugin - fix evaluation of falsy values for boolean parameters ``fail_on_error`` and ``retry_servfail`` (https://github.com/ansible-collections/community.general/pull/5129).
|
||||
- dnsimple_info - correctly report missing library as ``requests`` and not ``another_library`` (https://github.com/ansible-collections/community.general/pull/5111).
|
||||
- dnstxt lookup plugin - add option to return empty result without empty strings, and return empty list instead of ``NXDOMAIN`` (https://github.com/ansible-collections/community.general/pull/5457, https://github.com/ansible-collections/community.general/issues/5428).
|
||||
- dsv lookup plugin - do not ignore the ``tld`` parameter (https://github.com/ansible-collections/community.general/pull/4911).
|
||||
- filesystem - handle ``fatresize --info`` output lines without ``:`` (https://github.com/ansible-collections/community.general/pull/4700).
|
||||
- filesystem - improve error messages when output cannot be parsed by including newlines in escaped form (https://github.com/ansible-collections/community.general/pull/4700).
|
||||
- funcd connection plugin - fix signature of ``exec_command`` (https://github.com/ansible-collections/community.general/pull/5111).
|
||||
- ini_file - minor refactor fixing a python lint error (https://github.com/ansible-collections/community.general/pull/5307).
|
||||
- keycloak_realm - fix default groups and roles (https://github.com/ansible-collections/community.general/issues/4241).
|
||||
- keyring_info - fix the result from the keyring library never getting returned (https://github.com/ansible-collections/community.general/pull/4964).
|
||||
- ldap_attrs - fix ordering issue by ignoring the ``{x}`` prefix on attribute values (https://github.com/ansible-collections/community.general/issues/977, https://github.com/ansible-collections/community.general/pull/5385).
|
||||
- listen_ports_facts - removed leftover ``EnvironmentError`` . The ``else`` clause had a wrong indentation. The check is now handled in the ``split_pid_name`` function (https://github.com/ansible-collections/community.general/pull/5202).
|
||||
- locale_gen - fix support for Ubuntu (https://github.com/ansible-collections/community.general/issues/5281).
|
||||
- lxc_container - the module has been updated to support Python 3 (https://github.com/ansible-collections/community.general/pull/5304).
|
||||
- lxd connection plugin - fix incorrect ``inventory_hostname`` in ``remote_addr``. This is needed for compatibility with ansible-core 2.13 (https://github.com/ansible-collections/community.general/issues/4886).
|
||||
- manageiq_alert_profiles - avoid crash when reporting unknown profile caused by trying to return an undefined variable (https://github.com/ansible-collections/community.general/pull/5111).
|
||||
- nmcli - avoid changed status for most cases with VPN connections (https://github.com/ansible-collections/community.general/pull/5126).
|
||||
- nmcli - fix error caused by adding undefined module arguments for list options (https://github.com/ansible-collections/community.general/issues/4373, https://github.com/ansible-collections/community.general/pull/4813).
|
||||
- nmcli - fix error when setting previously unset MAC address, ``gsm.apn`` or ``vpn.data``: current values were being normalized without checking if they might be ``None`` (https://github.com/ansible-collections/community.general/pull/5291).
|
||||
- nmcli - fix int options idempotence (https://github.com/ansible-collections/community.general/issues/4998).
|
||||
- nsupdate - compatibility with NS records (https://github.com/ansible-collections/community.general/pull/5112).
|
||||
- nsupdate - fix silent failures when updating ``NS`` entries from Bind9 managed DNS zones (https://github.com/ansible-collections/community.general/issues/4657).
|
||||
- opentelemetry callback plugin - support opentelemetry-api 1.13.0 that removed support for ``_time_ns`` (https://github.com/ansible-collections/community.general/pull/5342).
|
||||
- osx_defaults - no longer expand ``~`` in ``value`` to the user's home directory, or expand environment variables (https://github.com/ansible-collections/community.general/issues/5234, https://github.com/ansible-collections/community.general/pull/5243).
|
||||
- packet_ip_subnet - fix error reporting in case of invalid CIDR prefix lengths (https://github.com/ansible-collections/community.general/pull/5111).
|
||||
- pacman - fixed name resolution of URL packages (https://github.com/ansible-collections/community.general/pull/4959).
|
||||
- passwordstore lookup plugin - fix ``returnall`` for gopass (https://github.com/ansible-collections/community.general/pull/5027).
|
||||
- passwordstore lookup plugin - fix password store path detection for gopass (https://github.com/ansible-collections/community.general/pull/4955).
|
||||
- pfexec become plugin - remove superflous quotes preventing exe wrap from working as expected (https://github.com/ansible-collections/community.general/issues/3671, https://github.com/ansible-collections/community.general/pull/3889).
|
||||
- pip_package_info - remove usage of global variable (https://github.com/ansible-collections/community.general/pull/5111).
|
||||
- pkgng - fix case when ``pkg`` fails when trying to upgrade all packages (https://github.com/ansible-collections/community.general/issues/5363).
|
||||
- proxmox - fix error handling when getting VM by name when ``state=absent`` (https://github.com/ansible-collections/community.general/pull/4945).
|
||||
- proxmox inventory plugin - fix crash when ``enabled=1`` is used in agent config string (https://github.com/ansible-collections/community.general/pull/4910).
|
||||
- proxmox inventory plugin - fixed extended status detection for qemu (https://github.com/ansible-collections/community.general/pull/4816).
|
||||
- proxmox_kvm - fix ``agent`` parameter when boolean value is specified (https://github.com/ansible-collections/community.general/pull/5198).
|
||||
- proxmox_kvm - fix error handling when getting VM by name when ``state=absent`` (https://github.com/ansible-collections/community.general/pull/4945).
|
||||
- proxmox_kvm - fix exception when no ``agent`` argument is specified (https://github.com/ansible-collections/community.general/pull/5194).
|
||||
- proxmox_kvm - fix wrong condition (https://github.com/ansible-collections/community.general/pull/5108).
|
||||
- proxmox_kvm - replace new condition with proper condition to allow for using ``vmid`` on update (https://github.com/ansible-collections/community.general/pull/5206).
|
||||
- rax_clb_nodes - fix code to be compatible with Python 3 (https://github.com/ansible-collections/community.general/pull/4933).
|
||||
- redfish_command - fix the check if a virtual media is unmounted to just check for ``instered= false`` caused by Supermicro hardware that does not clear the ``ImageName`` (https://github.com/ansible-collections/community.general/pull/4839).
|
||||
- redfish_command - the Supermicro Redfish implementation only supports the ``image_url`` parameter in the underlying API calls to ``VirtualMediaInsert`` and ``VirtualMediaEject``. Any values set (or the defaults) for ``write_protected`` or ``inserted`` will be ignored (https://github.com/ansible-collections/community.general/pull/4839).
|
||||
- redfish_info - fix to ``GetChassisPower`` to correctly report power information when multiple chassis exist, but not all chassis report power information (https://github.com/ansible-collections/community.general/issues/4901).
|
||||
- redfish_utils module utils - centralize payload checking when performing modification requests to a Redfish service (https://github.com/ansible-collections/community.general/issues/5210/).
|
||||
- redhat_subscription - fix unsubscribing on RHEL 9 (https://github.com/ansible-collections/community.general/issues/4741).
|
||||
- redhat_subscription - make module idempotent when ``pool_ids`` are used (https://github.com/ansible-collections/community.general/issues/5313).
|
||||
- redis* modules - fix call to ``module.fail_json`` when failing because of missing Python libraries (https://github.com/ansible-collections/community.general/pull/4733).
|
||||
- slack - fix incorrect channel prefix ``#`` caused by incomplete pattern detection by adding ``G0`` and ``GF`` as channel ID patterns (https://github.com/ansible-collections/community.general/pull/5019).
|
||||
- slack - fix message update for channels which start with ``CP``. When ``message-id`` was passed it failed for channels which started with ``CP`` because the ``#`` symbol was added before the ``channel_id`` (https://github.com/ansible-collections/community.general/pull/5249).
|
||||
- sudoers - ensure sudoers config files are created with the permissions requested by sudoers (0440) (https://github.com/ansible-collections/community.general/pull/4814).
|
||||
- sudoers - fix incorrect handling of ``state: absent`` (https://github.com/ansible-collections/community.general/issues/4852).
|
||||
- tss lookup plugin - adding support for updated Delinea library (https://github.com/DelineaXPM/python-tss-sdk/issues/9, https://github.com/ansible-collections/community.general/pull/5151).
|
||||
- virtualbox inventory plugin - skip parsing values with keys that have both a value and nested data. Skip parsing values that are nested more than two keys deep (https://github.com/ansible-collections/community.general/issues/5332, https://github.com/ansible-collections/community.general/pull/5348).
|
||||
- xcc_redfish_command - for compatibility due to Redfish spec changes the virtualMedia resource location changed from Manager to System (https://github.com/ansible-collections/community.general/pull/4682).
|
||||
- xenserver_facts - fix broken ``AnsibleModule`` call that prevented the module from working at all (https://github.com/ansible-collections/community.general/pull/5383).
|
||||
- xfconf - fix setting of boolean values (https://github.com/ansible-collections/community.general/issues/4999, https://github.com/ansible-collections/community.general/pull/5007).
|
||||
- zfs - fix wrong quoting of properties (https://github.com/ansible-collections/community.general/issues/4707, https://github.com/ansible-collections/community.general/pull/4726).
|
||||
- ModuleHelper - fix bug when adjusting the name of reserved output variables (https://github.com/ansible-collections/community.general/pull/5755).
|
||||
- alternatives - support subcommands on Fedora 37, which uses ``follower`` instead of ``slave`` (https://github.com/ansible-collections/community.general/pull/5794).
|
||||
- ansible_galaxy_install - set default to raise exception if command's return code is different from zero (https://github.com/ansible-collections/community.general/pull/5680).
|
||||
- ansible_galaxy_install - try ``C.UTF-8`` and then fall back to ``en_US.UTF-8`` before failing (https://github.com/ansible-collections/community.general/pull/5680).
|
||||
- archive - avoid deprecated exception class on Python 3 (https://github.com/ansible-collections/community.general/pull/6180).
|
||||
- archive - reduce RAM usage by generating CRC32 checksum over chunks (https://github.com/ansible-collections/community.general/pull/6274).
|
||||
- bitwarden lookup plugin - clarify what to do, if the bitwarden vault is not unlocked (https://github.com/ansible-collections/community.general/pull/5811).
|
||||
- cartesian and flattened lookup plugins - adjust to parameter deprecation in ansible-core 2.14's ``listify_lookup_plugin_terms`` helper function (https://github.com/ansible-collections/community.general/pull/6074).
|
||||
- chroot connection plugin - add ``inventory_hostname`` to vars under ``remote_addr``. This is needed for compatibility with ansible-core 2.13 (https://github.com/ansible-collections/community.general/pull/5570).
|
||||
- cloudflare_dns - fixed the idempotency for SRV DNS records (https://github.com/ansible-collections/community.general/pull/5972).
|
||||
- cloudflare_dns - fixed the possiblity of setting a root-level SRV DNS record (https://github.com/ansible-collections/community.general/pull/5972).
|
||||
- cmd_runner module utils - fixed bug when handling default cases in ``cmd_runner_fmt.as_map()`` (https://github.com/ansible-collections/community.general/pull/5538).
|
||||
- cmd_runner module utils - formatting arguments ``cmd_runner_fmt.as_fixed()`` was expecting an non-existing argument (https://github.com/ansible-collections/community.general/pull/5538).
|
||||
- dependent lookup plugin - avoid warning on deprecated parameter for ``Templar.template()`` (https://github.com/ansible-collections/community.general/pull/5543).
|
||||
- deps module utils - do not fail when dependency cannot be found (https://github.com/ansible-collections/community.general/pull/6479).
|
||||
- dig lookup plugin - correctly handle DNSKEY record type's ``algorithm`` field (https://github.com/ansible-collections/community.general/pull/5914).
|
||||
- flatpak - fixes idempotency detection issues. In some cases the module could fail to properly detect already existing Flatpaks because of a parameter witch only checks the installed apps (https://github.com/ansible-collections/community.general/pull/6289).
|
||||
- gconftool2 - fix ``changed`` result always being ``true`` (https://github.com/ansible-collections/community.general/issues/6028).
|
||||
- gconftool2 - remove requirement of parameter ``value`` when ``state=absent`` (https://github.com/ansible-collections/community.general/issues/6028).
|
||||
- gem - fix force parameter not being passed to gem command when uninstalling (https://github.com/ansible-collections/community.general/pull/5822).
|
||||
- gem - fix hang due to interactive prompt for confirmation on specific version uninstall (https://github.com/ansible-collections/community.general/pull/5751).
|
||||
- github_webhook - fix always changed state when no secret is provided (https://github.com/ansible-collections/community.general/pull/5994).
|
||||
- gitlab_deploy_key - also update ``title`` and not just ``can_push`` (https://github.com/ansible-collections/community.general/pull/5888).
|
||||
- gitlab_group_variables - fix dropping variables accidentally when GitLab introduced new properties (https://github.com/ansible-collections/community.general/pull/5667).
|
||||
- gitlab_project_variables - fix dropping variables accidentally when GitLab introduced new properties (https://github.com/ansible-collections/community.general/pull/5667).
|
||||
- gitlab_runner - fix ``KeyError`` on runner creation and update (https://github.com/ansible-collections/community.general/issues/6112).
|
||||
- icinga2_host - fix the data structure sent to Icinga to make use of host templates and template vars (https://github.com/ansible-collections/community.general/pull/6286).
|
||||
- idrac_redfish_command - allow user to specify ``resource_id`` for ``CreateBiosConfigJob`` to specify an exact manager (https://github.com/ansible-collections/community.general/issues/2090).
|
||||
- influxdb_user - fix running in check mode when the user does not exist yet (https://github.com/ansible-collections/community.general/pull/6111).
|
||||
- ini_file - make ``section`` parameter not required so it is possible to pass ``null`` as a value. This only was possible in the past due to a bug in ansible-core that now has been fixed (https://github.com/ansible-collections/community.general/pull/6404).
|
||||
- interfaces_file - fix reading options in lines not starting with a space (https://github.com/ansible-collections/community.general/issues/6120).
|
||||
- jail connection plugin - add ``inventory_hostname`` to vars under ``remote_addr``. This is needed for compatibility with ansible-core 2.13 (https://github.com/ansible-collections/community.general/pull/6118).
|
||||
- jenkins_build - fix the logical flaw when deleting a Jenkins build (https://github.com/ansible-collections/community.general/pull/5514).
|
||||
- jenkins_plugin - fix error due to undefined variable when updates file is not downloaded (https://github.com/ansible-collections/community.general/pull/6100).
|
||||
- keycloak - improve error messages (https://github.com/ansible-collections/community.general/pull/6318).
|
||||
- keycloak_client - fix accidental replacement of value for attribute ``saml.signing.private.key`` with ``no_log`` in wrong contexts (https://github.com/ansible-collections/community.general/pull/5934).
|
||||
- keycloak_client_rolemapping - calculate ``proposed`` and ``after`` return values properly (https://github.com/ansible-collections/community.general/pull/5619).
|
||||
- keycloak_client_rolemapping - remove only listed mappings with ``state=absent`` (https://github.com/ansible-collections/community.general/pull/5619).
|
||||
- keycloak_user_federation - fixes federation creation issue. When a new federation was created and at the same time a default / standard mapper was also changed / updated the creation process failed as a bad None set variable led to a bad malformed url request (https://github.com/ansible-collections/community.general/pull/5750).
|
||||
- keycloak_user_federation - fixes idempotency detection issues. In some cases the module could fail to properly detect already existing user federations because of a buggy seemingly superflous extra query parameter (https://github.com/ansible-collections/community.general/pull/5732).
|
||||
- loganalytics callback plugin - adjust type of callback to ``notification``, it was incorrectly classified as ``aggregate`` before (https://github.com/ansible-collections/community.general/pull/5761).
|
||||
- logdna callback plugin - adjust type of callback to ``notification``, it was incorrectly classified as ``aggregate`` before (https://github.com/ansible-collections/community.general/pull/5761).
|
||||
- logstash callback plugin - adjust type of callback to ``notification``, it was incorrectly classified as ``aggregate`` before (https://github.com/ansible-collections/community.general/pull/5761).
|
||||
- lxc_container - fix the arguments of the lxc command which broke the creation and cloning of containers (https://github.com/ansible-collections/community.general/issues/5578).
|
||||
- lxd_* modules, lxd inventory plugin - fix TLS/SSL certificate validation problems by using the correct purpose when creating the TLS context (https://github.com/ansible-collections/community.general/issues/5616, https://github.com/ansible-collections/community.general/pull/6034).
|
||||
- memset - fix memset urlerror handling (https://github.com/ansible-collections/community.general/pull/6114).
|
||||
- nmcli - fix change handling of values specified as an integer 0 (https://github.com/ansible-collections/community.general/pull/5431).
|
||||
- nmcli - fix failure to handle WIFI settings when connection type not specified (https://github.com/ansible-collections/community.general/pull/5431).
|
||||
- nmcli - fix improper detection of changes to ``wifi.wake-on-wlan`` (https://github.com/ansible-collections/community.general/pull/5431).
|
||||
- nmcli - fixed idempotency issue for bridge connections. Module forced default value of ``bridge.priority`` to nmcli if not set; if ``bridge.stp`` is disabled nmcli ignores it and keep default (https://github.com/ansible-collections/community.general/issues/3216, https://github.com/ansible-collections/community.general/issues/4683).
|
||||
- nmcli - fixed idempotency issue when module params is set to ``may_fail4=false`` and ``method4=disabled``; in this case nmcli ignores change and keeps their own default value ``yes`` (https://github.com/ansible-collections/community.general/pull/6106).
|
||||
- nmcli - implemented changing mtu value on vlan interfaces (https://github.com/ansible-collections/community.general/issues/4387).
|
||||
- nmcli - order is significant for lists of addresses (https://github.com/ansible-collections/community.general/pull/6048).
|
||||
- nsupdate - fix zone lookup. The SOA record for an existing zone is returned as an answer RR and not as an authority RR (https://github.com/ansible-collections/community.general/issues/5817, https://github.com/ansible-collections/community.general/pull/5818).
|
||||
- one_vm - avoid splitting labels that are ``None`` (https://github.com/ansible-collections/community.general/pull/5489).
|
||||
- one_vm - fix syntax error when creating VMs with a more complex template (https://github.com/ansible-collections/community.general/issues/6225).
|
||||
- onepassword lookup plugin - Changed to ignore errors from "op account get" calls. Previously, errors would prevent auto-signin code from executing (https://github.com/ansible-collections/community.general/pull/5942).
|
||||
- onepassword_raw - add missing parameter to plugin documentation (https://github.com/ansible-collections/community.general/issues/5506).
|
||||
- opkg - fix issue that ``force=reinstall`` would not reinstall an existing package (https://github.com/ansible-collections/community.general/pull/5705).
|
||||
- opkg - fixes bug when using ``update_cache=true`` (https://github.com/ansible-collections/community.general/issues/6004).
|
||||
- passwordstore lookup plugin - make compatible with ansible-core 2.16 (https://github.com/ansible-collections/community.general/pull/6447).
|
||||
- pipx - fixed handling of ``install_deps=true`` with ``state=latest`` and ``state=upgrade`` (https://github.com/ansible-collections/community.general/pull/6303).
|
||||
- portage - update the logic for generating the emerge command arguments to ensure that ``withbdeps: false`` results in a passing an ``n`` argument with the ``--with-bdeps`` emerge flag (https://github.com/ansible-collections/community.general/issues/6451, https://github.com/ansible-collections/community.general/pull/6456).
|
||||
- proxmox inventory plugin - fix bug while templating when using templates for the ``url``, ``user``, ``password``, ``token_id``, or ``token_secret`` options (https://github.com/ansible-collections/community.general/pull/5640).
|
||||
- proxmox inventory plugin - handle tags delimited by semicolon instead of comma, which happens from Proxmox 7.3 on (https://github.com/ansible-collections/community.general/pull/5602).
|
||||
- proxmox_disk - avoid duplicate ``vmid`` reference (https://github.com/ansible-collections/community.general/issues/5492, https://github.com/ansible-collections/community.general/pull/5493).
|
||||
- proxmox_disk - fixed issue with read timeout on import action (https://github.com/ansible-collections/community.general/pull/5803).
|
||||
- proxmox_disk - fixed possible issues with redundant ``vmid`` parameter (https://github.com/ansible-collections/community.general/issues/5492, https://github.com/ansible-collections/community.general/pull/5672).
|
||||
- proxmox_nic - fixed possible issues with redundant ``vmid`` parameter (https://github.com/ansible-collections/community.general/issues/5492, https://github.com/ansible-collections/community.general/pull/5672).
|
||||
- puppet - handling ``noop`` parameter was not working at all, now it is has been fixed (https://github.com/ansible-collections/community.general/issues/6452, https://github.com/ansible-collections/community.general/issues/6458).
|
||||
- redfish_utils - removed basic auth HTTP header when performing a GET on the service root resource and when performing a POST to the session collection (https://github.com/ansible-collections/community.general/issues/5886).
|
||||
- redhat_subscription - do not ignore ``consumer_name`` and other variables if ``activationkey`` is specified (https://github.com/ansible-collections/community.general/issues/3486, https://github.com/ansible-collections/community.general/pull/5627).
|
||||
- redhat_subscription - do not pass arguments to ``subscription-manager register`` for things already configured; now a specified ``rhsm_baseurl`` is properly set for subscription-manager (https://github.com/ansible-collections/community.general/pull/5583).
|
||||
- redhat_subscription - do not use D-Bus for registering when ``environment`` is specified, so it possible to specify again the environment names for registering, as the D-Bus APIs work only with IDs (https://github.com/ansible-collections/community.general/pull/6319).
|
||||
- redhat_subscription - try to unregister only when already registered when ``force_register`` is specified (https://github.com/ansible-collections/community.general/issues/6258, https://github.com/ansible-collections/community.general/pull/6259).
|
||||
- redhat_subscription - use the right D-Bus options for environments when registering a CentOS Stream 8 system and using ``environment`` (https://github.com/ansible-collections/community.general/pull/6275).
|
||||
- redhat_subscription, rhsm_release, rhsm_repository - cleanly fail when not running as root, rather than hanging on an interactive ``console-helper`` prompt; they all interact with ``subscription-manager``, which already requires to be run as root (https://github.com/ansible-collections/community.general/issues/734, https://github.com/ansible-collections/community.general/pull/6211).
|
||||
- rhsm_release - make ``release`` parameter not required so it is possible to pass ``null`` as a value. This only was possible in the past due to a bug in ansible-core that now has been fixed (https://github.com/ansible-collections/community.general/pull/6401).
|
||||
- rundeck module utils - fix errors caused by the API empty responses (https://github.com/ansible-collections/community.general/pull/6300)
|
||||
- rundeck_acl_policy - fix ``TypeError - byte indices must be integers or slices, not str`` error caused by empty API response. Update the module to use ``module_utils.rundeck`` functions (https://github.com/ansible-collections/community.general/pull/5887, https://github.com/ansible-collections/community.general/pull/6300).
|
||||
- rundeck_project - update the module to use ``module_utils.rundeck`` functions (https://github.com/ansible-collections/community.general/issues/5742) (https://github.com/ansible-collections/community.general/pull/6300)
|
||||
- snap_alias - module would only recognize snap names containing letter, numbers or the underscore character, failing to identify valid snap names such as ``lxd.lxc`` (https://github.com/ansible-collections/community.general/pull/6361).
|
||||
- splunk callback plugin - adjust type of callback to ``notification``, it was incorrectly classified as ``aggregate`` before (https://github.com/ansible-collections/community.general/pull/5761).
|
||||
- sumologic callback plugin - adjust type of callback to ``notification``, it was incorrectly classified as ``aggregate`` before (https://github.com/ansible-collections/community.general/pull/5761).
|
||||
- syslog_json callback plugin - adjust type of callback to ``notification``, it was incorrectly classified as ``aggregate`` before (https://github.com/ansible-collections/community.general/pull/5761).
|
||||
- terraform - fix ``current`` workspace never getting appended to the ``all`` key in the ``workspace_ctf`` object (https://github.com/ansible-collections/community.general/pull/5735).
|
||||
- terraform - fix ``terraform init`` failure when there are multiple workspaces on the remote backend and when ``default`` workspace is missing by setting ``TF_WORKSPACE`` environmental variable to the value of ``workspace`` when used (https://github.com/ansible-collections/community.general/pull/5735).
|
||||
- terraform - fix broken ``warn()`` call (https://github.com/ansible-collections/community.general/pull/6497).
|
||||
- terraform and timezone - slight refactoring to avoid linter reporting potentially undefined variables (https://github.com/ansible-collections/community.general/pull/5933).
|
||||
- terraform module - disable ANSI escape sequences during validation phase (https://github.com/ansible-collections/community.general/pull/5843).
|
||||
- tss lookup plugin - allow to download secret attachments. Previously, we could not download secret attachments but now use ``fetch_attachments`` and ``file_download_path`` variables to download attachments (https://github.com/ansible-collections/community.general/issues/6224).
|
||||
- unixy callback plugin - fix plugin to work with ansible-core 2.14 by using Ansible's configuration manager for handling options (https://github.com/ansible-collections/community.general/issues/5600).
|
||||
- unixy callback plugin - fix typo introduced when updating to use Ansible's configuration manager for handling options (https://github.com/ansible-collections/community.general/issues/5600).
|
||||
- various plugins and modules - remove unnecessary imports (https://github.com/ansible-collections/community.general/pull/5940).
|
||||
- vdo - now uses ``yaml.safe_load()`` to parse command output instead of the deprecated ``yaml.load()`` which is potentially unsafe. Using ``yaml.load()`` without explicitely setting a ``Loader=`` is also an error in pyYAML 6.0 (https://github.com/ansible-collections/community.general/pull/5632).
|
||||
- vmadm - fix for index out of range error in ``get_vm_uuid`` (https://github.com/ansible-collections/community.general/pull/5628).
|
||||
- xenorchestra inventory plugin - fix failure to receive objects from server due to not checking the id of the response (https://github.com/ansible-collections/community.general/pull/6227).
|
||||
- xfs_quota - in case of a project quota, the call to ``xfs_quota`` did not initialize/reset the project (https://github.com/ansible-collections/community.general/issues/5143).
|
||||
- xml - fixed a bug where empty ``children`` list would not be set (https://github.com/ansible-collections/community.general/pull/5808).
|
||||
- yarn - fix ``global=true`` to check for the configured global folder instead of assuming the default (https://github.com/ansible-collections/community.general/pull/5829)
|
||||
- yarn - fix ``global=true`` to not fail when `executable` wasn't specified (https://github.com/ansible-collections/community.general/pull/6132)
|
||||
- yarn - fix ``state=absent`` not working with ``global=true`` when the package does not include a binary (https://github.com/ansible-collections/community.general/pull/5829)
|
||||
- yarn - fix ``state=latest`` not working with ``global=true`` (https://github.com/ansible-collections/community.general/issues/5712).
|
||||
- yarn - fixes bug where yarn module tasks would fail when warnings were emitted from Yarn. The ``yarn.list`` method was not filtering out warnings (https://github.com/ansible-collections/community.general/issues/6127).
|
||||
- zfs_delegate_admin - zfs allow output can now be parsed when uids/gids are not known to the host system (https://github.com/ansible-collections/community.general/pull/5943).
|
||||
- zypper - make package managing work on readonly filesystem of openSUSE MicroOS (https://github.com/ansible-collections/community.general/pull/5615).
|
||||
|
||||
New Plugins
|
||||
-----------
|
||||
|
||||
Lookup
|
||||
~~~~~~
|
||||
|
||||
- merge_variables - merge variables with a certain suffix
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- scaleway_function_namespace - Scaleway Function namespace management
|
||||
- scaleway_function_namespace_info - Retrieve information on Scaleway Function namespace
|
||||
- btrfs_info - Query btrfs filesystem info
|
||||
- btrfs_subvolume - Manage btrfs subvolumes
|
||||
- gitlab_project_badge - Manage project badges on GitLab Server
|
||||
- ilo_redfish_command - Manages Out-Of-Band controllers using Redfish APIs
|
||||
- ipbase_info - Retrieve IP geolocation and other facts of a host's IP address using the ipbase.com API
|
||||
- kdeconfig - Manage KDE configuration files
|
||||
- keycloak_authz_authorization_scope - Allows administration of Keycloak client authorization scopes via Keycloak API
|
||||
- keycloak_clientscope_type - Set the type of aclientscope in realm or client via Keycloak API
|
||||
- keycloak_clientsecret_info - Retrieve client secret via Keycloak API
|
||||
- keycloak_clientsecret_regenerate - Regenerate Keycloak client secret via Keycloak API
|
||||
- ocapi_command - Manages Out-Of-Band controllers using Open Composable API (OCAPI)
|
||||
- ocapi_info - Manages Out-Of-Band controllers using Open Composable API (OCAPI)
|
||||
|
||||
@@ -31,7 +31,7 @@ Also, consider taking up a valuable, reviewed, but abandoned pull request which
|
||||
* Try committing your changes with an informative but short commit message.
|
||||
* Do not squash your commits and force-push to your branch if not needed. Reviews of your pull request are much easier with individual commits to comprehend the pull request history. All commits of your pull request branch will be squashed into one commit by GitHub upon merge.
|
||||
* Do not add merge commits to your PR. The bot will complain and you will have to rebase ([instructions for rebasing](https://docs.ansible.com/ansible/latest/dev_guide/developing_rebasing.html)) to remove them before your PR can be merged. To avoid that git automatically does merges during pulls, you can configure it to do rebases instead by running `git config pull.rebase true` inside the repository checkout.
|
||||
* Make sure your PR includes a [changelog fragment](https://docs.ansible.com/ansible/devel/community/development_process.html#changelogs-how-to). (You must not include a fragment for new modules or new plugins, except for test and filter plugins. Also you shouldn't include one for docs-only changes. If you're not sure, simply don't include one, we'll tell you whether one is needed or not :) )
|
||||
* Make sure your PR includes a [changelog fragment](https://docs.ansible.com/ansible/devel/community/development_process.html#creating-changelog-fragments). (You must not include a fragment for new modules or new plugins. Also you shouldn't include one for docs-only changes. If you're not sure, simply don't include one, we'll tell you whether one is needed or not :) )
|
||||
* Avoid reformatting unrelated parts of the codebase in your PR. These types of changes will likely be requested for reversion, create additional work for reviewers, and may cause approval to be delayed.
|
||||
|
||||
You can also read [our Quick-start development guide](https://github.com/ansible/community-docs/blob/main/create_pr_quick_start_guide.rst).
|
||||
|
||||
17
README.md
17
README.md
@@ -6,7 +6,8 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Community General Collection
|
||||
|
||||
[](https://dev.azure.com/ansible/community.general/_build?definitionId=31)
|
||||
[](https://dev.azure.com/ansible/community.general/_build?definitionId=31)
|
||||
[](https://github.com/ansible-collections/community.general/actions)
|
||||
[](https://codecov.io/gh/ansible-collections/community.general)
|
||||
|
||||
This repository contains the `community.general` Ansible Collection. The collection is a part of the Ansible package and includes many modules and plugins supported by Ansible community which are not part of more specialized community collections.
|
||||
@@ -72,13 +73,13 @@ We are actively accepting new contributors.
|
||||
|
||||
All types of contributions are very welcome.
|
||||
|
||||
You don't know how to start? Refer to our [contribution guide](https://github.com/ansible-collections/community.general/blob/main/CONTRIBUTING.md)!
|
||||
You don't know how to start? Refer to our [contribution guide](https://github.com/ansible-collections/community.general/blob/stable-7/CONTRIBUTING.md)!
|
||||
|
||||
The current maintainers are listed in the [commit-rights.md](https://github.com/ansible-collections/community.general/blob/main/commit-rights.md#people) file. If you have questions or need help, feel free to mention them in the proposals.
|
||||
The current maintainers are listed in the [commit-rights.md](https://github.com/ansible-collections/community.general/blob/stable-7/commit-rights.md#people) file. If you have questions or need help, feel free to mention them in the proposals.
|
||||
|
||||
You can find more information in the [developer guide for collections](https://docs.ansible.com/ansible/devel/dev_guide/developing_collections.html#contributing-to-collections), and in the [Ansible Community Guide](https://docs.ansible.com/ansible/latest/community/index.html).
|
||||
|
||||
Also for some notes specific to this collection see [our CONTRIBUTING documentation](https://github.com/ansible-collections/community.general/blob/main/CONTRIBUTING.md).
|
||||
Also for some notes specific to this collection see [our CONTRIBUTING documentation](https://github.com/ansible-collections/community.general/blob/stable-7/CONTRIBUTING.md).
|
||||
|
||||
### Running tests
|
||||
|
||||
@@ -88,7 +89,7 @@ See [here](https://docs.ansible.com/ansible/devel/dev_guide/developing_collectio
|
||||
|
||||
To learn how to maintain / become a maintainer of this collection, refer to:
|
||||
|
||||
* [Committer guidelines](https://github.com/ansible-collections/community.general/blob/main/commit-rights.md).
|
||||
* [Committer guidelines](https://github.com/ansible-collections/community.general/blob/stable-7/commit-rights.md).
|
||||
* [Maintainer guidelines](https://github.com/ansible/community-docs/blob/main/maintaining.rst).
|
||||
|
||||
It is necessary for maintainers of this collection to be subscribed to:
|
||||
@@ -116,7 +117,7 @@ See the [Releasing guidelines](https://github.com/ansible/community-docs/blob/ma
|
||||
|
||||
## Release notes
|
||||
|
||||
See the [changelog](https://github.com/ansible-collections/community.general/blob/main/CHANGELOG.rst).
|
||||
See the [changelog](https://github.com/ansible-collections/community.general/blob/stable-7/CHANGELOG.rst).
|
||||
|
||||
## Roadmap
|
||||
|
||||
@@ -135,8 +136,8 @@ See [this issue](https://github.com/ansible-collections/community.general/issues
|
||||
|
||||
This collection is primarily licensed and distributed as a whole under the GNU General Public License v3.0 or later.
|
||||
|
||||
See [LICENSES/GPL-3.0-or-later.txt](https://github.com/ansible-collections/community.general/blob/main/COPYING) for the full text.
|
||||
See [LICENSES/GPL-3.0-or-later.txt](https://github.com/ansible-collections/community.general/blob/stable-7/COPYING) for the full text.
|
||||
|
||||
Parts of the collection are licensed under the [BSD 2-Clause license](https://github.com/ansible-collections/community.general/blob/main/LICENSES/BSD-2-Clause.txt), the [MIT license](https://github.com/ansible-collections/community.general/blob/main/LICENSES/MIT.txt), and the [PSF 2.0 license](https://github.com/ansible-collections/community.general/blob/main/LICENSES/PSF-2.0.txt).
|
||||
Parts of the collection are licensed under the [BSD 2-Clause license](https://github.com/ansible-collections/community.general/blob/stable-7/LICENSES/BSD-2-Clause.txt), the [MIT license](https://github.com/ansible-collections/community.general/blob/stable-7/LICENSES/MIT.txt), and the [PSF 2.0 license](https://github.com/ansible-collections/community.general/blob/stable-7/LICENSES/PSF-2.0.txt).
|
||||
|
||||
All files have a machine readable `SDPX-License-Identifier:` comment denoting its respective license(s) or an equivalent entry in an accompanying `.license` file. Only changelog fragments (which will not be part of a release) are covered by a blanket statement in `.reuse/dep5`. This conforms to the [REUSE specification](https://reuse.software/spec/).
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
||||
minor_changes:
|
||||
- onepassword - support version 2 of the OnePassword CLI (https://github.com/ansible-collections/community.general/pull/4728)
|
||||
@@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- ldap_attrs - fix bug which caused a ``Bad search filter`` error. The error was occuring when the ldap attribute value contained special characters such as ``(`` or ``*`` (https://github.com/ansible-collections/community.general/issues/5434, https://github.com/ansible-collections/community.general/pull/5435).
|
||||
@@ -1,2 +0,0 @@
|
||||
minor_changes:
|
||||
- ldap_attrs - allow for DNs to have ``{x}`` prefix on first RDN (https://github.com/ansible-collections/community.general/issues/977, https://github.com/ansible-collections/community.general/pull/5450).
|
||||
@@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- iso_create - the module somtimes failed to add folders for Joliet and UDF formats (https://github.com/ansible-collections/community.general/issues/5275).
|
||||
@@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- snap - allow values in the ``options`` parameter to contain whitespaces (https://github.com/ansible-collections/community.general/pull/5475).
|
||||
@@ -1,2 +0,0 @@
|
||||
minor_changes:
|
||||
- ansible_galaxy_install - refactored module to use ``CmdRunner`` to execute ``ansible-galaxy`` (https://github.com/ansible-collections/community.general/pull/5477).
|
||||
@@ -1,2 +0,0 @@
|
||||
minor_changes:
|
||||
- hponcfg - refactored module to use ``CmdRunner`` to execute ``hponcfg`` (https://github.com/ansible-collections/community.general/pull/5483).
|
||||
@@ -1,2 +0,0 @@
|
||||
minor_changes:
|
||||
- mksysb - refactored module to use ``CmdRunner`` to execute ``mksysb`` (https://github.com/ansible-collections/community.general/pull/5484).
|
||||
@@ -1,2 +0,0 @@
|
||||
minor_changes:
|
||||
- cpanm - refactored module to use ``CmdRunner`` to execute ``cpanm`` (https://github.com/ansible-collections/community.general/pull/5485).
|
||||
@@ -1,3 +0,0 @@
|
||||
release_summary: >-
|
||||
New major release of community.general with lots of bugfixes, new features, some removed deprecated features, and some other breaking changes.
|
||||
Please check the coresponding sections of the changelog for more details.
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
namespace: community
|
||||
name: general
|
||||
version: 6.0.0
|
||||
version: 7.0.0
|
||||
readme: README.md
|
||||
authors:
|
||||
- Ansible (https://github.com/ansible)
|
||||
|
||||
128
meta/runtime.yml
128
meta/runtime.yml
@@ -22,6 +22,120 @@ plugin_routing:
|
||||
nios_next_network:
|
||||
redirect: infoblox.nios_modules.nios_next_network
|
||||
modules:
|
||||
rax_cbs_attachments:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax_cbs:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax_cdb_database:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax_cdb_user:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax_cdb:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax_clb_nodes:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax_clb_ssl:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax_clb:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax_dns_record:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax_dns:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax_facts:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax_files_objects:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax_files:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax_identity:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax_keypair:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax_meta:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax_mon_alarm:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax_mon_check:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax_mon_entity:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax_mon_notification_plan:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax_mon_notification:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax_network:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax_queue:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax_scaling_group:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rax_scaling_policy:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on the deprecated package pyrax.
|
||||
rhn_channel:
|
||||
deprecation:
|
||||
removal_version: 10.0.0
|
||||
warning_text: RHN is EOL, please contact the community.general maintainers
|
||||
if still using this; see the module documentation for more details.
|
||||
rhn_register:
|
||||
deprecation:
|
||||
removal_version: 10.0.0
|
||||
warning_text: RHN is EOL, please contact the community.general maintainers
|
||||
if still using this; see the module documentation for more details.
|
||||
database.aerospike.aerospike_migrations:
|
||||
redirect: community.general.aerospike_migrations
|
||||
deprecation:
|
||||
@@ -972,6 +1086,8 @@ plugin_routing:
|
||||
warning_text: You are using an internal name to access the community.general.heroku_collaborator
|
||||
modules. This has never been supported or documented, and will stop working
|
||||
in community.general 9.0.0.
|
||||
hana_query:
|
||||
redirect: community.sap_libs.sap_hdbsql
|
||||
hetzner_failover_ip:
|
||||
redirect: community.hrobot.failover_ip
|
||||
hetzner_failover_ip_info:
|
||||
@@ -3389,6 +3505,10 @@ plugin_routing:
|
||||
warning_text: You are using an internal name to access the community.general.redfish_info
|
||||
modules. This has never been supported or documented, and will stop working
|
||||
in community.general 9.0.0.
|
||||
sapcar_extract:
|
||||
redirect: community.sap_libs.sapcar_extract
|
||||
sap_task_list_execute:
|
||||
redirect: community.sap_libs.sap_task_list_execute
|
||||
packaging.os.redhat_subscription:
|
||||
redirect: community.general.redhat_subscription
|
||||
deprecation:
|
||||
@@ -4493,6 +4613,10 @@ plugin_routing:
|
||||
modules. This has never been supported or documented, and will stop working
|
||||
in community.general 9.0.0.
|
||||
doc_fragments:
|
||||
rackspace:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This doc fragment is used by rax modules, that rely on the deprecated package pyrax.
|
||||
_gcp:
|
||||
redirect: community.google._gcp
|
||||
docker:
|
||||
@@ -4508,6 +4632,10 @@ plugin_routing:
|
||||
postgresql:
|
||||
redirect: community.postgresql.postgresql
|
||||
module_utils:
|
||||
rax:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module util relies on the deprecated package pyrax.
|
||||
docker.common:
|
||||
redirect: community.docker.common
|
||||
docker.swarm:
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
from ansible.errors import AnsibleError, AnsibleConnectionFailure
|
||||
@@ -80,13 +81,6 @@ class ActionModule(ActionBase):
|
||||
getattr(self, default_value))))
|
||||
return value
|
||||
|
||||
def get_shutdown_command_args(self, distribution):
|
||||
args = self._get_value_from_facts('SHUTDOWN_COMMAND_ARGS', distribution, 'DEFAULT_SHUTDOWN_COMMAND_ARGS')
|
||||
# Convert seconds to minutes. If less that 60, set it to 0.
|
||||
delay_sec = self.delay
|
||||
shutdown_message = self._task.args.get('msg', self.DEFAULT_SHUTDOWN_MESSAGE)
|
||||
return args.format(delay_sec=delay_sec, delay_min=delay_sec // 60, message=shutdown_message)
|
||||
|
||||
def get_distribution(self, task_vars):
|
||||
# FIXME: only execute the module if we don't already have the facts we need
|
||||
distribution = {}
|
||||
@@ -101,7 +95,8 @@ class ActionModule(ActionBase):
|
||||
to_native(module_output['module_stdout']).strip(),
|
||||
to_native(module_output['module_stderr']).strip()))
|
||||
distribution['name'] = module_output['ansible_facts']['ansible_distribution'].lower()
|
||||
distribution['version'] = to_text(module_output['ansible_facts']['ansible_distribution_version'].split('.')[0])
|
||||
distribution['version'] = to_text(
|
||||
module_output['ansible_facts']['ansible_distribution_version'].split('.')[0])
|
||||
distribution['family'] = to_text(module_output['ansible_facts']['ansible_os_family'].lower())
|
||||
display.debug("{action}: distribution: {dist}".format(action=self._task.action, dist=distribution))
|
||||
return distribution
|
||||
@@ -109,6 +104,23 @@ class ActionModule(ActionBase):
|
||||
raise AnsibleError('Failed to get distribution information. Missing "{0}" in output.'.format(ke.args[0]))
|
||||
|
||||
def get_shutdown_command(self, task_vars, distribution):
|
||||
def find_command(command, find_search_paths):
|
||||
display.debug('{action}: running find module looking in {paths} to get path for "{command}"'.format(
|
||||
action=self._task.action,
|
||||
command=command,
|
||||
paths=find_search_paths))
|
||||
find_result = self._execute_module(
|
||||
task_vars=task_vars,
|
||||
# prevent collection search by calling with ansible.legacy (still allows library/ override of find)
|
||||
module_name='ansible.legacy.find',
|
||||
module_args={
|
||||
'paths': find_search_paths,
|
||||
'patterns': [command],
|
||||
'file_type': 'any'
|
||||
}
|
||||
)
|
||||
return [x['path'] for x in find_result['files']]
|
||||
|
||||
shutdown_bin = self._get_value_from_facts('SHUTDOWN_COMMANDS', distribution, 'DEFAULT_SHUTDOWN_COMMAND')
|
||||
default_search_paths = ['/sbin', '/usr/sbin', '/usr/local/sbin']
|
||||
search_paths = self._task.args.get('search_paths', default_search_paths)
|
||||
@@ -127,45 +139,53 @@ class ActionModule(ActionBase):
|
||||
except TypeError:
|
||||
raise AnsibleError(err_msg.format(search_paths))
|
||||
|
||||
display.debug('{action}: running find module looking in {paths} to get path for "{command}"'.format(
|
||||
action=self._task.action,
|
||||
command=shutdown_bin,
|
||||
paths=search_paths))
|
||||
find_result = self._execute_module(
|
||||
task_vars=task_vars,
|
||||
# prevent collection search by calling with ansible.legacy (still allows library/ override of find)
|
||||
module_name='ansible.legacy.find',
|
||||
module_args={
|
||||
'paths': search_paths,
|
||||
'patterns': [shutdown_bin],
|
||||
'file_type': 'any'
|
||||
}
|
||||
)
|
||||
full_path = find_command(shutdown_bin, search_paths) # find the path to the shutdown command
|
||||
if not full_path: # if we could not find the shutdown command
|
||||
display.vvv('Unable to find command "{0}" in search paths: {1}, will attempt a shutdown using systemd '
|
||||
'directly.'.format(shutdown_bin, search_paths)) # tell the user we will try with systemd
|
||||
systemctl_search_paths = ['/bin', '/usr/bin']
|
||||
full_path = find_command('systemctl', systemctl_search_paths) # find the path to the systemctl command
|
||||
if not full_path: # if we couldn't find systemctl
|
||||
raise AnsibleError(
|
||||
'Could not find command "{0}" in search paths: {1} or systemctl command in search paths: {2}, unable to shutdown.'.
|
||||
format(shutdown_bin, search_paths, systemctl_search_paths)) # we give up here
|
||||
else:
|
||||
return "{0} poweroff".format(full_path[0]) # done, since we cannot use args with systemd shutdown
|
||||
|
||||
full_path = [x['path'] for x in find_result['files']]
|
||||
if not full_path:
|
||||
raise AnsibleError('Unable to find command "{0}" in search paths: {1}'.format(shutdown_bin, search_paths))
|
||||
self._shutdown_command = full_path[0]
|
||||
return self._shutdown_command
|
||||
# systemd case taken care of, here we add args to the command
|
||||
args = self._get_value_from_facts('SHUTDOWN_COMMAND_ARGS', distribution, 'DEFAULT_SHUTDOWN_COMMAND_ARGS')
|
||||
# Convert seconds to minutes. If less that 60, set it to 0.
|
||||
delay_sec = self.delay
|
||||
shutdown_message = self._task.args.get('msg', self.DEFAULT_SHUTDOWN_MESSAGE)
|
||||
return '{0} {1}'. \
|
||||
format(
|
||||
full_path[0],
|
||||
args.format(
|
||||
delay_sec=delay_sec,
|
||||
delay_min=delay_sec // 60,
|
||||
message=shutdown_message
|
||||
)
|
||||
)
|
||||
|
||||
def perform_shutdown(self, task_vars, distribution):
|
||||
result = {}
|
||||
shutdown_result = {}
|
||||
shutdown_command = self.get_shutdown_command(task_vars, distribution)
|
||||
shutdown_command_args = self.get_shutdown_command_args(distribution)
|
||||
shutdown_command_exec = '{0} {1}'.format(shutdown_command, shutdown_command_args)
|
||||
shutdown_command_exec = self.get_shutdown_command(task_vars, distribution)
|
||||
|
||||
self.cleanup(force=True)
|
||||
try:
|
||||
display.vvv("{action}: shutting down server...".format(action=self._task.action))
|
||||
display.debug("{action}: shutting down server with command '{command}'".format(action=self._task.action, command=shutdown_command_exec))
|
||||
display.debug("{action}: shutting down server with command '{command}'".
|
||||
format(action=self._task.action, command=shutdown_command_exec))
|
||||
if self._play_context.check_mode:
|
||||
shutdown_result['rc'] = 0
|
||||
else:
|
||||
shutdown_result = self._low_level_execute_command(shutdown_command_exec, sudoable=self.DEFAULT_SUDOABLE)
|
||||
except AnsibleConnectionFailure as e:
|
||||
# If the connection is closed too quickly due to the system being shutdown, carry on
|
||||
display.debug('{action}: AnsibleConnectionFailure caught and handled: {error}'.format(action=self._task.action, error=to_text(e)))
|
||||
display.debug(
|
||||
'{action}: AnsibleConnectionFailure caught and handled: {error}'.format(action=self._task.action,
|
||||
error=to_text(e)))
|
||||
shutdown_result['rc'] = 0
|
||||
|
||||
if shutdown_result['rc'] != 0:
|
||||
|
||||
2
plugins/cache/memcached.py
vendored
2
plugins/cache/memcached.py
vendored
@@ -52,11 +52,9 @@ import time
|
||||
from multiprocessing import Lock
|
||||
from itertools import chain
|
||||
|
||||
from ansible import constants as C
|
||||
from ansible.errors import AnsibleError
|
||||
from ansible.module_utils.common._collections_compat import MutableSet
|
||||
from ansible.plugins.cache import BaseCacheModule
|
||||
from ansible.release import __version__ as ansible_base_version
|
||||
from ansible.utils.display import Display
|
||||
|
||||
try:
|
||||
|
||||
2
plugins/cache/redis.py
vendored
2
plugins/cache/redis.py
vendored
@@ -67,12 +67,10 @@ import re
|
||||
import time
|
||||
import json
|
||||
|
||||
from ansible import constants as C
|
||||
from ansible.errors import AnsibleError
|
||||
from ansible.module_utils.common.text.converters import to_native
|
||||
from ansible.parsing.ajson import AnsibleJSONEncoder, AnsibleJSONDecoder
|
||||
from ansible.plugins.cache import BaseCacheModule
|
||||
from ansible.release import __version__ as ansible_base_version
|
||||
from ansible.utils.display import Display
|
||||
|
||||
try:
|
||||
|
||||
@@ -16,15 +16,15 @@ DOCUMENTATION = '''
|
||||
- cgroups
|
||||
short_description: Profiles maximum memory usage of tasks and full execution using cgroups
|
||||
description:
|
||||
- This is an ansible callback plugin that profiles maximum memory usage of ansible and individual tasks, and displays a recap at the end using cgroups
|
||||
- This is an ansible callback plugin that profiles maximum memory usage of ansible and individual tasks, and displays a recap at the end using cgroups.
|
||||
notes:
|
||||
- Requires ansible to be run from within a cgroup, such as with C(cgexec -g memory:ansible_profile ansible-playbook ...)
|
||||
- This cgroup should only be used by ansible to get accurate results
|
||||
- To create the cgroup, first use a command such as C(sudo cgcreate -a ec2-user:ec2-user -t ec2-user:ec2-user -g memory:ansible_profile)
|
||||
- Requires ansible to be run from within a cgroup, such as with C(cgexec -g memory:ansible_profile ansible-playbook ...).
|
||||
- This cgroup should only be used by ansible to get accurate results.
|
||||
- To create the cgroup, first use a command such as C(sudo cgcreate -a ec2-user:ec2-user -t ec2-user:ec2-user -g memory:ansible_profile).
|
||||
options:
|
||||
max_mem_file:
|
||||
required: true
|
||||
description: Path to cgroups C(memory.max_usage_in_bytes) file. Example C(/sys/fs/cgroup/memory/ansible_profile/memory.max_usage_in_bytes)
|
||||
description: Path to cgroups C(memory.max_usage_in_bytes) file. Example C(/sys/fs/cgroup/memory/ansible_profile/memory.max_usage_in_bytes).
|
||||
env:
|
||||
- name: CGROUP_MAX_MEM_FILE
|
||||
ini:
|
||||
@@ -32,7 +32,7 @@ DOCUMENTATION = '''
|
||||
key: max_mem_file
|
||||
cur_mem_file:
|
||||
required: true
|
||||
description: Path to C(memory.usage_in_bytes) file. Example C(/sys/fs/cgroup/memory/ansible_profile/memory.usage_in_bytes)
|
||||
description: Path to C(memory.usage_in_bytes) file. Example C(/sys/fs/cgroup/memory/ansible_profile/memory.usage_in_bytes).
|
||||
env:
|
||||
- name: CGROUP_CUR_MEM_FILE
|
||||
ini:
|
||||
|
||||
@@ -13,8 +13,8 @@ DOCUMENTATION = '''
|
||||
type: aggregate
|
||||
short_description: demo callback that adds play/task context
|
||||
description:
|
||||
- Displays some play and task context along with normal output
|
||||
- This is mostly for demo purposes
|
||||
- Displays some play and task context along with normal output.
|
||||
- This is mostly for demo purposes.
|
||||
requirements:
|
||||
- whitelist in configuration
|
||||
'''
|
||||
|
||||
@@ -21,13 +21,12 @@ DOCUMENTATION = '''
|
||||
extends_documentation_fragment:
|
||||
- default_callback
|
||||
requirements:
|
||||
- set as stdout callback in ansible.cfg (stdout_callback = counter_enabled)
|
||||
- set as stdout callback in C(ansible.cfg) (C(stdout_callback = counter_enabled))
|
||||
'''
|
||||
|
||||
from ansible import constants as C
|
||||
from ansible.plugins.callback import CallbackBase
|
||||
from ansible.utils.color import colorize, hostcolor
|
||||
from ansible.template import Templar
|
||||
from ansible.playbook.task_include import TaskInclude
|
||||
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ short_description: minimal stdout output
|
||||
extends_documentation_fragment:
|
||||
- default_callback
|
||||
description:
|
||||
- When in verbose mode it will act the same as the default callback
|
||||
- When in verbose mode it will act the same as the default callback.
|
||||
author:
|
||||
- Dag Wieers (@dagwieers)
|
||||
requirements:
|
||||
|
||||
@@ -786,10 +786,6 @@ playbook.yml: >
|
||||
|
||||
import sys
|
||||
from contextlib import contextmanager
|
||||
from ansible import constants as C
|
||||
from ansible.playbook.task_include import TaskInclude
|
||||
from ansible.plugins.callback import CallbackBase
|
||||
from ansible.utils.color import colorize, hostcolor
|
||||
from ansible.template import Templar
|
||||
from ansible.vars.manager import VariableManager
|
||||
from ansible.plugins.callback.default import CallbackModule as Default
|
||||
|
||||
@@ -13,10 +13,10 @@ DOCUMENTATION = '''
|
||||
type: notification
|
||||
short_description: post task events to a jabber server
|
||||
description:
|
||||
- The chatty part of ChatOps with a Hipchat server as a target
|
||||
- The chatty part of ChatOps with a Hipchat server as a target.
|
||||
- This callback plugin sends status updates to a HipChat channel during playbook execution.
|
||||
requirements:
|
||||
- xmpp (python lib https://github.com/ArchipelProject/xmpppy)
|
||||
- xmpp (Python library U(https://github.com/ArchipelProject/xmpppy))
|
||||
options:
|
||||
server:
|
||||
description: connection info to jabber server
|
||||
|
||||
@@ -13,10 +13,10 @@ DOCUMENTATION = '''
|
||||
type: notification
|
||||
short_description: write playbook output to log file
|
||||
description:
|
||||
- This callback writes playbook output to a file per host in the C(/var/log/ansible/hosts) directory
|
||||
- This callback writes playbook output to a file per host in the C(/var/log/ansible/hosts) directory.
|
||||
requirements:
|
||||
- Whitelist in configuration
|
||||
- A writeable /var/log/ansible/hosts directory by the user executing Ansible on the controller
|
||||
- A writeable C(/var/log/ansible/hosts) directory by the user executing Ansible on the controller
|
||||
options:
|
||||
log_folder:
|
||||
default: /var/log/ansible/hosts
|
||||
|
||||
@@ -8,7 +8,7 @@ __metaclass__ = type
|
||||
|
||||
DOCUMENTATION = '''
|
||||
name: loganalytics
|
||||
type: aggregate
|
||||
type: notification
|
||||
short_description: Posts task results to Azure Log Analytics
|
||||
author: "Cyrus Li (@zhcli) <cyrus1006@gmail.com>"
|
||||
description:
|
||||
@@ -54,7 +54,6 @@ examples: |
|
||||
import hashlib
|
||||
import hmac
|
||||
import base64
|
||||
import logging
|
||||
import json
|
||||
import uuid
|
||||
import socket
|
||||
@@ -155,7 +154,7 @@ class AzureLogAnalyticsSource(object):
|
||||
|
||||
class CallbackModule(CallbackBase):
|
||||
CALLBACK_VERSION = 2.0
|
||||
CALLBACK_TYPE = 'aggregate'
|
||||
CALLBACK_TYPE = 'notification'
|
||||
CALLBACK_NAME = 'loganalytics'
|
||||
CALLBACK_NEEDS_WHITELIST = True
|
||||
|
||||
|
||||
@@ -9,17 +9,17 @@ __metaclass__ = type
|
||||
DOCUMENTATION = '''
|
||||
author: Unknown (!UNKNOWN)
|
||||
name: logdna
|
||||
type: aggregate
|
||||
type: notification
|
||||
short_description: Sends playbook logs to LogDNA
|
||||
description:
|
||||
- This callback will report logs from playbook actions, tasks, and events to LogDNA (https://app.logdna.com)
|
||||
- This callback will report logs from playbook actions, tasks, and events to LogDNA (U(https://app.logdna.com)).
|
||||
requirements:
|
||||
- LogDNA Python Library (https://github.com/logdna/python)
|
||||
- LogDNA Python Library (U(https://github.com/logdna/python))
|
||||
- whitelisting in configuration
|
||||
options:
|
||||
conf_key:
|
||||
required: true
|
||||
description: LogDNA Ingestion Key
|
||||
description: LogDNA Ingestion Key.
|
||||
type: string
|
||||
env:
|
||||
- name: LOGDNA_INGESTION_KEY
|
||||
@@ -28,7 +28,7 @@ DOCUMENTATION = '''
|
||||
key: conf_key
|
||||
plugin_ignore_errors:
|
||||
required: false
|
||||
description: Whether to ignore errors on failing or not
|
||||
description: Whether to ignore errors on failing or not.
|
||||
type: boolean
|
||||
env:
|
||||
- name: ANSIBLE_IGNORE_ERRORS
|
||||
@@ -38,7 +38,7 @@ DOCUMENTATION = '''
|
||||
default: false
|
||||
conf_hostname:
|
||||
required: false
|
||||
description: Alternative Host Name; the current host name by default
|
||||
description: Alternative Host Name; the current host name by default.
|
||||
type: string
|
||||
env:
|
||||
- name: LOGDNA_HOSTNAME
|
||||
@@ -47,7 +47,7 @@ DOCUMENTATION = '''
|
||||
key: conf_hostname
|
||||
conf_tags:
|
||||
required: false
|
||||
description: Tags
|
||||
description: Tags.
|
||||
type: string
|
||||
env:
|
||||
- name: LOGDNA_TAGS
|
||||
@@ -111,7 +111,7 @@ def isJSONable(obj):
|
||||
class CallbackModule(CallbackBase):
|
||||
|
||||
CALLBACK_VERSION = 0.1
|
||||
CALLBACK_TYPE = 'aggregate'
|
||||
CALLBACK_TYPE = 'notification'
|
||||
CALLBACK_NAME = 'community.general.logdna'
|
||||
CALLBACK_NEEDS_WHITELIST = True
|
||||
|
||||
|
||||
@@ -13,15 +13,15 @@ DOCUMENTATION = '''
|
||||
short_description: Sends events to Logentries
|
||||
description:
|
||||
- This callback plugin will generate JSON objects and send them to Logentries via TCP for auditing/debugging purposes.
|
||||
- Before 2.4, if you wanted to use an ini configuration, the file must be placed in the same directory as this plugin and named logentries.ini
|
||||
- Before 2.4, if you wanted to use an ini configuration, the file must be placed in the same directory as this plugin and named C(logentries.ini).
|
||||
- In 2.4 and above you can just put it in the main Ansible configuration file.
|
||||
requirements:
|
||||
- whitelisting in configuration
|
||||
- certifi (python library)
|
||||
- flatdict (python library), if you want to use the 'flatten' option
|
||||
- certifi (Python library)
|
||||
- flatdict (Python library), if you want to use the 'flatten' option
|
||||
options:
|
||||
api:
|
||||
description: URI to the Logentries API
|
||||
description: URI to the Logentries API.
|
||||
env:
|
||||
- name: LOGENTRIES_API
|
||||
default: data.logentries.com
|
||||
@@ -29,7 +29,7 @@ DOCUMENTATION = '''
|
||||
- section: callback_logentries
|
||||
key: api
|
||||
port:
|
||||
description: HTTP port to use when connecting to the API
|
||||
description: HTTP port to use when connecting to the API.
|
||||
env:
|
||||
- name: LOGENTRIES_PORT
|
||||
default: 80
|
||||
@@ -37,7 +37,7 @@ DOCUMENTATION = '''
|
||||
- section: callback_logentries
|
||||
key: port
|
||||
tls_port:
|
||||
description: Port to use when connecting to the API when TLS is enabled
|
||||
description: Port to use when connecting to the API when TLS is enabled.
|
||||
env:
|
||||
- name: LOGENTRIES_TLS_PORT
|
||||
default: 443
|
||||
@@ -45,7 +45,7 @@ DOCUMENTATION = '''
|
||||
- section: callback_logentries
|
||||
key: tls_port
|
||||
token:
|
||||
description: The logentries "TCP token"
|
||||
description: The logentries C(TCP token).
|
||||
env:
|
||||
- name: LOGENTRIES_ANSIBLE_TOKEN
|
||||
required: true
|
||||
@@ -54,7 +54,7 @@ DOCUMENTATION = '''
|
||||
key: token
|
||||
use_tls:
|
||||
description:
|
||||
- Toggle to decide whether to use TLS to encrypt the communications with the API server
|
||||
- Toggle to decide whether to use TLS to encrypt the communications with the API server.
|
||||
env:
|
||||
- name: LOGENTRIES_USE_TLS
|
||||
default: false
|
||||
@@ -63,7 +63,7 @@ DOCUMENTATION = '''
|
||||
- section: callback_logentries
|
||||
key: use_tls
|
||||
flatten:
|
||||
description: flatten complex data structures into a single dictionary with complex keys
|
||||
description: Flatten complex data structures into a single dictionary with complex keys.
|
||||
type: boolean
|
||||
default: false
|
||||
env:
|
||||
|
||||
@@ -13,13 +13,13 @@ DOCUMENTATION = r'''
|
||||
type: notification
|
||||
short_description: Sends events to Logstash
|
||||
description:
|
||||
- This callback will report facts and task events to Logstash https://www.elastic.co/products/logstash
|
||||
- This callback will report facts and task events to Logstash U(https://www.elastic.co/products/logstash).
|
||||
requirements:
|
||||
- whitelisting in configuration
|
||||
- logstash (python library)
|
||||
- logstash (Python library)
|
||||
options:
|
||||
server:
|
||||
description: Address of the Logstash server
|
||||
description: Address of the Logstash server.
|
||||
env:
|
||||
- name: LOGSTASH_SERVER
|
||||
ini:
|
||||
@@ -28,7 +28,7 @@ DOCUMENTATION = r'''
|
||||
version_added: 1.0.0
|
||||
default: localhost
|
||||
port:
|
||||
description: Port on which logstash is listening
|
||||
description: Port on which logstash is listening.
|
||||
env:
|
||||
- name: LOGSTASH_PORT
|
||||
ini:
|
||||
@@ -37,7 +37,7 @@ DOCUMENTATION = r'''
|
||||
version_added: 1.0.0
|
||||
default: 5000
|
||||
type:
|
||||
description: Message type
|
||||
description: Message type.
|
||||
env:
|
||||
- name: LOGSTASH_TYPE
|
||||
ini:
|
||||
@@ -54,7 +54,7 @@ DOCUMENTATION = r'''
|
||||
env:
|
||||
- name: LOGSTASH_PRE_COMMAND
|
||||
format_version:
|
||||
description: Logging format
|
||||
description: Logging format.
|
||||
type: str
|
||||
version_added: 2.0.0
|
||||
ini:
|
||||
@@ -113,7 +113,7 @@ from ansible.plugins.callback import CallbackBase
|
||||
class CallbackModule(CallbackBase):
|
||||
|
||||
CALLBACK_VERSION = 2.0
|
||||
CALLBACK_TYPE = 'aggregate'
|
||||
CALLBACK_TYPE = 'notification'
|
||||
CALLBACK_NAME = 'community.general.logstash'
|
||||
CALLBACK_NEEDS_WHITELIST = True
|
||||
|
||||
|
||||
@@ -79,7 +79,6 @@ import re
|
||||
import email.utils
|
||||
import smtplib
|
||||
|
||||
from ansible.module_utils.six import string_types
|
||||
from ansible.module_utils.common.text.converters import to_bytes
|
||||
from ansible.parsing.ajson import AnsibleJSONEncoder
|
||||
from ansible.plugins.callback import CallbackBase
|
||||
|
||||
@@ -67,9 +67,6 @@ DOCUMENTATION = '''
|
||||
type: string
|
||||
'''
|
||||
|
||||
import os
|
||||
import json
|
||||
|
||||
from ansible.module_utils.six.moves.urllib.parse import urlencode
|
||||
from ansible.module_utils.common.text.converters import to_bytes
|
||||
from ansible.module_utils.urls import open_url
|
||||
|
||||
@@ -15,7 +15,7 @@ DOCUMENTATION = '''
|
||||
- set as main display callback
|
||||
short_description: Don't display stuff to screen
|
||||
description:
|
||||
- This callback prevents outputing events to screen
|
||||
- This callback prevents outputing events to screen.
|
||||
'''
|
||||
|
||||
from ansible.plugins.callback import CallbackBase
|
||||
|
||||
@@ -14,12 +14,12 @@ DOCUMENTATION = '''
|
||||
type: notification
|
||||
requirements:
|
||||
- whitelisting in configuration
|
||||
- the '/usr/bin/say' command line program (standard on macOS) or 'espeak' command line program
|
||||
- the C(/usr/bin/say) command line program (standard on macOS) or C(espeak) command line program
|
||||
short_description: notify using software speech synthesizer
|
||||
description:
|
||||
- This plugin will use the 'say' or 'espeak' program to "speak" about play events.
|
||||
- This plugin will use the C(say) or C(espeak) program to "speak" about play events.
|
||||
notes:
|
||||
- In 2.8, this callback has been renamed from C(osx_say) into M(community.general.say).
|
||||
- In Ansible 2.8, this callback has been renamed from C(osx_say) into M(community.general.say).
|
||||
'''
|
||||
|
||||
import platform
|
||||
|
||||
@@ -22,7 +22,7 @@ DOCUMENTATION = '''
|
||||
options:
|
||||
nocolor:
|
||||
default: false
|
||||
description: This setting allows suppressing colorizing output
|
||||
description: This setting allows suppressing colorizing output.
|
||||
env:
|
||||
- name: ANSIBLE_NOCOLOR
|
||||
- name: ANSIBLE_SELECTIVE_DONT_COLORIZE
|
||||
|
||||
@@ -18,11 +18,11 @@ DOCUMENTATION = '''
|
||||
short_description: Sends play events to a Slack channel
|
||||
description:
|
||||
- This is an ansible callback plugin that sends status updates to a Slack channel during playbook execution.
|
||||
- Before 2.4 only environment variables were available for configuring this plugin
|
||||
- Before Ansible 2.4 only environment variables were available for configuring this plugin.
|
||||
options:
|
||||
webhook_url:
|
||||
required: true
|
||||
description: Slack Webhook URL
|
||||
description: Slack Webhook URL.
|
||||
env:
|
||||
- name: SLACK_WEBHOOK_URL
|
||||
ini:
|
||||
@@ -45,7 +45,7 @@ DOCUMENTATION = '''
|
||||
- section: callback_slack
|
||||
key: username
|
||||
validate_certs:
|
||||
description: validate the SSL certificate of the Slack server. (For HTTPS URLs)
|
||||
description: Validate the SSL certificate of the Slack server for HTTPS URLs.
|
||||
env:
|
||||
- name: SLACK_VALIDATE_CERTS
|
||||
ini:
|
||||
|
||||
@@ -8,27 +8,27 @@ __metaclass__ = type
|
||||
|
||||
DOCUMENTATION = '''
|
||||
name: splunk
|
||||
type: aggregate
|
||||
type: notification
|
||||
short_description: Sends task result events to Splunk HTTP Event Collector
|
||||
author: "Stuart Hirst (!UNKNOWN) <support@convergingdata.com>"
|
||||
description:
|
||||
- This callback plugin will send task results as JSON formatted events to a Splunk HTTP collector.
|
||||
- The companion Splunk Monitoring & Diagnostics App is available here "https://splunkbase.splunk.com/app/4023/"
|
||||
- The companion Splunk Monitoring & Diagnostics App is available here U(https://splunkbase.splunk.com/app/4023/).
|
||||
- Credit to "Ryan Currah (@ryancurrah)" for original source upon which this is based.
|
||||
requirements:
|
||||
- Whitelisting this callback plugin
|
||||
- 'Create a HTTP Event Collector in Splunk'
|
||||
- 'Define the url and token in ansible.cfg'
|
||||
- 'Define the URL and token in C(ansible.cfg)'
|
||||
options:
|
||||
url:
|
||||
description: URL to the Splunk HTTP collector source
|
||||
description: URL to the Splunk HTTP collector source.
|
||||
env:
|
||||
- name: SPLUNK_URL
|
||||
ini:
|
||||
- section: callback_splunk
|
||||
key: url
|
||||
authtoken:
|
||||
description: Token to authenticate the connection to the Splunk HTTP collector
|
||||
description: Token to authenticate the connection to the Splunk HTTP collector.
|
||||
env:
|
||||
- name: SPLUNK_AUTHTOKEN
|
||||
ini:
|
||||
@@ -48,7 +48,7 @@ DOCUMENTATION = '''
|
||||
version_added: '1.0.0'
|
||||
include_milliseconds:
|
||||
description: Whether to include milliseconds as part of the generated timestamp field in the event
|
||||
sent to the Splunk HTTP collector
|
||||
sent to the Splunk HTTP collector.
|
||||
env:
|
||||
- name: SPLUNK_INCLUDE_MILLISECONDS
|
||||
ini:
|
||||
@@ -165,7 +165,7 @@ class SplunkHTTPCollectorSource(object):
|
||||
|
||||
class CallbackModule(CallbackBase):
|
||||
CALLBACK_VERSION = 2.0
|
||||
CALLBACK_TYPE = 'aggregate'
|
||||
CALLBACK_TYPE = 'notification'
|
||||
CALLBACK_NAME = 'community.general.splunk'
|
||||
CALLBACK_NEEDS_WHITELIST = True
|
||||
|
||||
|
||||
@@ -8,18 +8,18 @@ __metaclass__ = type
|
||||
|
||||
DOCUMENTATION = '''
|
||||
name: sumologic
|
||||
type: aggregate
|
||||
type: notification
|
||||
short_description: Sends task result events to Sumologic
|
||||
author: "Ryan Currah (@ryancurrah)"
|
||||
description:
|
||||
- This callback plugin will send task results as JSON formatted events to a Sumologic HTTP collector source
|
||||
- This callback plugin will send task results as JSON formatted events to a Sumologic HTTP collector source.
|
||||
requirements:
|
||||
- Whitelisting this callback plugin
|
||||
- 'Create a HTTP collector source in Sumologic and specify a custom timestamp format of C(yyyy-MM-dd HH:mm:ss ZZZZ) and a custom timestamp locator
|
||||
of C("timestamp": "(.*)")'
|
||||
options:
|
||||
url:
|
||||
description: URL to the Sumologic HTTP collector source
|
||||
description: URL to the Sumologic HTTP collector source.
|
||||
env:
|
||||
- name: SUMOLOGIC_URL
|
||||
ini:
|
||||
@@ -28,7 +28,7 @@ options:
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
examples: >
|
||||
examples: |
|
||||
To enable, add this to your ansible.cfg file in the defaults block
|
||||
[defaults]
|
||||
callback_whitelist = community.general.sumologic
|
||||
@@ -111,7 +111,7 @@ class SumologicHTTPCollectorSource(object):
|
||||
|
||||
class CallbackModule(CallbackBase):
|
||||
CALLBACK_VERSION = 2.0
|
||||
CALLBACK_TYPE = 'aggregate'
|
||||
CALLBACK_TYPE = 'notification'
|
||||
CALLBACK_NAME = 'community.general.sumologic'
|
||||
CALLBACK_NEEDS_WHITELIST = True
|
||||
|
||||
|
||||
@@ -15,11 +15,11 @@ DOCUMENTATION = '''
|
||||
- whitelist in configuration
|
||||
short_description: sends JSON events to syslog
|
||||
description:
|
||||
- This plugin logs ansible-playbook and ansible runs to a syslog server in JSON format
|
||||
- Before Ansible 2.9 only environment variables were available for configuration
|
||||
- This plugin logs ansible-playbook and ansible runs to a syslog server in JSON format.
|
||||
- Before Ansible 2.9 only environment variables were available for configuration.
|
||||
options:
|
||||
server:
|
||||
description: syslog server that will receive the event
|
||||
description: Syslog server that will receive the event.
|
||||
env:
|
||||
- name: SYSLOG_SERVER
|
||||
default: localhost
|
||||
@@ -27,7 +27,7 @@ DOCUMENTATION = '''
|
||||
- section: callback_syslog_json
|
||||
key: syslog_server
|
||||
port:
|
||||
description: port on which the syslog server is listening
|
||||
description: Port on which the syslog server is listening.
|
||||
env:
|
||||
- name: SYSLOG_PORT
|
||||
default: 514
|
||||
@@ -35,7 +35,7 @@ DOCUMENTATION = '''
|
||||
- section: callback_syslog_json
|
||||
key: syslog_port
|
||||
facility:
|
||||
description: syslog facility to log as
|
||||
description: Syslog facility to log as.
|
||||
env:
|
||||
- name: SYSLOG_FACILITY
|
||||
default: user
|
||||
@@ -54,9 +54,6 @@ DOCUMENTATION = '''
|
||||
version_added: 4.5.0
|
||||
'''
|
||||
|
||||
import os
|
||||
import json
|
||||
|
||||
import logging
|
||||
import logging.handlers
|
||||
|
||||
@@ -71,7 +68,7 @@ class CallbackModule(CallbackBase):
|
||||
"""
|
||||
|
||||
CALLBACK_VERSION = 2.0
|
||||
CALLBACK_TYPE = 'aggregate'
|
||||
CALLBACK_TYPE = 'notification'
|
||||
CALLBACK_NAME = 'community.general.syslog_json'
|
||||
CALLBACK_NEEDS_WHITELIST = True
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ class CallbackModule(CallbackModule_default):
|
||||
|
||||
def _preprocess_result(self, result):
|
||||
self.delegated_vars = result._result.get('_ansible_delegated_vars', None)
|
||||
self._handle_exception(result._result, use_stderr=self.display_failed_stderr)
|
||||
self._handle_exception(result._result, use_stderr=self.get_option('display_failed_stderr'))
|
||||
self._handle_warnings(result._result)
|
||||
|
||||
def _process_result_output(self, result, msg):
|
||||
@@ -109,7 +109,7 @@ class CallbackModule(CallbackModule_default):
|
||||
self._display.display(msg)
|
||||
|
||||
def v2_runner_on_skipped(self, result, ignore_errors=False):
|
||||
if self.display_skipped_hosts:
|
||||
if self.get_option('display_skipped_hosts'):
|
||||
self._preprocess_result(result)
|
||||
display_color = C.COLOR_SKIP
|
||||
msg = "skipped"
|
||||
@@ -128,7 +128,7 @@ class CallbackModule(CallbackModule_default):
|
||||
msg += " | item: %s" % (item_value,)
|
||||
|
||||
task_result = self._process_result_output(result, msg)
|
||||
self._display.display(" " + task_result, display_color, stderr=self.display_failed_stderr)
|
||||
self._display.display(" " + task_result, display_color, stderr=self.get_option('display_failed_stderr'))
|
||||
|
||||
def v2_runner_on_ok(self, result, msg="ok", display_color=C.COLOR_OK):
|
||||
self._preprocess_result(result)
|
||||
@@ -142,7 +142,7 @@ class CallbackModule(CallbackModule_default):
|
||||
display_color = C.COLOR_CHANGED
|
||||
task_result = self._process_result_output(result, msg)
|
||||
self._display.display(" " + task_result, display_color)
|
||||
elif self.display_ok_hosts:
|
||||
elif self.get_option('display_ok_hosts'):
|
||||
task_result = self._process_result_output(result, msg)
|
||||
self._display.display(" " + task_result, display_color)
|
||||
|
||||
@@ -162,7 +162,7 @@ class CallbackModule(CallbackModule_default):
|
||||
display_color = C.COLOR_UNREACHABLE
|
||||
task_result = self._process_result_output(result, msg)
|
||||
|
||||
self._display.display(" " + task_result, display_color, stderr=self.display_failed_stderr)
|
||||
self._display.display(" " + task_result, display_color, stderr=self.get_option('display_failed_stderr'))
|
||||
|
||||
def v2_on_file_diff(self, result):
|
||||
if result._task.loop and 'results' in result._result:
|
||||
@@ -205,7 +205,7 @@ class CallbackModule(CallbackModule_default):
|
||||
colorize(u'ignored', t['ignored'], None)),
|
||||
log_only=True
|
||||
)
|
||||
if stats.custom and self.show_custom_stats:
|
||||
if stats.custom and self.get_option('show_custom_stats'):
|
||||
self._display.banner("CUSTOM STATS: ")
|
||||
# per host
|
||||
# TODO: come up with 'pretty format'
|
||||
|
||||
@@ -11,7 +11,7 @@ DOCUMENTATION = '''
|
||||
author: Unknown (!UNKNOWN)
|
||||
name: yaml
|
||||
type: stdout
|
||||
short_description: yaml-ized Ansible screen output
|
||||
short_description: YAML-ized Ansible screen output
|
||||
description:
|
||||
- Ansible output that can be quite a bit easier to read than the
|
||||
default JSON formatting.
|
||||
@@ -25,12 +25,10 @@ import yaml
|
||||
import json
|
||||
import re
|
||||
import string
|
||||
import sys
|
||||
|
||||
from ansible.module_utils.common.text.converters import to_bytes, to_text
|
||||
from ansible.module_utils.six import string_types
|
||||
from ansible.module_utils.common.text.converters import to_text
|
||||
from ansible.parsing.yaml.dumper import AnsibleDumper
|
||||
from ansible.plugins.callback import CallbackBase, strip_internal_keys, module_response_deepcopy
|
||||
from ansible.plugins.callback import strip_internal_keys, module_response_deepcopy
|
||||
from ansible.plugins.callback.default import CallbackModule as Default
|
||||
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ DOCUMENTATION = '''
|
||||
- The path of the chroot you want to access.
|
||||
default: inventory_hostname
|
||||
vars:
|
||||
- name: inventory_hostname
|
||||
- name: ansible_host
|
||||
executable:
|
||||
description:
|
||||
|
||||
@@ -22,6 +22,7 @@ DOCUMENTATION = '''
|
||||
- Path to the jail
|
||||
default: inventory_hostname
|
||||
vars:
|
||||
- name: inventory_hostname
|
||||
- name: ansible_host
|
||||
- name: ansible_jail_host
|
||||
remote_user:
|
||||
|
||||
@@ -20,9 +20,13 @@ attributes:
|
||||
description: Will return details on what has changed (or possibly needs changing in C(check_mode)), when in diff mode.
|
||||
'''
|
||||
|
||||
# platform:
|
||||
# description: Target OS/families that can be operated against.
|
||||
# support: N/A
|
||||
PLATFORM = r'''
|
||||
options: {}
|
||||
attributes:
|
||||
platform:
|
||||
description: Target OS/families that can be operated against.
|
||||
support: N/A
|
||||
'''
|
||||
|
||||
# Should be used together with the standard fragment
|
||||
INFO_MODULE = r'''
|
||||
|
||||
@@ -29,8 +29,7 @@ options:
|
||||
required: true
|
||||
|
||||
requirements:
|
||||
- hpe3par_sdk >= 1.0.2. Install using 'pip install hpe3par_sdk'
|
||||
- hpe3par_sdk >= 1.0.2. Install using C(pip install hpe3par_sdk).
|
||||
- WSAPI service should be enabled on the 3PAR storage array.
|
||||
notes:
|
||||
- check_mode not supported
|
||||
'''
|
||||
|
||||
@@ -24,6 +24,11 @@ options:
|
||||
- The password to use with I(bind_dn).
|
||||
type: str
|
||||
default: ''
|
||||
ca_path:
|
||||
description:
|
||||
- Set the path to PEM file with CA certs.
|
||||
type: path
|
||||
version_added: "6.5.0"
|
||||
dn:
|
||||
required: true
|
||||
description:
|
||||
@@ -60,9 +65,20 @@ options:
|
||||
sasl_class:
|
||||
description:
|
||||
- The class to use for SASL authentication.
|
||||
- possible choices are C(external), C(gssapi).
|
||||
- Possible choices are C(external), C(gssapi).
|
||||
type: str
|
||||
choices: ['external', 'gssapi']
|
||||
default: external
|
||||
version_added: "2.0.0"
|
||||
xorder_discovery:
|
||||
description:
|
||||
- Set the behavior on how to process Xordered DNs.
|
||||
- C(enable) will perform a C(ONELEVEL) search below the superior RDN to find the matching DN.
|
||||
- C(disable) will always use the DN unmodified (as passed by the I(dn) parameter).
|
||||
- C(auto) will only perform a search if the first RDN does not contain an index number (C({x})).
|
||||
- Possible choices are C(enable), C(auto), C(disable).
|
||||
type: str
|
||||
choices: ['enable', 'auto', 'disable']
|
||||
default: auto
|
||||
version_added: "6.4.0"
|
||||
'''
|
||||
|
||||
@@ -105,6 +105,10 @@ options:
|
||||
- Whether or not to require SSL validation of API endpoints.
|
||||
type: bool
|
||||
aliases: [ verify_ssl ]
|
||||
deprecated:
|
||||
removed_in: 9.0.0
|
||||
why: This module relies on the deprecated package pyrax.
|
||||
alternative: Use the Openstack modules instead.
|
||||
requirements:
|
||||
- python >= 2.6
|
||||
- pyrax
|
||||
|
||||
@@ -26,6 +26,7 @@ DOCUMENTATION = '''
|
||||
description:
|
||||
- The correct parser for the input data.
|
||||
- For example C(ifconfig).
|
||||
- "Note: use underscores instead of dashes (if any) in the parser module name."
|
||||
- See U(https://github.com/kellyjonbrazil/jc#parsers) for the latest list of parsers.
|
||||
type: string
|
||||
required: true
|
||||
@@ -79,13 +80,13 @@ from ansible.errors import AnsibleError, AnsibleFilterError
|
||||
import importlib
|
||||
|
||||
try:
|
||||
import jc
|
||||
import jc # noqa: F401, pylint: disable=unused-import
|
||||
HAS_LIB = True
|
||||
except ImportError:
|
||||
HAS_LIB = False
|
||||
|
||||
|
||||
def jc(data, parser, quiet=True, raw=False):
|
||||
def jc_filter(data, parser, quiet=True, raw=False):
|
||||
"""Convert returned command output to JSON using the JC library
|
||||
|
||||
Arguments:
|
||||
@@ -137,8 +138,14 @@ def jc(data, parser, quiet=True, raw=False):
|
||||
raise AnsibleError('You need to install "jc" as a Python library on the Ansible controller prior to running jc filter')
|
||||
|
||||
try:
|
||||
jc_parser = importlib.import_module('jc.parsers.' + parser)
|
||||
return jc_parser.parse(data, quiet=quiet, raw=raw)
|
||||
# new API (jc v1.18.0 and higher) allows use of plugin parsers
|
||||
if hasattr(jc, 'parse'):
|
||||
return jc.parse(parser, data, quiet=quiet, raw=raw)
|
||||
|
||||
# old API (jc v1.17.7 and lower)
|
||||
else:
|
||||
jc_parser = importlib.import_module('jc.parsers.' + parser)
|
||||
return jc_parser.parse(data, quiet=quiet, raw=raw)
|
||||
|
||||
except Exception as e:
|
||||
raise AnsibleFilterError('Error in jc filter plugin: %s' % e)
|
||||
@@ -149,5 +156,5 @@ class FilterModule(object):
|
||||
|
||||
def filters(self):
|
||||
return {
|
||||
'jc': jc
|
||||
'jc': jc_filter,
|
||||
}
|
||||
|
||||
@@ -102,8 +102,6 @@ from ansible.errors import AnsibleFilterError
|
||||
from ansible.module_utils.six import string_types
|
||||
from ansible.module_utils.common._collections_compat import Mapping, Sequence
|
||||
from ansible.utils.vars import merge_hash
|
||||
from ansible.release import __version__ as ansible_version
|
||||
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
|
||||
|
||||
from collections import defaultdict
|
||||
from operator import itemgetter
|
||||
|
||||
@@ -121,10 +121,7 @@ compose:
|
||||
ansible_host: "ipv4 | community.general.json_query('[?public==`false`].address') | first"
|
||||
'''
|
||||
|
||||
import os
|
||||
|
||||
from ansible.errors import AnsibleError, AnsibleParserError
|
||||
from ansible.module_utils.six import string_types
|
||||
from ansible.errors import AnsibleError
|
||||
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable, Cacheable
|
||||
|
||||
|
||||
|
||||
@@ -55,6 +55,11 @@ DOCUMENTATION = r'''
|
||||
type: str
|
||||
default: none
|
||||
choices: [ 'STOPPED', 'STARTING', 'RUNNING', 'none' ]
|
||||
project:
|
||||
description: Filter the instance according to the given project.
|
||||
type: str
|
||||
default: default
|
||||
version_added: 6.2.0
|
||||
type_filter:
|
||||
description:
|
||||
- Filter the instances by type C(virtual-machine), C(container) or C(both).
|
||||
@@ -140,19 +145,21 @@ groupby:
|
||||
vlan666:
|
||||
type: vlanid
|
||||
attribute: 666
|
||||
projectInternals:
|
||||
type: project
|
||||
attribute: internals
|
||||
'''
|
||||
|
||||
import binascii
|
||||
import json
|
||||
import re
|
||||
import time
|
||||
import os
|
||||
import socket
|
||||
from ansible.plugins.inventory import BaseInventoryPlugin
|
||||
from ansible.module_utils.common.text.converters import to_native, to_text
|
||||
from ansible.module_utils.common.dict_transformations import dict_merge
|
||||
from ansible.module_utils.six import raise_from
|
||||
from ansible.errors import AnsibleError, AnsibleParserError
|
||||
from ansible.module_utils.six.moves.urllib.parse import urlencode
|
||||
from ansible_collections.community.general.plugins.module_utils.lxd import LXDClient, LXDClientException
|
||||
|
||||
try:
|
||||
@@ -330,7 +337,15 @@ class InventoryModule(BaseInventoryPlugin):
|
||||
# "status_code": 200,
|
||||
# "type": "sync"
|
||||
# }
|
||||
instances = self.socket.do('GET', '/1.0/instances')
|
||||
url = '/1.0/instances'
|
||||
if self.project:
|
||||
url = url + '?{0}'.format(urlencode(dict(project=self.project)))
|
||||
|
||||
instances = self.socket.do('GET', url)
|
||||
|
||||
if self.project:
|
||||
return [m.split('/')[3].split('?')[0] for m in instances['metadata']]
|
||||
|
||||
return [m.split('/')[3] for m in instances['metadata']]
|
||||
|
||||
def _get_config(self, branch, name):
|
||||
@@ -351,9 +366,11 @@ class InventoryModule(BaseInventoryPlugin):
|
||||
dict(config): Config of the instance"""
|
||||
config = {}
|
||||
if isinstance(branch, (tuple, list)):
|
||||
config[name] = {branch[1]: self.socket.do('GET', '/1.0/{0}/{1}/{2}'.format(to_native(branch[0]), to_native(name), to_native(branch[1])))}
|
||||
config[name] = {branch[1]: self.socket.do(
|
||||
'GET', '/1.0/{0}/{1}/{2}?{3}'.format(to_native(branch[0]), to_native(name), to_native(branch[1]), urlencode(dict(project=self.project))))}
|
||||
else:
|
||||
config[name] = {branch: self.socket.do('GET', '/1.0/{0}/{1}'.format(to_native(branch), to_native(name)))}
|
||||
config[name] = {branch: self.socket.do(
|
||||
'GET', '/1.0/{0}/{1}?{2}'.format(to_native(branch), to_native(name), urlencode(dict(project=self.project))))}
|
||||
return config
|
||||
|
||||
def get_instance_data(self, names):
|
||||
@@ -583,6 +600,8 @@ class InventoryModule(BaseInventoryPlugin):
|
||||
self._set_data_entry(instance_name, 'network_interfaces', self.extract_network_information_from_instance_config(instance_name))
|
||||
self._set_data_entry(instance_name, 'preferred_interface', self.get_prefered_instance_network_interface(instance_name))
|
||||
self._set_data_entry(instance_name, 'vlan_ids', self.get_instance_vlans(instance_name))
|
||||
self._set_data_entry(instance_name, 'project', self._get_data_entry(
|
||||
'instances/{0}/instances/metadata/project'.format(instance_name)))
|
||||
|
||||
def build_inventory_network(self, instance_name):
|
||||
"""Add the network interfaces of the instance to the inventory
|
||||
@@ -686,6 +705,8 @@ class InventoryModule(BaseInventoryPlugin):
|
||||
# add VLAN_ID information
|
||||
if self._get_data_entry('inventory/{0}/vlan_ids'.format(instance_name)):
|
||||
self.inventory.set_variable(instance_name, 'ansible_lxd_vlan_ids', self._get_data_entry('inventory/{0}/vlan_ids'.format(instance_name)))
|
||||
# add project
|
||||
self.inventory.set_variable(instance_name, 'ansible_lxd_project', self._get_data_entry('inventory/{0}/project'.format(instance_name)))
|
||||
|
||||
def build_inventory_groups_location(self, group_name):
|
||||
"""create group by attribute: location
|
||||
@@ -761,6 +782,28 @@ class InventoryModule(BaseInventoryPlugin):
|
||||
# Ignore invalid IP addresses returned by lxd
|
||||
pass
|
||||
|
||||
def build_inventory_groups_project(self, group_name):
|
||||
"""create group by attribute: project
|
||||
|
||||
Args:
|
||||
str(group_name): Group name
|
||||
Kwargs:
|
||||
None
|
||||
Raises:
|
||||
None
|
||||
Returns:
|
||||
None"""
|
||||
# maybe we just want to expand one group
|
||||
if group_name not in self.inventory.groups:
|
||||
self.inventory.add_group(group_name)
|
||||
|
||||
gen_instances = [
|
||||
instance_name for instance_name in self.inventory.hosts
|
||||
if 'ansible_lxd_project' in self.inventory.get_host(instance_name).get_vars()]
|
||||
for instance_name in gen_instances:
|
||||
if self.groupby[group_name].get('attribute').lower() == self.inventory.get_host(instance_name).get_vars().get('ansible_lxd_project'):
|
||||
self.inventory.add_child(group_name, instance_name)
|
||||
|
||||
def build_inventory_groups_os(self, group_name):
|
||||
"""create group by attribute: os
|
||||
|
||||
@@ -899,6 +942,7 @@ class InventoryModule(BaseInventoryPlugin):
|
||||
* 'profile'
|
||||
* 'vlanid'
|
||||
* 'type'
|
||||
* 'project'
|
||||
|
||||
Args:
|
||||
str(group_name): Group name
|
||||
@@ -926,6 +970,8 @@ class InventoryModule(BaseInventoryPlugin):
|
||||
self.build_inventory_groups_vlanid(group_name)
|
||||
elif self.groupby[group_name].get('type') == 'type':
|
||||
self.build_inventory_groups_type(group_name)
|
||||
elif self.groupby[group_name].get('type') == 'project':
|
||||
self.build_inventory_groups_project(group_name)
|
||||
else:
|
||||
raise AnsibleParserError('Unknown group type: {0}'.format(to_native(group_name)))
|
||||
|
||||
@@ -1032,6 +1078,7 @@ class InventoryModule(BaseInventoryPlugin):
|
||||
try:
|
||||
self.client_key = self.get_option('client_key')
|
||||
self.client_cert = self.get_option('client_cert')
|
||||
self.project = self.get_option('project')
|
||||
self.debug = self.DEBUG
|
||||
self.data = {} # store for inventory-data
|
||||
self.groupby = self.get_option('groupby')
|
||||
|
||||
@@ -30,12 +30,27 @@ DOCUMENTATION = '''
|
||||
address:
|
||||
description: Network IP or range of IPs to scan, you can use a simple range (10.2.2.15-25) or CIDR notation.
|
||||
required: true
|
||||
env:
|
||||
- name: ANSIBLE_NMAP_ADDRESS
|
||||
version_added: 6.6.0
|
||||
exclude:
|
||||
description: list of addresses to exclude
|
||||
description:
|
||||
- List of addresses to exclude.
|
||||
- For example C(10.2.2.15-25) or C(10.2.2.15,10.2.2.16).
|
||||
type: list
|
||||
elements: string
|
||||
env:
|
||||
- name: ANSIBLE_NMAP_EXCLUDE
|
||||
version_added: 6.6.0
|
||||
port:
|
||||
description:
|
||||
- Only scan specific port or port range (C(-p)).
|
||||
- For example, you could pass C(22) for a single port, C(1-65535) for a range of ports,
|
||||
or C(U:53,137,T:21-25,139,8080,S:9) to check port 53 with UDP, ports 21-25 with TCP, port 9 with SCTP, and ports 137, 139, and 8080 with all.
|
||||
type: string
|
||||
version_added: 6.5.0
|
||||
ports:
|
||||
description: Enable/disable scanning for open ports
|
||||
description: Enable/disable scanning ports.
|
||||
type: boolean
|
||||
default: true
|
||||
ipv4:
|
||||
@@ -46,6 +61,30 @@ DOCUMENTATION = '''
|
||||
description: use IPv6 type addresses
|
||||
type: boolean
|
||||
default: true
|
||||
udp_scan:
|
||||
description:
|
||||
- Scan via UDP.
|
||||
- Depending on your system you might need I(sudo=true) for this to work.
|
||||
type: boolean
|
||||
default: false
|
||||
version_added: 6.1.0
|
||||
icmp_timestamp:
|
||||
description:
|
||||
- Scan via ICMP Timestamp (C(-PP)).
|
||||
- Depending on your system you might need I(sudo=true) for this to work.
|
||||
type: boolean
|
||||
default: false
|
||||
version_added: 6.1.0
|
||||
open:
|
||||
description: Only scan for open (or possibly open) ports.
|
||||
type: boolean
|
||||
default: false
|
||||
version_added: 6.5.0
|
||||
dns_resolve:
|
||||
description: Whether to always (C(true)) or never (C(false)) do DNS resolution.
|
||||
type: boolean
|
||||
default: false
|
||||
version_added: 6.1.0
|
||||
notes:
|
||||
- At least one of ipv4 or ipv6 is required to be True, both can be True, but they cannot both be False.
|
||||
- 'TODO: add OS fingerprinting'
|
||||
@@ -62,6 +101,14 @@ plugin: community.general.nmap
|
||||
sudo: true
|
||||
strict: false
|
||||
address: 192.168.0.0/24
|
||||
|
||||
# an nmap scan specifying ports and classifying results to an inventory group
|
||||
plugin: community.general.nmap
|
||||
address: 192.168.0.0/24
|
||||
exclude: 192.168.0.1, web.example.com
|
||||
port: 22, 443
|
||||
groups:
|
||||
web_servers: "ports | selectattr('port', 'equalto', '443')"
|
||||
'''
|
||||
|
||||
import os
|
||||
@@ -152,6 +199,10 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||
if self._options['sudo']:
|
||||
cmd.insert(0, 'sudo')
|
||||
|
||||
if self._options['port']:
|
||||
cmd.append('-p')
|
||||
cmd.append(self._options['port'])
|
||||
|
||||
if not self._options['ports']:
|
||||
cmd.append('-sP')
|
||||
|
||||
@@ -166,6 +217,18 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||
cmd.append('--exclude')
|
||||
cmd.append(','.join(self._options['exclude']))
|
||||
|
||||
if self._options['dns_resolve']:
|
||||
cmd.append('-n')
|
||||
|
||||
if self._options['udp_scan']:
|
||||
cmd.append('-sU')
|
||||
|
||||
if self._options['icmp_timestamp']:
|
||||
cmd.append('-PP')
|
||||
|
||||
if self._options['open']:
|
||||
cmd.append('--open')
|
||||
|
||||
cmd.append(self._options['address'])
|
||||
try:
|
||||
# execute
|
||||
|
||||
@@ -65,7 +65,7 @@ from sys import version as python_version
|
||||
from ansible.errors import AnsibleError
|
||||
from ansible.module_utils.urls import open_url
|
||||
from ansible.plugins.inventory import BaseInventoryPlugin
|
||||
from ansible.module_utils.common.text.converters import to_native, to_text
|
||||
from ansible.module_utils.common.text.converters import to_text
|
||||
from ansible.module_utils.ansible_release import __version__ as ansible_version
|
||||
from ansible.module_utils.six.moves.urllib.parse import urljoin
|
||||
|
||||
|
||||
@@ -277,6 +277,11 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||
credentials = urlencode({'username': self.proxmox_user, 'password': self.proxmox_password, })
|
||||
|
||||
a = self._get_session()
|
||||
|
||||
if a.verify is False:
|
||||
from requests.packages.urllib3 import disable_warnings
|
||||
disable_warnings()
|
||||
|
||||
ret = a.post('%s/api2/json/access/ticket' % self.proxmox_url, data=credentials)
|
||||
|
||||
json = ret.json()
|
||||
@@ -408,7 +413,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||
stripped_value = value.strip()
|
||||
if stripped_value:
|
||||
parsed_key = key + "_parsed"
|
||||
properties[parsed_key] = [tag.strip() for tag in stripped_value.split(",")]
|
||||
properties[parsed_key] = [tag.strip() for tag in stripped_value.replace(',', ';').split(";")]
|
||||
|
||||
# The first field in the agent string tells you whether the agent is enabled
|
||||
# the rest of the comma separated string is extra config for the agent.
|
||||
@@ -615,7 +620,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||
for o in ('url', 'user', 'password', 'token_id', 'token_secret'):
|
||||
v = self.get_option(o)
|
||||
if self.templar.is_template(v):
|
||||
v = self.templar.template(v, disable_looups=False)
|
||||
v = self.templar.template(v, disable_lookups=False)
|
||||
setattr(self, 'proxmox_%s' % o, v)
|
||||
|
||||
# some more cleanup and validation
|
||||
|
||||
@@ -78,6 +78,7 @@ compose:
|
||||
|
||||
import json
|
||||
import ssl
|
||||
from time import sleep
|
||||
|
||||
from ansible.errors import AnsibleError
|
||||
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable, Cacheable
|
||||
@@ -138,21 +139,42 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||
self.conn = create_connection(
|
||||
'{0}://{1}/api/'.format(proto, xoa_api_host), sslopt=sslopt)
|
||||
|
||||
CALL_TIMEOUT = 100
|
||||
"""Number of 1/10ths of a second to wait before method call times out."""
|
||||
|
||||
def call(self, method, params):
|
||||
"""Calls a method on the XO server with the provided parameters."""
|
||||
id = self.pointer
|
||||
self.conn.send(json.dumps({
|
||||
'id': id,
|
||||
'jsonrpc': '2.0',
|
||||
'method': method,
|
||||
'params': params
|
||||
}))
|
||||
|
||||
waited = 0
|
||||
while waited < self.CALL_TIMEOUT:
|
||||
response = json.loads(self.conn.recv())
|
||||
if 'id' in response and response['id'] == id:
|
||||
return response
|
||||
else:
|
||||
sleep(0.1)
|
||||
waited += 1
|
||||
|
||||
raise AnsibleError(
|
||||
'Method call {method} timed out after {timeout} seconds.'.format(method=method, timeout=self.CALL_TIMEOUT / 10))
|
||||
|
||||
def login(self, user, password):
|
||||
payload = {'id': self.pointer, 'jsonrpc': '2.0', 'method': 'session.signIn', 'params': {
|
||||
'username': user, 'password': password}}
|
||||
self.conn.send(json.dumps(payload))
|
||||
result = json.loads(self.conn.recv())
|
||||
result = self.call('session.signIn', {
|
||||
'username': user, 'password': password
|
||||
})
|
||||
|
||||
if 'error' in result:
|
||||
raise AnsibleError(
|
||||
'Could not connect: {0}'.format(result['error']))
|
||||
|
||||
def get_object(self, name):
|
||||
payload = {'id': self.pointer, 'jsonrpc': '2.0',
|
||||
'method': 'xo.getAllObjects', 'params': {'filter': {'type': name}}}
|
||||
self.conn.send(json.dumps(payload))
|
||||
answer = json.loads(self.conn.recv())
|
||||
answer = self.call('xo.getAllObjects', {'filter': {'type': name}})
|
||||
|
||||
if 'error' in answer:
|
||||
raise AnsibleError(
|
||||
|
||||
@@ -28,8 +28,12 @@ DOCUMENTATION = """
|
||||
default: name
|
||||
version_added: 5.7.0
|
||||
field:
|
||||
description: Field to fetch; leave unset to fetch whole response.
|
||||
description: Field to fetch. Leave unset to fetch whole response.
|
||||
type: str
|
||||
collection_id:
|
||||
description: Collection ID to filter results by collection. Leave unset to skip filtering.
|
||||
type: str
|
||||
version_added: 6.3.0
|
||||
"""
|
||||
|
||||
EXAMPLES = """
|
||||
@@ -43,10 +47,20 @@ EXAMPLES = """
|
||||
msg: >-
|
||||
{{ lookup('community.general.bitwarden', 'bafba515-af11-47e6-abe3-af1200cd18b2', search='id', field='password') }}
|
||||
|
||||
- name: "Get 'password' from Bitwarden record named 'a_test' from collection"
|
||||
ansible.builtin.debug:
|
||||
msg: >-
|
||||
{{ lookup('community.general.bitwarden', 'a_test', field='password', collection_id='bafba515-af11-47e6-abe3-af1200cd18b2') }}
|
||||
|
||||
- name: "Get full Bitwarden record named 'a_test'"
|
||||
ansible.builtin.debug:
|
||||
msg: >-
|
||||
{{ lookup('community.general.bitwarden', 'a_test') }}
|
||||
|
||||
- name: "Get custom field 'api_key' from Bitwarden record named 'a_test'"
|
||||
ansible.builtin.debug:
|
||||
msg: >-
|
||||
{{ lookup('community.general.bitwarden', 'a_test', field='api_key') }}
|
||||
"""
|
||||
|
||||
RETURN = """
|
||||
@@ -78,7 +92,7 @@ class Bitwarden(object):
|
||||
return self._cli_path
|
||||
|
||||
@property
|
||||
def logged_in(self):
|
||||
def unlocked(self):
|
||||
out, err = self._run(['status'], stdin="")
|
||||
decoded = AnsibleJSONDecoder().raw_decode(out)[0]
|
||||
return decoded['status'] == 'unlocked'
|
||||
@@ -91,10 +105,17 @@ class Bitwarden(object):
|
||||
raise BitwardenException(err)
|
||||
return to_text(out, errors='surrogate_or_strict'), to_text(err, errors='surrogate_or_strict')
|
||||
|
||||
def _get_matches(self, search_value, search_field):
|
||||
def _get_matches(self, search_value, search_field, collection_id):
|
||||
"""Return matching records whose search_field is equal to key.
|
||||
"""
|
||||
out, err = self._run(['list', 'items', '--search', search_value])
|
||||
|
||||
# Prepare set of params for Bitwarden CLI
|
||||
params = ['list', 'items', '--search', search_value]
|
||||
|
||||
if collection_id:
|
||||
params.extend(['--collectionid', collection_id])
|
||||
|
||||
out, err = self._run(params)
|
||||
|
||||
# This includes things that matched in different fields.
|
||||
initial_matches = AnsibleJSONDecoder().raw_decode(out)[0]
|
||||
@@ -102,17 +123,27 @@ class Bitwarden(object):
|
||||
# Filter to only include results from the right field.
|
||||
return [item for item in initial_matches if item[search_field] == search_value]
|
||||
|
||||
def get_field(self, field, search_value, search_field="name"):
|
||||
"""Return a list of the specified field for records whose search_field match search_value.
|
||||
def get_field(self, field, search_value, search_field="name", collection_id=None):
|
||||
"""Return a list of the specified field for records whose search_field match search_value
|
||||
and filtered by collection if collection has been provided.
|
||||
|
||||
If field is None, return the whole record for each match.
|
||||
"""
|
||||
matches = self._get_matches(search_value, search_field)
|
||||
matches = self._get_matches(search_value, search_field, collection_id)
|
||||
|
||||
if field:
|
||||
if field in ['autofillOnPageLoad', 'password', 'passwordRevisionDate', 'totp', 'uris', 'username']:
|
||||
return [match['login'][field] for match in matches]
|
||||
|
||||
return matches
|
||||
elif not field:
|
||||
return matches
|
||||
else:
|
||||
custom_field_matches = []
|
||||
for match in matches:
|
||||
for custom_field in match['fields']:
|
||||
if custom_field['name'] == field:
|
||||
custom_field_matches.append(custom_field['value'])
|
||||
if matches and not custom_field_matches:
|
||||
raise AnsibleError("Custom field {field} does not exist in {search_value}".format(field=field, search_value=search_value))
|
||||
return custom_field_matches
|
||||
|
||||
|
||||
class LookupModule(LookupBase):
|
||||
@@ -121,10 +152,11 @@ class LookupModule(LookupBase):
|
||||
self.set_options(var_options=variables, direct=kwargs)
|
||||
field = self.get_option('field')
|
||||
search_field = self.get_option('search')
|
||||
if not _bitwarden.logged_in:
|
||||
raise AnsibleError("Not logged into Bitwarden. Run 'bw login'.")
|
||||
collection_id = self.get_option('collection_id')
|
||||
if not _bitwarden.unlocked:
|
||||
raise AnsibleError("Bitwarden Vault locked. Run 'bw unlock'.")
|
||||
|
||||
return [_bitwarden.get_field(field, term, search_field) for term in terms]
|
||||
return [_bitwarden.get_field(field, term, search_field, collection_id) for term in terms]
|
||||
|
||||
|
||||
_bitwarden = Bitwarden()
|
||||
|
||||
@@ -66,7 +66,12 @@ class LookupModule(LookupBase):
|
||||
"""
|
||||
results = []
|
||||
for x in terms:
|
||||
intermediate = listify_lookup_plugin_terms(x, templar=self._templar, loader=self._loader)
|
||||
try:
|
||||
intermediate = listify_lookup_plugin_terms(x, templar=self._templar)
|
||||
except TypeError:
|
||||
# The loader argument is deprecated in ansible-core 2.14+. Fall back to
|
||||
# pre-2.14 behavior for older ansible-core versions.
|
||||
intermediate = listify_lookup_plugin_terms(x, templar=self._templar, loader=self._loader)
|
||||
results.append(intermediate)
|
||||
return results
|
||||
|
||||
|
||||
@@ -105,7 +105,6 @@ RETURN = """
|
||||
type: dict
|
||||
"""
|
||||
|
||||
import os
|
||||
from ansible.module_utils.six.moves.urllib.parse import urlparse
|
||||
from ansible.errors import AnsibleError, AnsibleAssertionError
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
|
||||
@@ -93,8 +93,6 @@ RETURN = """
|
||||
type: str
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from ansible.errors import AnsibleError
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
|
||||
|
||||
@@ -80,7 +80,6 @@ from subprocess import Popen
|
||||
|
||||
from ansible.errors import AnsibleError
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
from ansible.parsing.splitter import parse_kv
|
||||
from ansible.module_utils.common.text.converters import to_bytes, to_text, to_native
|
||||
from ansible.utils.display import Display
|
||||
|
||||
|
||||
@@ -125,8 +125,16 @@ from ansible.errors import AnsibleLookupError
|
||||
from ansible.module_utils.common._collections_compat import Mapping, Sequence
|
||||
from ansible.module_utils.six import string_types
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
from ansible.release import __version__ as ansible_version
|
||||
from ansible.template import Templar
|
||||
|
||||
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
|
||||
|
||||
|
||||
# Whether Templar has a cache, which can be controlled by Templar.template()'s cache option.
|
||||
# The cache was removed for ansible-core 2.14 (https://github.com/ansible/ansible/pull/78419)
|
||||
_TEMPLAR_HAS_TEMPLATE_CACHE = LooseVersion(ansible_version) < LooseVersion('2.14.0')
|
||||
|
||||
|
||||
class LookupModule(LookupBase):
|
||||
def __evaluate(self, expression, templar, variables):
|
||||
@@ -136,7 +144,10 @@ class LookupModule(LookupBase):
|
||||
``variables`` are the variables to use.
|
||||
"""
|
||||
templar.available_variables = variables or {}
|
||||
return templar.template("{0}{1}{2}".format("{{", expression, "}}"), cache=False)
|
||||
expression = "{0}{1}{2}".format("{{", expression, "}}")
|
||||
if _TEMPLAR_HAS_TEMPLATE_CACHE:
|
||||
return templar.template(expression, cache=False)
|
||||
return templar.template(expression)
|
||||
|
||||
def __process(self, result, terms, index, current, templar, variables):
|
||||
"""Fills ``result`` list with evaluated items.
|
||||
|
||||
@@ -35,9 +35,10 @@ DOCUMENTATION = '''
|
||||
description:
|
||||
- Record type to query.
|
||||
- C(DLV) has been removed in community.general 6.0.0.
|
||||
- C(CAA) has been added in community.general 6.3.0.
|
||||
type: str
|
||||
default: 'A'
|
||||
choices: [A, ALL, AAAA, CNAME, DNAME, DNSKEY, DS, HINFO, LOC, MX, NAPTR, NS, NSEC3PARAM, PTR, RP, RRSIG, SOA, SPF, SRV, SSHFP, TLSA, TXT]
|
||||
choices: [A, ALL, AAAA, CAA, CNAME, DNAME, DNSKEY, DS, HINFO, LOC, MX, NAPTR, NS, NSEC3PARAM, PTR, RP, RRSIG, SOA, SPF, SRV, SSHFP, TLSA, TXT]
|
||||
flat:
|
||||
description: If 0 each record is returned as a dictionary, otherwise a string.
|
||||
type: int
|
||||
@@ -60,6 +61,7 @@ DOCUMENTATION = '''
|
||||
description:
|
||||
- Return empty result without empty strings, and return empty list instead of C(NXDOMAIN).
|
||||
- The default for this option will likely change to C(true) in the future.
|
||||
- This option will be forced to C(true) if multiple domains to be queried are specified.
|
||||
default: false
|
||||
type: bool
|
||||
version_added: 6.0.0
|
||||
@@ -94,6 +96,21 @@ EXAMPLES = """
|
||||
msg: "MX record for gmail.com {{ item }}"
|
||||
with_items: "{{ lookup('community.general.dig', 'gmail.com./MX', wantlist=true) }}"
|
||||
|
||||
- name: Lookup multiple names at once
|
||||
ansible.builtin.debug:
|
||||
msg: "A record found {{ item }}"
|
||||
loop: "{{ query('community.general.dig', 'example.org.', 'example.com.', 'gmail.com.') }}"
|
||||
|
||||
- name: Lookup multiple names at once (from list variable)
|
||||
ansible.builtin.debug:
|
||||
msg: "A record found {{ item }}"
|
||||
loop: "{{ query('community.general.dig', *hosts) }}"
|
||||
vars:
|
||||
hosts:
|
||||
- example.org.
|
||||
- example.com.
|
||||
- gmail.com.
|
||||
|
||||
- ansible.builtin.debug:
|
||||
msg: "Reverse DNS for 192.0.2.5 is {{ lookup('community.general.dig', '192.0.2.5/PTR') }}"
|
||||
- ansible.builtin.debug:
|
||||
@@ -129,6 +146,12 @@ RETURN = """
|
||||
AAAA:
|
||||
description:
|
||||
- address
|
||||
CAA:
|
||||
description:
|
||||
- flags
|
||||
- tag
|
||||
- value
|
||||
version_added: 6.3.0
|
||||
CNAME:
|
||||
description:
|
||||
- target
|
||||
@@ -198,7 +221,7 @@ try:
|
||||
import dns.resolver
|
||||
import dns.reversename
|
||||
import dns.rdataclass
|
||||
from dns.rdatatype import (A, AAAA, CNAME, DNAME, DNSKEY, DS, HINFO, LOC,
|
||||
from dns.rdatatype import (A, AAAA, CAA, CNAME, DNAME, DNSKEY, DS, HINFO, LOC,
|
||||
MX, NAPTR, NS, NSEC3PARAM, PTR, RP, SOA, SPF, SRV, SSHFP, TLSA, TXT)
|
||||
HAVE_DNS = True
|
||||
except ImportError:
|
||||
@@ -218,6 +241,7 @@ def make_rdata_dict(rdata):
|
||||
supported_types = {
|
||||
A: ['address'],
|
||||
AAAA: ['address'],
|
||||
CAA: ['flags', 'tag', 'value'],
|
||||
CNAME: ['target'],
|
||||
DNAME: ['target'],
|
||||
DNSKEY: ['flags', 'algorithm', 'protocol', 'key'],
|
||||
@@ -230,7 +254,7 @@ def make_rdata_dict(rdata):
|
||||
NSEC3PARAM: ['algorithm', 'flags', 'iterations', 'salt'],
|
||||
PTR: ['target'],
|
||||
RP: ['mbox', 'txt'],
|
||||
# RRSIG: ['algorithm', 'labels', 'original_ttl', 'expiration', 'inception', 'signature'],
|
||||
# RRSIG: ['type_covered', 'algorithm', 'labels', 'original_ttl', 'expiration', 'inception', 'key_tag', 'signer', 'signature'],
|
||||
SOA: ['mname', 'rname', 'serial', 'refresh', 'retry', 'expire', 'minimum'],
|
||||
SPF: ['strings'],
|
||||
SRV: ['priority', 'weight', 'port', 'target'],
|
||||
@@ -251,6 +275,8 @@ def make_rdata_dict(rdata):
|
||||
|
||||
if rdata.rdtype == DS and f == 'digest':
|
||||
val = dns.rdata._hexify(rdata.digest).replace(' ', '')
|
||||
if rdata.rdtype == DNSKEY and f == 'algorithm':
|
||||
val = int(val)
|
||||
if rdata.rdtype == DNSKEY and f == 'key':
|
||||
val = dns.rdata._base64ify(rdata.key).replace(' ', '')
|
||||
if rdata.rdtype == NSEC3PARAM and f == 'salt':
|
||||
@@ -298,7 +324,7 @@ class LookupModule(LookupBase):
|
||||
edns_size = 4096
|
||||
myres.use_edns(0, ednsflags=dns.flags.DO, payload=edns_size)
|
||||
|
||||
domain = None
|
||||
domains = []
|
||||
qtype = self.get_option('qtype')
|
||||
flat = self.get_option('flat')
|
||||
fail_on_error = self.get_option('fail_on_error')
|
||||
@@ -355,63 +381,71 @@ class LookupModule(LookupBase):
|
||||
if '/' in t:
|
||||
try:
|
||||
domain, qtype = t.split('/')
|
||||
domains.append(domain)
|
||||
except Exception:
|
||||
domain = t
|
||||
domains.append(t)
|
||||
else:
|
||||
domain = t
|
||||
domains.append(t)
|
||||
|
||||
# print "--- domain = {0} qtype={1} rdclass={2}".format(domain, qtype, rdclass)
|
||||
|
||||
if qtype.upper() == 'PTR':
|
||||
reversed_domains = []
|
||||
for domain in domains:
|
||||
try:
|
||||
n = dns.reversename.from_address(domain)
|
||||
reversed_domains.append(n.to_text())
|
||||
except dns.exception.SyntaxError:
|
||||
pass
|
||||
except Exception as e:
|
||||
raise AnsibleError("dns.reversename unhandled exception %s" % to_native(e))
|
||||
domains = reversed_domains
|
||||
|
||||
if len(domains) > 1:
|
||||
real_empty = True
|
||||
|
||||
ret = []
|
||||
|
||||
if qtype.upper() == 'PTR':
|
||||
for domain in domains:
|
||||
try:
|
||||
n = dns.reversename.from_address(domain)
|
||||
domain = n.to_text()
|
||||
except dns.exception.SyntaxError:
|
||||
pass
|
||||
except Exception as e:
|
||||
raise AnsibleError("dns.reversename unhandled exception %s" % to_native(e))
|
||||
answers = myres.query(domain, qtype, rdclass=rdclass)
|
||||
for rdata in answers:
|
||||
s = rdata.to_text()
|
||||
if qtype.upper() == 'TXT':
|
||||
s = s[1:-1] # Strip outside quotes on TXT rdata
|
||||
|
||||
try:
|
||||
answers = myres.query(domain, qtype, rdclass=rdclass)
|
||||
for rdata in answers:
|
||||
s = rdata.to_text()
|
||||
if qtype.upper() == 'TXT':
|
||||
s = s[1:-1] # Strip outside quotes on TXT rdata
|
||||
if flat:
|
||||
ret.append(s)
|
||||
else:
|
||||
try:
|
||||
rd = make_rdata_dict(rdata)
|
||||
rd['owner'] = answers.canonical_name.to_text()
|
||||
rd['type'] = dns.rdatatype.to_text(rdata.rdtype)
|
||||
rd['ttl'] = answers.rrset.ttl
|
||||
rd['class'] = dns.rdataclass.to_text(rdata.rdclass)
|
||||
|
||||
if flat:
|
||||
ret.append(s)
|
||||
else:
|
||||
try:
|
||||
rd = make_rdata_dict(rdata)
|
||||
rd['owner'] = answers.canonical_name.to_text()
|
||||
rd['type'] = dns.rdatatype.to_text(rdata.rdtype)
|
||||
rd['ttl'] = answers.rrset.ttl
|
||||
rd['class'] = dns.rdataclass.to_text(rdata.rdclass)
|
||||
ret.append(rd)
|
||||
except Exception as err:
|
||||
if fail_on_error:
|
||||
raise AnsibleError("Lookup failed: %s" % str(err))
|
||||
ret.append(str(err))
|
||||
|
||||
ret.append(rd)
|
||||
except Exception as err:
|
||||
if fail_on_error:
|
||||
raise AnsibleError("Lookup failed: %s" % str(err))
|
||||
ret.append(str(err))
|
||||
|
||||
except dns.resolver.NXDOMAIN as err:
|
||||
if fail_on_error:
|
||||
raise AnsibleError("Lookup failed: %s" % str(err))
|
||||
if not real_empty:
|
||||
ret.append('NXDOMAIN')
|
||||
except dns.resolver.NoAnswer as err:
|
||||
if fail_on_error:
|
||||
raise AnsibleError("Lookup failed: %s" % str(err))
|
||||
if not real_empty:
|
||||
ret.append("")
|
||||
except dns.resolver.Timeout as err:
|
||||
if fail_on_error:
|
||||
raise AnsibleError("Lookup failed: %s" % str(err))
|
||||
if not real_empty:
|
||||
ret.append("")
|
||||
except dns.exception.DNSException as err:
|
||||
raise AnsibleError("dns.resolver unhandled exception %s" % to_native(err))
|
||||
except dns.resolver.NXDOMAIN as err:
|
||||
if fail_on_error:
|
||||
raise AnsibleError("Lookup failed: %s" % str(err))
|
||||
if not real_empty:
|
||||
ret.append('NXDOMAIN')
|
||||
except dns.resolver.NoAnswer as err:
|
||||
if fail_on_error:
|
||||
raise AnsibleError("Lookup failed: %s" % str(err))
|
||||
if not real_empty:
|
||||
ret.append("")
|
||||
except dns.resolver.Timeout as err:
|
||||
if fail_on_error:
|
||||
raise AnsibleError("Lookup failed: %s" % str(err))
|
||||
if not real_empty:
|
||||
ret.append("")
|
||||
except dns.exception.DNSException as err:
|
||||
raise AnsibleError("dns.resolver unhandled exception %s" % to_native(err))
|
||||
|
||||
return ret
|
||||
|
||||
@@ -136,12 +136,11 @@ RETURN = '''
|
||||
|
||||
import re
|
||||
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
from ansible.utils.display import Display
|
||||
from ansible.errors import AnsibleLookupError
|
||||
from ansible.module_utils.basic import missing_required_lib
|
||||
from ansible.module_utils.common.text.converters import to_native
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
from ansible.errors import AnsibleError, AnsibleLookupError
|
||||
from ansible.utils.display import Display
|
||||
|
||||
try:
|
||||
import etcd3
|
||||
|
||||
@@ -67,7 +67,12 @@ class LookupModule(LookupBase):
|
||||
|
||||
if isinstance(term, string_types):
|
||||
# convert a variable to a list
|
||||
term2 = listify_lookup_plugin_terms(term, templar=self._templar, loader=self._loader)
|
||||
try:
|
||||
term2 = listify_lookup_plugin_terms(term, templar=self._templar)
|
||||
except TypeError:
|
||||
# The loader argument is deprecated in ansible-core 2.14+. Fall back to
|
||||
# pre-2.14 behavior for older ansible-core versions.
|
||||
term2 = listify_lookup_plugin_terms(term, templar=self._templar, loader=self._loader)
|
||||
# but avoid converting a plain string to a list of one string
|
||||
if term2 != [term]:
|
||||
term = term2
|
||||
|
||||
@@ -61,8 +61,6 @@ RETURN = """
|
||||
elements: str
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
from ansible.utils.cmd_functions import run_cmd
|
||||
from ansible.module_utils.common.text.converters import to_text
|
||||
|
||||
@@ -69,7 +69,6 @@ from ansible.utils.display import Display
|
||||
from traceback import format_exception
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
|
||||
display = Display()
|
||||
|
||||
|
||||
212
plugins/lookup/merge_variables.py
Normal file
212
plugins/lookup/merge_variables.py
Normal file
@@ -0,0 +1,212 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Thales Netherlands
|
||||
# Copyright (c) 2021, Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
DOCUMENTATION = """
|
||||
author:
|
||||
- Roy Lenferink (@rlenferink)
|
||||
- Mark Ettema (@m-a-r-k-e)
|
||||
name: merge_variables
|
||||
short_description: merge variables with a certain suffix
|
||||
description:
|
||||
- This lookup returns the merged result of all variables in scope that match the given prefixes, suffixes, or
|
||||
regular expressions, optionally.
|
||||
version_added: 6.5.0
|
||||
options:
|
||||
_terms:
|
||||
description:
|
||||
- Depending on the value of I(pattern_type), this is a list of prefixes, suffixes, or regular expressions
|
||||
that will be used to match all variables that should be merged.
|
||||
required: true
|
||||
type: list
|
||||
elements: str
|
||||
pattern_type:
|
||||
description:
|
||||
- Change the way of searching for the specified pattern.
|
||||
type: str
|
||||
default: 'regex'
|
||||
choices:
|
||||
- prefix
|
||||
- suffix
|
||||
- regex
|
||||
env:
|
||||
- name: ANSIBLE_MERGE_VARIABLES_PATTERN_TYPE
|
||||
ini:
|
||||
- section: merge_variables_lookup
|
||||
key: pattern_type
|
||||
initial_value:
|
||||
description:
|
||||
- An initial value to start with.
|
||||
type: raw
|
||||
override:
|
||||
description:
|
||||
- Return an error, print a warning or ignore it when a key will be overwritten.
|
||||
- The default behavior C(error) makes the plugin fail when a key would be overwritten.
|
||||
- When C(warn) and C(ignore) are used, note that it is important to know that the variables
|
||||
are sorted by name before being merged. Keys for later variables in this order will overwrite
|
||||
keys of the same name for variables earlier in this order. To avoid potential confusion,
|
||||
better use I(override=error) whenever possible.
|
||||
type: str
|
||||
default: 'error'
|
||||
choices:
|
||||
- error
|
||||
- warn
|
||||
- ignore
|
||||
env:
|
||||
- name: ANSIBLE_MERGE_VARIABLES_OVERRIDE
|
||||
ini:
|
||||
- section: merge_variables_lookup
|
||||
key: override
|
||||
"""
|
||||
|
||||
EXAMPLES = """
|
||||
# Some example variables, they can be defined anywhere as long as they are in scope
|
||||
test_init_list:
|
||||
- "list init item 1"
|
||||
- "list init item 2"
|
||||
|
||||
testa__test_list:
|
||||
- "test a item 1"
|
||||
|
||||
testb__test_list:
|
||||
- "test b item 1"
|
||||
|
||||
testa__test_dict:
|
||||
ports:
|
||||
- 1
|
||||
|
||||
testb__test_dict:
|
||||
ports:
|
||||
- 3
|
||||
|
||||
|
||||
# Merge variables that end with '__test_dict' and store the result in a variable 'example_a'
|
||||
example_a: "{{ lookup('community.general.merge_variables', '__test_dict', pattern_type='suffix') }}"
|
||||
|
||||
# The variable example_a now contains:
|
||||
# ports:
|
||||
# - 1
|
||||
# - 3
|
||||
|
||||
|
||||
# Merge variables that match the '^.+__test_list$' regular expression, starting with an initial value and store the
|
||||
# result in a variable 'example_b'
|
||||
example_b: "{{ lookup('community.general.merge_variables', '^.+__test_list$', initial_value=test_init_list) }}"
|
||||
|
||||
# The variable example_b now contains:
|
||||
# - "list init item 1"
|
||||
# - "list init item 2"
|
||||
# - "test a item 1"
|
||||
# - "test b item 1"
|
||||
"""
|
||||
|
||||
RETURN = """
|
||||
_raw:
|
||||
description: In case the search matches list items, a list will be returned. In case the search matches dicts, a
|
||||
dict will be returned.
|
||||
type: raw
|
||||
elements: raw
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
from ansible.errors import AnsibleError
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
from ansible.utils.display import Display
|
||||
|
||||
display = Display()
|
||||
|
||||
|
||||
def _verify_and_get_type(variable):
|
||||
if isinstance(variable, list):
|
||||
return "list"
|
||||
elif isinstance(variable, dict):
|
||||
return "dict"
|
||||
else:
|
||||
raise AnsibleError("Not supported type detected, variable must be a list or a dict")
|
||||
|
||||
|
||||
class LookupModule(LookupBase):
|
||||
|
||||
def run(self, terms, variables=None, **kwargs):
|
||||
self.set_options(direct=kwargs)
|
||||
initial_value = self.get_option("initial_value", None)
|
||||
self._override = self.get_option('override', 'error')
|
||||
self._pattern_type = self.get_option('pattern_type', 'regex')
|
||||
|
||||
ret = []
|
||||
for term in terms:
|
||||
if not isinstance(term, str):
|
||||
raise AnsibleError("Non-string type '{0}' passed, only 'str' types are allowed!".format(type(term)))
|
||||
|
||||
ret.append(self._merge_vars(term, initial_value, variables))
|
||||
|
||||
return ret
|
||||
|
||||
def _var_matches(self, key, search_pattern):
|
||||
if self._pattern_type == "prefix":
|
||||
return key.startswith(search_pattern)
|
||||
elif self._pattern_type == "suffix":
|
||||
return key.endswith(search_pattern)
|
||||
elif self._pattern_type == "regex":
|
||||
matcher = re.compile(search_pattern)
|
||||
return matcher.search(key)
|
||||
|
||||
return False
|
||||
|
||||
def _merge_vars(self, search_pattern, initial_value, variables):
|
||||
display.vvv("Merge variables with {0}: {1}".format(self._pattern_type, search_pattern))
|
||||
var_merge_names = sorted([key for key in variables.keys() if self._var_matches(key, search_pattern)])
|
||||
display.vvv("The following variables will be merged: {0}".format(var_merge_names))
|
||||
|
||||
prev_var_type = None
|
||||
result = None
|
||||
|
||||
if initial_value is not None:
|
||||
prev_var_type = _verify_and_get_type(initial_value)
|
||||
result = initial_value
|
||||
|
||||
for var_name in var_merge_names:
|
||||
var_value = self._templar.template(variables[var_name]) # Render jinja2 templates
|
||||
var_type = _verify_and_get_type(var_value)
|
||||
|
||||
if prev_var_type is None:
|
||||
prev_var_type = var_type
|
||||
elif prev_var_type != var_type:
|
||||
raise AnsibleError("Unable to merge, not all variables are of the same type")
|
||||
|
||||
if result is None:
|
||||
result = var_value
|
||||
continue
|
||||
|
||||
if var_type == "dict":
|
||||
result = self._merge_dict(var_value, result, [var_name])
|
||||
else: # var_type == "list"
|
||||
result += var_value
|
||||
|
||||
return result
|
||||
|
||||
def _merge_dict(self, src, dest, path):
|
||||
for key, value in src.items():
|
||||
if isinstance(value, dict):
|
||||
node = dest.setdefault(key, {})
|
||||
self._merge_dict(value, node, path + [key])
|
||||
elif isinstance(value, list) and key in dest:
|
||||
dest[key] += value
|
||||
else:
|
||||
if (key in dest) and dest[key] != value:
|
||||
msg = "The key '{0}' with value '{1}' will be overwritten with value '{2}' from '{3}.{0}'".format(
|
||||
key, dest[key], value, ".".join(path))
|
||||
|
||||
if self._override == "error":
|
||||
raise AnsibleError(msg)
|
||||
if self._override == "warn":
|
||||
display.warning(msg)
|
||||
|
||||
dest[key] = value
|
||||
|
||||
return dest
|
||||
@@ -32,7 +32,7 @@ DOCUMENTATION = '''
|
||||
section:
|
||||
description: Item section containing the field to retrieve (case-insensitive). If absent will return first match from any section.
|
||||
domain:
|
||||
description: Domain of 1Password. Default is U(1password.com).
|
||||
description: Domain of 1Password.
|
||||
version_added: 3.2.0
|
||||
default: '1password.com'
|
||||
type: str
|
||||
@@ -488,7 +488,7 @@ class OnePassCLIv2(OnePassCLIBase):
|
||||
account = "{subdomain}.{domain}".format(subdomain=self.subdomain, domain=self.domain)
|
||||
args.extend(["--account", account])
|
||||
|
||||
rc, out, err = self._run(args)
|
||||
rc, out, err = self._run(args, ignore_errors=True)
|
||||
|
||||
return not bool(rc)
|
||||
|
||||
|
||||
@@ -30,6 +30,11 @@ DOCUMENTATION = '''
|
||||
description: Item section containing the field to retrieve (case-insensitive). If absent will return first match from any section.
|
||||
subdomain:
|
||||
description: The 1Password subdomain to authenticate against.
|
||||
domain:
|
||||
description: Domain of 1Password.
|
||||
version_added: 6.0.0
|
||||
default: '1password.com'
|
||||
type: str
|
||||
username:
|
||||
description: The username used to sign in.
|
||||
secret_key:
|
||||
|
||||
@@ -209,7 +209,6 @@ import time
|
||||
import yaml
|
||||
|
||||
from ansible.errors import AnsibleError, AnsibleAssertionError
|
||||
from ansible.module_utils.common.file import FileLock
|
||||
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
|
||||
from ansible.module_utils.parsing.convert_bool import boolean
|
||||
from ansible.utils.display import Display
|
||||
@@ -217,6 +216,8 @@ from ansible.utils.encrypt import random_password
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
from ansible import constants as C
|
||||
|
||||
from ansible_collections.community.general.plugins.module_utils._filelock import FileLock
|
||||
|
||||
display = Display()
|
||||
|
||||
|
||||
|
||||
@@ -73,8 +73,6 @@ _raw:
|
||||
elements: str
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
HAVE_REDIS = False
|
||||
try:
|
||||
import redis
|
||||
|
||||
@@ -26,6 +26,18 @@ options:
|
||||
description: The integer ID of the secret.
|
||||
required: true
|
||||
type: int
|
||||
fetch_attachments:
|
||||
description:
|
||||
- Boolean flag which indicates whether attached files will get downloaded or not.
|
||||
- The download will only happen if I(file_download_path) has been provided.
|
||||
required: false
|
||||
type: bool
|
||||
version_added: 7.0.0
|
||||
file_download_path:
|
||||
description: Indicate the file attachment download location.
|
||||
required: false
|
||||
type: path
|
||||
version_added: 7.0.0
|
||||
base_url:
|
||||
description: The base URL of the server, e.g. C(https://localhost/SecretServer).
|
||||
env:
|
||||
@@ -157,10 +169,35 @@ EXAMPLES = r"""
|
||||
tasks:
|
||||
- ansible.builtin.debug:
|
||||
msg: the password is {{ secret_password }}
|
||||
|
||||
# Private key stores into certificate file which is attached with secret.
|
||||
# If fetch_attachments=True then private key file will be download on specified path
|
||||
# and file content will display in debug message.
|
||||
- hosts: localhost
|
||||
vars:
|
||||
secret: >-
|
||||
{{
|
||||
lookup(
|
||||
'community.general.tss',
|
||||
102,
|
||||
fetch_attachments=True,
|
||||
file_download_path='/home/certs',
|
||||
base_url='https://secretserver.domain.com/SecretServer/',
|
||||
token='thycotic_access_token'
|
||||
)
|
||||
}}
|
||||
tasks:
|
||||
- ansible.builtin.debug:
|
||||
msg: >
|
||||
the private key is {{
|
||||
(secret['items']
|
||||
| items2dict(key_name='slug',
|
||||
value_name='itemValue'))['private-key']
|
||||
}}
|
||||
"""
|
||||
|
||||
import abc
|
||||
|
||||
import os
|
||||
from ansible.errors import AnsibleError, AnsibleOptionsError
|
||||
from ansible.module_utils import six
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
@@ -211,13 +248,27 @@ class TSSClient(object):
|
||||
else:
|
||||
return TSSClientV0(**server_parameters)
|
||||
|
||||
def get_secret(self, term):
|
||||
def get_secret(self, term, fetch_file_attachments, file_download_path):
|
||||
display.debug("tss_lookup term: %s" % term)
|
||||
|
||||
secret_id = self._term_to_secret_id(term)
|
||||
display.vvv(u"Secret Server lookup of Secret with ID %d" % secret_id)
|
||||
|
||||
return self._client.get_secret_json(secret_id)
|
||||
if fetch_file_attachments:
|
||||
obj = self._client.get_secret(secret_id, fetch_file_attachments)
|
||||
for i in obj['items']:
|
||||
if file_download_path and os.path.isdir(file_download_path):
|
||||
if i['isFile']:
|
||||
try:
|
||||
with open(os.path.join(file_download_path, str(obj['id']) + "_" + i['slug']), "w") as f:
|
||||
f.write(i['itemValue'].text)
|
||||
i['itemValue'] = "*** Not Valid For Display ***"
|
||||
except ValueError:
|
||||
raise AnsibleOptionsError("Failed to download {0}".format(str(i['slug'])))
|
||||
else:
|
||||
raise AnsibleOptionsError("File download path does not exist")
|
||||
return obj
|
||||
else:
|
||||
return self._client.get_secret_json(secret_id)
|
||||
|
||||
@staticmethod
|
||||
def _term_to_secret_id(term):
|
||||
@@ -294,6 +345,6 @@ class LookupModule(LookupBase):
|
||||
)
|
||||
|
||||
try:
|
||||
return [tss.get_secret(term) for term in terms]
|
||||
return [tss.get_secret(term, self.get_option("fetch_attachments"), self.get_option("file_download_path")) for term in terms]
|
||||
except SecretServerError as error:
|
||||
raise AnsibleError("Secret Server lookup failure: %s" % error.message)
|
||||
|
||||
109
plugins/module_utils/_filelock.py
Normal file
109
plugins/module_utils/_filelock.py
Normal file
@@ -0,0 +1,109 @@
|
||||
# Copyright (c) 2018, Ansible Project
|
||||
# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
# NOTE:
|
||||
# This has been vendored from ansible.module_utils.common.file. This code has been removed from there for ansible-core 2.16.
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
import os
|
||||
import stat
|
||||
import time
|
||||
import fcntl
|
||||
import sys
|
||||
|
||||
from contextlib import contextmanager
|
||||
|
||||
|
||||
class LockTimeout(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class FileLock:
|
||||
'''
|
||||
Currently FileLock is implemented via fcntl.flock on a lock file, however this
|
||||
behaviour may change in the future. Avoid mixing lock types fcntl.flock,
|
||||
fcntl.lockf and module_utils.common.file.FileLock as it will certainly cause
|
||||
unwanted and/or unexpected behaviour
|
||||
'''
|
||||
def __init__(self):
|
||||
self.lockfd = None
|
||||
|
||||
@contextmanager
|
||||
def lock_file(self, path, tmpdir, lock_timeout=None):
|
||||
'''
|
||||
Context for lock acquisition
|
||||
'''
|
||||
try:
|
||||
self.set_lock(path, tmpdir, lock_timeout)
|
||||
yield
|
||||
finally:
|
||||
self.unlock()
|
||||
|
||||
def set_lock(self, path, tmpdir, lock_timeout=None):
|
||||
'''
|
||||
Create a lock file based on path with flock to prevent other processes
|
||||
using given path.
|
||||
Please note that currently file locking only works when it's executed by
|
||||
the same user, I.E single user scenarios
|
||||
|
||||
:kw path: Path (file) to lock
|
||||
:kw tmpdir: Path where to place the temporary .lock file
|
||||
:kw lock_timeout:
|
||||
Wait n seconds for lock acquisition, fail if timeout is reached.
|
||||
0 = Do not wait, fail if lock cannot be acquired immediately,
|
||||
Default is None, wait indefinitely until lock is released.
|
||||
:returns: True
|
||||
'''
|
||||
lock_path = os.path.join(tmpdir, 'ansible-{0}.lock'.format(os.path.basename(path)))
|
||||
l_wait = 0.1
|
||||
r_exception = IOError
|
||||
if sys.version_info[0] == 3:
|
||||
r_exception = BlockingIOError
|
||||
|
||||
self.lockfd = open(lock_path, 'w')
|
||||
|
||||
if lock_timeout <= 0:
|
||||
fcntl.flock(self.lockfd, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||
os.chmod(lock_path, stat.S_IWRITE | stat.S_IREAD)
|
||||
return True
|
||||
|
||||
if lock_timeout:
|
||||
e_secs = 0
|
||||
while e_secs < lock_timeout:
|
||||
try:
|
||||
fcntl.flock(self.lockfd, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||
os.chmod(lock_path, stat.S_IWRITE | stat.S_IREAD)
|
||||
return True
|
||||
except r_exception:
|
||||
time.sleep(l_wait)
|
||||
e_secs += l_wait
|
||||
continue
|
||||
|
||||
self.lockfd.close()
|
||||
raise LockTimeout('{0} sec'.format(lock_timeout))
|
||||
|
||||
fcntl.flock(self.lockfd, fcntl.LOCK_EX)
|
||||
os.chmod(lock_path, stat.S_IWRITE | stat.S_IREAD)
|
||||
|
||||
return True
|
||||
|
||||
def unlock(self):
|
||||
'''
|
||||
Make sure lock file is available for everyone and Unlock the file descriptor
|
||||
locked by set_lock
|
||||
|
||||
:returns: True
|
||||
'''
|
||||
if not self.lockfd:
|
||||
return True
|
||||
|
||||
try:
|
||||
fcntl.flock(self.lockfd, fcntl.LOCK_UN)
|
||||
self.lockfd.close()
|
||||
except ValueError: # file wasn't opened, let context manager fail gracefully
|
||||
pass
|
||||
|
||||
return True
|
||||
258
plugins/module_utils/_stormssh.py
Normal file
258
plugins/module_utils/_stormssh.py
Normal file
@@ -0,0 +1,258 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# This code is part of Ansible, but is an independent component.
|
||||
# This particular file snippet, and this file snippet only, is based on
|
||||
# the config parser from here: https://github.com/emre/storm/blob/master/storm/parsers/ssh_config_parser.py
|
||||
# Copyright (C) <2013> <Emre Yilmaz>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
import os
|
||||
import re
|
||||
import traceback
|
||||
from operator import itemgetter
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
try:
|
||||
from paramiko.config import SSHConfig
|
||||
except ImportError:
|
||||
SSHConfig = object
|
||||
HAS_PARAMIKO = False
|
||||
PARAMIKO_IMPORT_ERROR = traceback.format_exc()
|
||||
else:
|
||||
HAS_PARAMIKO = True
|
||||
PARAMIKO_IMPORT_ERROR = None
|
||||
|
||||
|
||||
class StormConfig(SSHConfig):
|
||||
def parse(self, file_obj):
|
||||
"""
|
||||
Read an OpenSSH config from the given file object.
|
||||
@param file_obj: a file-like object to read the config file from
|
||||
@type file_obj: file
|
||||
"""
|
||||
order = 1
|
||||
host = {"host": ['*'], "config": {}, }
|
||||
for line in file_obj:
|
||||
line = line.rstrip('\n').lstrip()
|
||||
if line == '':
|
||||
self._config.append({
|
||||
'type': 'empty_line',
|
||||
'value': line,
|
||||
'host': '',
|
||||
'order': order,
|
||||
})
|
||||
order += 1
|
||||
continue
|
||||
|
||||
if line.startswith('#'):
|
||||
self._config.append({
|
||||
'type': 'comment',
|
||||
'value': line,
|
||||
'host': '',
|
||||
'order': order,
|
||||
})
|
||||
order += 1
|
||||
continue
|
||||
|
||||
if '=' in line:
|
||||
# Ensure ProxyCommand gets properly split
|
||||
if line.lower().strip().startswith('proxycommand'):
|
||||
proxy_re = re.compile(r"^(proxycommand)\s*=*\s*(.*)", re.I)
|
||||
match = proxy_re.match(line)
|
||||
key, value = match.group(1).lower(), match.group(2)
|
||||
else:
|
||||
key, value = line.split('=', 1)
|
||||
key = key.strip().lower()
|
||||
else:
|
||||
# find first whitespace, and split there
|
||||
i = 0
|
||||
while (i < len(line)) and not line[i].isspace():
|
||||
i += 1
|
||||
if i == len(line):
|
||||
raise Exception('Unparsable line: %r' % line)
|
||||
key = line[:i].lower()
|
||||
value = line[i:].lstrip()
|
||||
if key == 'host':
|
||||
self._config.append(host)
|
||||
value = value.split()
|
||||
host = {
|
||||
key: value,
|
||||
'config': {},
|
||||
'type': 'entry',
|
||||
'order': order
|
||||
}
|
||||
order += 1
|
||||
elif key in ['identityfile', 'localforward', 'remoteforward']:
|
||||
if key in host['config']:
|
||||
host['config'][key].append(value)
|
||||
else:
|
||||
host['config'][key] = [value]
|
||||
elif key not in host['config']:
|
||||
host['config'].update({key: value})
|
||||
self._config.append(host)
|
||||
|
||||
|
||||
class ConfigParser(object):
|
||||
"""
|
||||
Config parser for ~/.ssh/config files.
|
||||
"""
|
||||
|
||||
def __init__(self, ssh_config_file=None):
|
||||
if not ssh_config_file:
|
||||
ssh_config_file = self.get_default_ssh_config_file()
|
||||
|
||||
self.defaults = {}
|
||||
|
||||
self.ssh_config_file = ssh_config_file
|
||||
|
||||
if not os.path.exists(self.ssh_config_file):
|
||||
if not os.path.exists(os.path.dirname(self.ssh_config_file)):
|
||||
os.makedirs(os.path.dirname(self.ssh_config_file))
|
||||
open(self.ssh_config_file, 'w+').close()
|
||||
os.chmod(self.ssh_config_file, 0o600)
|
||||
|
||||
self.config_data = []
|
||||
|
||||
def get_default_ssh_config_file(self):
|
||||
return os.path.expanduser("~/.ssh/config")
|
||||
|
||||
def load(self):
|
||||
config = StormConfig()
|
||||
|
||||
with open(self.ssh_config_file) as fd:
|
||||
config.parse(fd)
|
||||
|
||||
for entry in config.__dict__.get("_config"):
|
||||
if entry.get("host") == ["*"]:
|
||||
self.defaults.update(entry.get("config"))
|
||||
|
||||
if entry.get("type") in ["comment", "empty_line"]:
|
||||
self.config_data.append(entry)
|
||||
continue
|
||||
|
||||
host_item = {
|
||||
'host': entry["host"][0],
|
||||
'options': entry.get("config"),
|
||||
'type': 'entry',
|
||||
'order': entry.get("order", 0),
|
||||
}
|
||||
|
||||
if len(entry["host"]) > 1:
|
||||
host_item.update({
|
||||
'host': " ".join(entry["host"]),
|
||||
})
|
||||
# minor bug in paramiko.SSHConfig that duplicates
|
||||
# "Host *" entries.
|
||||
if entry.get("config") and len(entry.get("config")) > 0:
|
||||
self.config_data.append(host_item)
|
||||
|
||||
return self.config_data
|
||||
|
||||
def add_host(self, host, options):
|
||||
self.config_data.append({
|
||||
'host': host,
|
||||
'options': options,
|
||||
'order': self.get_last_index(),
|
||||
})
|
||||
|
||||
return self
|
||||
|
||||
def update_host(self, host, options, use_regex=False):
|
||||
for index, host_entry in enumerate(self.config_data):
|
||||
if host_entry.get("host") == host or \
|
||||
(use_regex and re.match(host, host_entry.get("host"))):
|
||||
|
||||
if 'deleted_fields' in options:
|
||||
deleted_fields = options.pop("deleted_fields")
|
||||
for deleted_field in deleted_fields:
|
||||
del self.config_data[index]["options"][deleted_field]
|
||||
|
||||
self.config_data[index]["options"].update(options)
|
||||
|
||||
return self
|
||||
|
||||
def search_host(self, search_string):
|
||||
results = []
|
||||
for host_entry in self.config_data:
|
||||
if host_entry.get("type") != 'entry':
|
||||
continue
|
||||
if host_entry.get("host") == "*":
|
||||
continue
|
||||
|
||||
searchable_information = host_entry.get("host")
|
||||
for key, value in host_entry.get("options").items():
|
||||
if isinstance(value, list):
|
||||
value = " ".join(value)
|
||||
if isinstance(value, int):
|
||||
value = str(value)
|
||||
|
||||
searchable_information += " " + value
|
||||
|
||||
if search_string in searchable_information:
|
||||
results.append(host_entry)
|
||||
|
||||
return results
|
||||
|
||||
def delete_host(self, host):
|
||||
found = 0
|
||||
for index, host_entry in enumerate(self.config_data):
|
||||
if host_entry.get("host") == host:
|
||||
del self.config_data[index]
|
||||
found += 1
|
||||
|
||||
if found == 0:
|
||||
raise ValueError('No host found')
|
||||
return self
|
||||
|
||||
def delete_all_hosts(self):
|
||||
self.config_data = []
|
||||
self.write_to_ssh_config()
|
||||
|
||||
return self
|
||||
|
||||
def dump(self):
|
||||
if len(self.config_data) < 1:
|
||||
return
|
||||
|
||||
file_content = ""
|
||||
self.config_data = sorted(self.config_data, key=itemgetter("order"))
|
||||
|
||||
for host_item in self.config_data:
|
||||
if host_item.get("type") in ['comment', 'empty_line']:
|
||||
file_content += host_item.get("value") + "\n"
|
||||
continue
|
||||
host_item_content = "Host {0}\n".format(host_item.get("host"))
|
||||
for key, value in host_item.get("options").items():
|
||||
if isinstance(value, list):
|
||||
sub_content = ""
|
||||
for value_ in value:
|
||||
sub_content += " {0} {1}\n".format(
|
||||
key, value_
|
||||
)
|
||||
host_item_content += sub_content
|
||||
else:
|
||||
host_item_content += " {0} {1}\n".format(
|
||||
key, value
|
||||
)
|
||||
file_content += host_item_content
|
||||
|
||||
return file_content
|
||||
|
||||
def write_to_ssh_config(self):
|
||||
with open(self.ssh_config_file, 'w+') as f:
|
||||
data = self.dump()
|
||||
if data:
|
||||
f.write(data)
|
||||
return self
|
||||
|
||||
def get_last_index(self):
|
||||
last_index = 0
|
||||
indexes = []
|
||||
for item in self.config_data:
|
||||
if item.get("order"):
|
||||
indexes.append(item.get("order"))
|
||||
if len(indexes) > 0:
|
||||
last_index = max(indexes)
|
||||
|
||||
return last_index
|
||||
464
plugins/module_utils/btrfs.py
Normal file
464
plugins/module_utils/btrfs.py
Normal file
@@ -0,0 +1,464 @@
|
||||
# Copyright (c) 2022, Gregory Furlong <gnfzdz@fzdz.io>
|
||||
# GNU General Public License v3.0+ (see COPYING 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 ansible.module_utils.common.text.converters import to_bytes
|
||||
import re
|
||||
import os
|
||||
|
||||
|
||||
def normalize_subvolume_path(path):
|
||||
"""
|
||||
Normalizes btrfs subvolume paths to ensure exactly one leading slash, no trailing slashes and no consecutive slashes.
|
||||
In addition, if the path is prefixed with a leading <FS_TREE>, this value is removed.
|
||||
"""
|
||||
fstree_stripped = re.sub(r'^<FS_TREE>', '', path)
|
||||
result = re.sub(r'/+$', '', re.sub(r'/+', '/', '/' + fstree_stripped))
|
||||
return result if len(result) > 0 else '/'
|
||||
|
||||
|
||||
class BtrfsModuleException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class BtrfsCommands(object):
|
||||
|
||||
"""
|
||||
Provides access to a subset of the Btrfs command line
|
||||
"""
|
||||
|
||||
def __init__(self, module):
|
||||
self.__module = module
|
||||
self.__btrfs = self.__module.get_bin_path("btrfs", required=True)
|
||||
|
||||
def filesystem_show(self):
|
||||
command = "%s filesystem show -d" % (self.__btrfs)
|
||||
result = self.__module.run_command(command, check_rc=True)
|
||||
stdout = [x.strip() for x in result[1].splitlines()]
|
||||
filesystems = []
|
||||
current = None
|
||||
for line in stdout:
|
||||
if line.startswith('Label'):
|
||||
current = self.__parse_filesystem(line)
|
||||
filesystems.append(current)
|
||||
elif line.startswith('devid'):
|
||||
current['devices'].append(self.__parse_filesystem_device(line))
|
||||
return filesystems
|
||||
|
||||
def __parse_filesystem(self, line):
|
||||
label = re.sub(r'\s*uuid:.*$', '', re.sub(r'^Label:\s*', '', line))
|
||||
id = re.sub(r'^.*uuid:\s*', '', line)
|
||||
|
||||
filesystem = {}
|
||||
filesystem['label'] = label.strip("'") if label != 'none' else None
|
||||
filesystem['uuid'] = id
|
||||
filesystem['devices'] = []
|
||||
filesystem['mountpoints'] = []
|
||||
filesystem['subvolumes'] = []
|
||||
filesystem['default_subvolid'] = None
|
||||
return filesystem
|
||||
|
||||
def __parse_filesystem_device(self, line):
|
||||
return re.sub(r'^.*path\s', '', line)
|
||||
|
||||
def subvolumes_list(self, filesystem_path):
|
||||
command = "%s subvolume list -tap %s" % (self.__btrfs, filesystem_path)
|
||||
result = self.__module.run_command(command, check_rc=True)
|
||||
stdout = [x.split('\t') for x in result[1].splitlines()]
|
||||
subvolumes = [{'id': 5, 'parent': None, 'path': '/'}]
|
||||
if len(stdout) > 2:
|
||||
subvolumes.extend([self.__parse_subvolume_list_record(x) for x in stdout[2:]])
|
||||
return subvolumes
|
||||
|
||||
def __parse_subvolume_list_record(self, item):
|
||||
return {
|
||||
'id': int(item[0]),
|
||||
'parent': int(item[2]),
|
||||
'path': normalize_subvolume_path(item[5]),
|
||||
}
|
||||
|
||||
def subvolume_get_default(self, filesystem_path):
|
||||
command = [self.__btrfs, "subvolume", "get-default", to_bytes(filesystem_path)]
|
||||
result = self.__module.run_command(command, check_rc=True)
|
||||
# ID [n] ...
|
||||
return int(result[1].strip().split()[1])
|
||||
|
||||
def subvolume_set_default(self, filesystem_path, subvolume_id):
|
||||
command = [self.__btrfs, "subvolume", "set-default", str(subvolume_id), to_bytes(filesystem_path)]
|
||||
result = self.__module.run_command(command, check_rc=True)
|
||||
|
||||
def subvolume_create(self, subvolume_path):
|
||||
command = [self.__btrfs, "subvolume", "create", to_bytes(subvolume_path)]
|
||||
result = self.__module.run_command(command, check_rc=True)
|
||||
|
||||
def subvolume_snapshot(self, snapshot_source, snapshot_destination):
|
||||
command = [self.__btrfs, "subvolume", "snapshot", to_bytes(snapshot_source), to_bytes(snapshot_destination)]
|
||||
result = self.__module.run_command(command, check_rc=True)
|
||||
|
||||
def subvolume_delete(self, subvolume_path):
|
||||
command = [self.__btrfs, "subvolume", "delete", to_bytes(subvolume_path)]
|
||||
result = self.__module.run_command(command, check_rc=True)
|
||||
|
||||
|
||||
class BtrfsInfoProvider(object):
|
||||
|
||||
"""
|
||||
Utility providing details of the currently available btrfs filesystems
|
||||
"""
|
||||
|
||||
def __init__(self, module):
|
||||
self.__module = module
|
||||
self.__btrfs_api = BtrfsCommands(module)
|
||||
self.__findmnt_path = self.__module.get_bin_path("findmnt", required=True)
|
||||
|
||||
def get_filesystems(self):
|
||||
filesystems = self.__btrfs_api.filesystem_show()
|
||||
mountpoints = self.__find_mountpoints()
|
||||
for filesystem in filesystems:
|
||||
device_mountpoints = self.__filter_mountpoints_for_devices(mountpoints, filesystem['devices'])
|
||||
filesystem['mountpoints'] = device_mountpoints
|
||||
|
||||
if len(device_mountpoints) > 0:
|
||||
|
||||
# any path within the filesystem can be used to query metadata
|
||||
mountpoint = device_mountpoints[0]['mountpoint']
|
||||
filesystem['subvolumes'] = self.get_subvolumes(mountpoint)
|
||||
filesystem['default_subvolid'] = self.get_default_subvolume_id(mountpoint)
|
||||
|
||||
return filesystems
|
||||
|
||||
def get_mountpoints(self, filesystem_devices):
|
||||
mountpoints = self.__find_mountpoints()
|
||||
return self.__filter_mountpoints_for_devices(mountpoints, filesystem_devices)
|
||||
|
||||
def get_subvolumes(self, filesystem_path):
|
||||
return self.__btrfs_api.subvolumes_list(filesystem_path)
|
||||
|
||||
def get_default_subvolume_id(self, filesystem_path):
|
||||
return self.__btrfs_api.subvolume_get_default(filesystem_path)
|
||||
|
||||
def __filter_mountpoints_for_devices(self, mountpoints, devices):
|
||||
return [m for m in mountpoints if (m['device'] in devices)]
|
||||
|
||||
def __find_mountpoints(self):
|
||||
command = "%s -t btrfs -nvP" % self.__findmnt_path
|
||||
result = self.__module.run_command(command)
|
||||
mountpoints = []
|
||||
if result[0] == 0:
|
||||
lines = result[1].splitlines()
|
||||
for line in lines:
|
||||
mountpoint = self.__parse_mountpoint_pairs(line)
|
||||
mountpoints.append(mountpoint)
|
||||
return mountpoints
|
||||
|
||||
def __parse_mountpoint_pairs(self, line):
|
||||
pattern = re.compile(r'^TARGET="(?P<target>.*)"\s+SOURCE="(?P<source>.*)"\s+FSTYPE="(?P<fstype>.*)"\s+OPTIONS="(?P<options>.*)"\s*$')
|
||||
match = pattern.search(line)
|
||||
if match is not None:
|
||||
groups = match.groupdict()
|
||||
|
||||
return {
|
||||
'mountpoint': groups['target'],
|
||||
'device': groups['source'],
|
||||
'subvolid': self.__extract_mount_subvolid(groups['options']),
|
||||
}
|
||||
else:
|
||||
raise BtrfsModuleException("Failed to parse findmnt result for line: '%s'" % line)
|
||||
|
||||
def __extract_mount_subvolid(self, mount_options):
|
||||
for option in mount_options.split(','):
|
||||
if option.startswith('subvolid='):
|
||||
return int(option[len('subvolid='):])
|
||||
raise BtrfsModuleException("Failed to find subvolid for mountpoint in options '%s'" % mount_options)
|
||||
|
||||
|
||||
class BtrfsSubvolume(object):
|
||||
|
||||
"""
|
||||
Wrapper class providing convenience methods for inspection of a btrfs subvolume
|
||||
"""
|
||||
|
||||
def __init__(self, filesystem, subvolume_id):
|
||||
self.__filesystem = filesystem
|
||||
self.__subvolume_id = subvolume_id
|
||||
|
||||
def get_filesystem(self):
|
||||
return self.__filesystem
|
||||
|
||||
def is_mounted(self):
|
||||
mountpoints = self.get_mountpoints()
|
||||
return mountpoints is not None and len(mountpoints) > 0
|
||||
|
||||
def is_filesystem_root(self):
|
||||
return 5 == self.__subvolume_id
|
||||
|
||||
def is_filesystem_default(self):
|
||||
return self.__filesystem.default_subvolid == self.__subvolume_id
|
||||
|
||||
def get_mounted_path(self):
|
||||
mountpoints = self.get_mountpoints()
|
||||
if mountpoints is not None and len(mountpoints) > 0:
|
||||
return mountpoints[0]
|
||||
elif self.parent is not None:
|
||||
parent = self.__filesystem.get_subvolume_by_id(self.parent)
|
||||
parent_path = parent.get_mounted_path()
|
||||
if parent_path is not None:
|
||||
return parent_path + os.path.sep + self.name
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_mountpoints(self):
|
||||
return self.__filesystem.get_mountpoints_by_subvolume_id(self.__subvolume_id)
|
||||
|
||||
def get_child_relative_path(self, absolute_child_path):
|
||||
"""
|
||||
Get the relative path from this subvolume to the named child subvolume.
|
||||
The provided parameter is expected to be normalized as by normalize_subvolume_path.
|
||||
"""
|
||||
path = self.path
|
||||
if absolute_child_path.startswith(path):
|
||||
relative = absolute_child_path[len(path):]
|
||||
return re.sub(r'^/*', '', relative)
|
||||
else:
|
||||
raise BtrfsModuleException("Path '%s' doesn't start with '%s'" % (absolute_child_path, path))
|
||||
|
||||
def get_parent_subvolume(self):
|
||||
parent_id = self.parent
|
||||
return self.__filesystem.get_subvolume_by_id(parent_id) if parent_id is not None else None
|
||||
|
||||
def get_child_subvolumes(self):
|
||||
return self.__filesystem.get_subvolume_children(self.__subvolume_id)
|
||||
|
||||
@property
|
||||
def __info(self):
|
||||
return self.__filesystem.get_subvolume_info_for_id(self.__subvolume_id)
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self.__subvolume_id
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.path.split('/').pop()
|
||||
|
||||
@property
|
||||
def path(self):
|
||||
return self.__info['path']
|
||||
|
||||
@property
|
||||
def parent(self):
|
||||
return self.__info['parent']
|
||||
|
||||
|
||||
class BtrfsFilesystem(object):
|
||||
|
||||
"""
|
||||
Wrapper class providing convenience methods for inspection of a btrfs filesystem
|
||||
"""
|
||||
|
||||
def __init__(self, info, provider, module):
|
||||
self.__provider = provider
|
||||
|
||||
# constant for module execution
|
||||
self.__uuid = info['uuid']
|
||||
self.__label = info['label']
|
||||
self.__devices = info['devices']
|
||||
|
||||
# refreshable
|
||||
self.__default_subvolid = info['default_subvolid'] if 'default_subvolid' in info else None
|
||||
self.__update_mountpoints(info['mountpoints'] if 'mountpoints' in info else [])
|
||||
self.__update_subvolumes(info['subvolumes'] if 'subvolumes' in info else [])
|
||||
|
||||
@property
|
||||
def uuid(self):
|
||||
return self.__uuid
|
||||
|
||||
@property
|
||||
def label(self):
|
||||
return self.__label
|
||||
|
||||
@property
|
||||
def default_subvolid(self):
|
||||
return self.__default_subvolid
|
||||
|
||||
@property
|
||||
def devices(self):
|
||||
return list(self.__devices)
|
||||
|
||||
def refresh(self):
|
||||
self.refresh_mountpoints()
|
||||
self.refresh_subvolumes()
|
||||
self.refresh_default_subvolume()
|
||||
|
||||
def refresh_mountpoints(self):
|
||||
mountpoints = self.__provider.get_mountpoints(list(self.__devices))
|
||||
self.__update_mountpoints(mountpoints)
|
||||
|
||||
def __update_mountpoints(self, mountpoints):
|
||||
self.__mountpoints = dict()
|
||||
for i in mountpoints:
|
||||
subvolid = i['subvolid']
|
||||
mountpoint = i['mountpoint']
|
||||
if subvolid not in self.__mountpoints:
|
||||
self.__mountpoints[subvolid] = []
|
||||
self.__mountpoints[subvolid].append(mountpoint)
|
||||
|
||||
def refresh_subvolumes(self):
|
||||
filesystem_path = self.get_any_mountpoint()
|
||||
if filesystem_path is not None:
|
||||
subvolumes = self.__provider.get_subvolumes(filesystem_path)
|
||||
self.__update_subvolumes(subvolumes)
|
||||
|
||||
def __update_subvolumes(self, subvolumes):
|
||||
# TODO strategy for retaining information on deleted subvolumes?
|
||||
self.__subvolumes = dict()
|
||||
for subvolume in subvolumes:
|
||||
self.__subvolumes[subvolume['id']] = subvolume
|
||||
|
||||
def refresh_default_subvolume(self):
|
||||
filesystem_path = self.get_any_mountpoint()
|
||||
if filesystem_path is not None:
|
||||
self.__default_subvolid = self.__provider.get_default_subvolume_id(filesystem_path)
|
||||
|
||||
def contains_device(self, device):
|
||||
return device in self.__devices
|
||||
|
||||
def contains_subvolume(self, subvolume):
|
||||
return self.get_subvolume_by_name(subvolume) is not None
|
||||
|
||||
def get_subvolume_by_id(self, subvolume_id):
|
||||
return BtrfsSubvolume(self, subvolume_id) if subvolume_id in self.__subvolumes else None
|
||||
|
||||
def get_subvolume_info_for_id(self, subvolume_id):
|
||||
return self.__subvolumes[subvolume_id] if subvolume_id in self.__subvolumes else None
|
||||
|
||||
def get_subvolume_by_name(self, subvolume):
|
||||
for subvolume_info in self.__subvolumes.values():
|
||||
if subvolume_info['path'] == subvolume:
|
||||
return BtrfsSubvolume(self, subvolume_info['id'])
|
||||
return None
|
||||
|
||||
def get_any_mountpoint(self):
|
||||
for subvol_mountpoints in self.__mountpoints.values():
|
||||
if len(subvol_mountpoints) > 0:
|
||||
return subvol_mountpoints[0]
|
||||
# maybe error?
|
||||
return None
|
||||
|
||||
def get_any_mounted_subvolume(self):
|
||||
for subvolid, subvol_mountpoints in self.__mountpoints.items():
|
||||
if len(subvol_mountpoints) > 0:
|
||||
return self.get_subvolume_by_id(subvolid)
|
||||
return None
|
||||
|
||||
def get_mountpoints_by_subvolume_id(self, subvolume_id):
|
||||
return self.__mountpoints[subvolume_id] if subvolume_id in self.__mountpoints else []
|
||||
|
||||
def get_nearest_subvolume(self, subvolume):
|
||||
"""Return the identified subvolume if existing, else the closest matching parent"""
|
||||
subvolumes_by_path = self.__get_subvolumes_by_path()
|
||||
while len(subvolume) > 1:
|
||||
if subvolume in subvolumes_by_path:
|
||||
return BtrfsSubvolume(self, subvolumes_by_path[subvolume]['id'])
|
||||
else:
|
||||
subvolume = re.sub(r'/[^/]+$', '', subvolume)
|
||||
|
||||
return BtrfsSubvolume(self, 5)
|
||||
|
||||
def get_mountpath_as_child(self, subvolume_name):
|
||||
"""Find a path to the target subvolume through a mounted ancestor"""
|
||||
nearest = self.get_nearest_subvolume(subvolume_name)
|
||||
if nearest.path == subvolume_name:
|
||||
nearest = nearest.get_parent_subvolume()
|
||||
if nearest is None or nearest.get_mounted_path() is None:
|
||||
raise BtrfsModuleException("Failed to find a path '%s' through a mounted parent subvolume" % subvolume_name)
|
||||
else:
|
||||
return nearest.get_mounted_path() + os.path.sep + nearest.get_child_relative_path(subvolume_name)
|
||||
|
||||
def get_subvolume_children(self, subvolume_id):
|
||||
return [BtrfsSubvolume(self, x['id']) for x in self.__subvolumes.values() if x['parent'] == subvolume_id]
|
||||
|
||||
def __get_subvolumes_by_path(self):
|
||||
result = {}
|
||||
for s in self.__subvolumes.values():
|
||||
path = s['path']
|
||||
result[path] = s
|
||||
return result
|
||||
|
||||
def is_mounted(self):
|
||||
return self.__mountpoints is not None and len(self.__mountpoints) > 0
|
||||
|
||||
def get_summary(self):
|
||||
subvolumes = []
|
||||
sources = self.__subvolumes.values() if self.__subvolumes is not None else []
|
||||
for subvolume in sources:
|
||||
id = subvolume['id']
|
||||
subvolumes.append({
|
||||
'id': id,
|
||||
'path': subvolume['path'],
|
||||
'parent': subvolume['parent'],
|
||||
'mountpoints': self.get_mountpoints_by_subvolume_id(id),
|
||||
})
|
||||
|
||||
return {
|
||||
'default_subvolume': self.__default_subvolid,
|
||||
'devices': self.__devices,
|
||||
'label': self.__label,
|
||||
'uuid': self.__uuid,
|
||||
'subvolumes': subvolumes,
|
||||
}
|
||||
|
||||
|
||||
class BtrfsFilesystemsProvider(object):
|
||||
|
||||
"""
|
||||
Provides methods to query available btrfs filesystems
|
||||
"""
|
||||
|
||||
def __init__(self, module):
|
||||
self.__module = module
|
||||
self.__provider = BtrfsInfoProvider(module)
|
||||
self.__filesystems = None
|
||||
|
||||
def get_matching_filesystem(self, criteria):
|
||||
if criteria['device'] is not None:
|
||||
criteria['device'] = os.path.realpath(criteria['device'])
|
||||
|
||||
self.__check_init()
|
||||
matching = [f for f in self.__filesystems.values() if self.__filesystem_matches_criteria(f, criteria)]
|
||||
if len(matching) == 1:
|
||||
return matching[0]
|
||||
else:
|
||||
raise BtrfsModuleException("Found %d filesystems matching criteria uuid=%s label=%s device=%s" % (
|
||||
len(matching),
|
||||
criteria['uuid'],
|
||||
criteria['label'],
|
||||
criteria['device']
|
||||
))
|
||||
|
||||
def __filesystem_matches_criteria(self, filesystem, criteria):
|
||||
return ((criteria['uuid'] is None or filesystem.uuid == criteria['uuid']) and
|
||||
(criteria['label'] is None or filesystem.label == criteria['label']) and
|
||||
(criteria['device'] is None or filesystem.contains_device(criteria['device'])))
|
||||
|
||||
def get_filesystem_for_device(self, device):
|
||||
real_device = os.path.realpath(device)
|
||||
self.__check_init()
|
||||
for fs in self.__filesystems.values():
|
||||
if fs.contains_device(real_device):
|
||||
return fs
|
||||
return None
|
||||
|
||||
def get_filesystems(self):
|
||||
self.__check_init()
|
||||
return list(self.__filesystems.values())
|
||||
|
||||
def __check_init(self):
|
||||
if self.__filesystems is None:
|
||||
self.__filesystems = dict()
|
||||
for f in self.__provider.get_filesystems():
|
||||
uuid = f['uuid']
|
||||
self.__filesystems[uuid] = BtrfsFilesystem(f, self.__provider, self.__module)
|
||||
@@ -88,9 +88,10 @@ class FormatError(CmdRunnerException):
|
||||
|
||||
|
||||
class _ArgFormat(object):
|
||||
def __init__(self, func, ignore_none=None):
|
||||
def __init__(self, func, ignore_none=None, ignore_missing_value=False):
|
||||
self.func = func
|
||||
self.ignore_none = ignore_none
|
||||
self.ignore_missing_value = ignore_missing_value
|
||||
|
||||
def __call__(self, value, ctx_ignore_none):
|
||||
ignore_none = self.ignore_none if self.ignore_none is not None else ctx_ignore_none
|
||||
@@ -102,8 +103,13 @@ class _ArgFormat(object):
|
||||
|
||||
class _Format(object):
|
||||
@staticmethod
|
||||
def as_bool(args):
|
||||
return _ArgFormat(lambda value: _ensure_list(args) if value else [])
|
||||
def as_bool(args_true, args_false=None, ignore_none=None):
|
||||
if args_false is not None:
|
||||
if ignore_none is None:
|
||||
ignore_none = False
|
||||
else:
|
||||
args_false = []
|
||||
return _ArgFormat(lambda value: _ensure_list(args_true) if value else _ensure_list(args_false), ignore_none=ignore_none)
|
||||
|
||||
@staticmethod
|
||||
def as_bool_not(args):
|
||||
@@ -127,7 +133,7 @@ class _Format(object):
|
||||
|
||||
@staticmethod
|
||||
def as_fixed(args):
|
||||
return _ArgFormat(lambda value: _ensure_list(args), ignore_none=False)
|
||||
return _ArgFormat(lambda value: _ensure_list(args), ignore_none=False, ignore_missing_value=True)
|
||||
|
||||
@staticmethod
|
||||
def as_func(func, ignore_none=None):
|
||||
@@ -135,14 +141,15 @@ class _Format(object):
|
||||
|
||||
@staticmethod
|
||||
def as_map(_map, default=None, ignore_none=None):
|
||||
if default is None:
|
||||
default = []
|
||||
return _ArgFormat(lambda value: _ensure_list(_map.get(value, default)), ignore_none=ignore_none)
|
||||
|
||||
@staticmethod
|
||||
def as_default_type(_type, arg="", ignore_none=None):
|
||||
fmt = _Format
|
||||
if _type == "dict":
|
||||
return fmt.as_func(lambda d: ["--{0}={1}".format(*a) for a in iteritems(d)],
|
||||
ignore_none=ignore_none)
|
||||
return fmt.as_func(lambda d: ["--{0}={1}".format(*a) for a in iteritems(d)], ignore_none=ignore_none)
|
||||
if _type == "list":
|
||||
return fmt.as_func(lambda value: ["--{0}".format(x) for x in value], ignore_none=ignore_none)
|
||||
if _type == "bool":
|
||||
@@ -261,10 +268,13 @@ class _CmdRunnerContext(object):
|
||||
for arg_name in self.args_order:
|
||||
value = None
|
||||
try:
|
||||
value = named_args[arg_name]
|
||||
if arg_name in named_args:
|
||||
value = named_args[arg_name]
|
||||
elif not runner.arg_formats[arg_name].ignore_missing_value:
|
||||
raise MissingArgumentValue(self.args_order, arg_name)
|
||||
self.cmd.extend(runner.arg_formats[arg_name](value, ctx_ignore_none=self.ignore_value_none))
|
||||
except KeyError:
|
||||
raise MissingArgumentValue(self.args_order, arg_name)
|
||||
except MissingArgumentValue:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise FormatError(arg_name, value, runner.arg_formats[arg_name], e)
|
||||
|
||||
@@ -299,11 +309,3 @@ class _CmdRunnerContext(object):
|
||||
|
||||
|
||||
cmd_runner_fmt = _Format()
|
||||
|
||||
#
|
||||
# The fmt form is deprecated and will be removed in community.general 7.0.0
|
||||
# Please use:
|
||||
# cmd_runner_fmt
|
||||
# Or, to retain the same effect, use:
|
||||
# from ansible_collections.community.general.plugins.module_utils.cmd_runner import cmd_runner_fmt as fmt
|
||||
fmt = cmd_runner_fmt
|
||||
|
||||
98
plugins/module_utils/deps.py
Normal file
98
plugins/module_utils/deps.py
Normal file
@@ -0,0 +1,98 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# (c) 2022, Alexei Znamensky <russoz@gmail.com>
|
||||
# Copyright (c) 2022, Ansible Project
|
||||
# Simplified BSD License (see LICENSES/BSD-2-Clause.txt or https://opensource.org/licenses/BSD-2-Clause)
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
import traceback
|
||||
from contextlib import contextmanager
|
||||
|
||||
from ansible.module_utils.common.text.converters import to_native
|
||||
from ansible.module_utils.basic import missing_required_lib
|
||||
|
||||
|
||||
_deps = dict()
|
||||
|
||||
|
||||
class _Dependency(object):
|
||||
_states = ["pending", "failure", "success"]
|
||||
|
||||
def __init__(self, name, reason=None, url=None, msg=None):
|
||||
self.name = name
|
||||
self.reason = reason
|
||||
self.url = url
|
||||
self.msg = msg
|
||||
|
||||
self.state = 0
|
||||
self.trace = None
|
||||
self.exc = None
|
||||
|
||||
def succeed(self):
|
||||
self.state = 2
|
||||
|
||||
def fail(self, exc, trace):
|
||||
self.state = 1
|
||||
self.exc = exc
|
||||
self.trace = trace
|
||||
|
||||
@property
|
||||
def message(self):
|
||||
if self.msg:
|
||||
return to_native(self.msg)
|
||||
else:
|
||||
return missing_required_lib(self.name, reason=self.reason, url=self.url)
|
||||
|
||||
@property
|
||||
def failed(self):
|
||||
return self.state == 1
|
||||
|
||||
def validate(self, module):
|
||||
if self.failed:
|
||||
module.fail_json(msg=self.message, exception=self.trace)
|
||||
|
||||
def __str__(self):
|
||||
return "<dependency: {0} [{1}]>".format(self.name, self._states[self.state])
|
||||
|
||||
|
||||
@contextmanager
|
||||
def declare(name, *args, **kwargs):
|
||||
dep = _Dependency(name, *args, **kwargs)
|
||||
try:
|
||||
yield dep
|
||||
except Exception as e:
|
||||
dep.fail(e, traceback.format_exc())
|
||||
else:
|
||||
dep.succeed()
|
||||
finally:
|
||||
_deps[name] = dep
|
||||
|
||||
|
||||
def _select_names(spec):
|
||||
dep_names = sorted(_deps)
|
||||
|
||||
if spec:
|
||||
if spec.startswith("-"):
|
||||
spec_split = spec[1:].split(":")
|
||||
for d in spec_split:
|
||||
dep_names.remove(d)
|
||||
else:
|
||||
spec_split = spec.split(":")
|
||||
dep_names = []
|
||||
for d in spec_split:
|
||||
_deps[d] # ensure it exists
|
||||
dep_names.append(d)
|
||||
|
||||
return dep_names
|
||||
|
||||
|
||||
def validate(module, spec=None):
|
||||
for dep in _select_names(spec):
|
||||
_deps[dep].validate(module)
|
||||
|
||||
|
||||
def failed(spec=None):
|
||||
return any(_deps[d].failed for d in _select_names(spec))
|
||||
@@ -19,15 +19,16 @@ import os
|
||||
import re
|
||||
import traceback
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
# (TODO: remove AnsibleModule from next line!)
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib # noqa: F401, pylint: disable=unused-import
|
||||
from ansible.module_utils.six.moves import configparser
|
||||
from os.path import expanduser
|
||||
from uuid import UUID
|
||||
|
||||
LIBCLOUD_IMP_ERR = None
|
||||
try:
|
||||
from libcloud.common.dimensiondata import API_ENDPOINTS, DimensionDataAPIException, DimensionDataStatus
|
||||
from libcloud.compute.base import Node, NodeLocation
|
||||
from libcloud.common.dimensiondata import API_ENDPOINTS, DimensionDataAPIException, DimensionDataStatus # noqa: F401, pylint: disable=unused-import
|
||||
from libcloud.compute.base import Node, NodeLocation # noqa: F401, pylint: disable=unused-import
|
||||
from libcloud.compute.providers import get_driver
|
||||
from libcloud.compute.types import Provider
|
||||
|
||||
|
||||
@@ -6,7 +6,14 @@
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
from ansible_collections.community.general.plugins.module_utils.cmd_runner import CmdRunner, cmd_runner_fmt as fmt
|
||||
from ansible_collections.community.general.plugins.module_utils.cmd_runner import CmdRunner, cmd_runner_fmt
|
||||
|
||||
|
||||
_state_map = {
|
||||
"present": "--set",
|
||||
"absent": "--unset",
|
||||
"get": "--get",
|
||||
}
|
||||
|
||||
|
||||
def gconftool2_runner(module, **kwargs):
|
||||
@@ -14,14 +21,12 @@ def gconftool2_runner(module, **kwargs):
|
||||
module,
|
||||
command='gconftool-2',
|
||||
arg_formats=dict(
|
||||
key=fmt.as_list(),
|
||||
value_type=fmt.as_opt_val("--type"),
|
||||
value=fmt.as_list(),
|
||||
direct=fmt.as_bool("--direct"),
|
||||
config_source=fmt.as_opt_val("--config-source"),
|
||||
get=fmt.as_bool("--get"),
|
||||
set_arg=fmt.as_bool("--set"),
|
||||
unset=fmt.as_bool("--unset"),
|
||||
state=cmd_runner_fmt.as_map(_state_map),
|
||||
key=cmd_runner_fmt.as_list(),
|
||||
value_type=cmd_runner_fmt.as_opt_val("--type"),
|
||||
value=cmd_runner_fmt.as_list(),
|
||||
direct=cmd_runner_fmt.as_bool("--direct"),
|
||||
config_source=cmd_runner_fmt.as_opt_val("--config-source"),
|
||||
),
|
||||
**kwargs
|
||||
)
|
||||
|
||||
@@ -10,6 +10,7 @@ __metaclass__ = type
|
||||
|
||||
from ansible.module_utils.basic import missing_required_lib
|
||||
from ansible.module_utils.common.text.converters import to_native
|
||||
from ansible.module_utils.six import integer_types, string_types
|
||||
|
||||
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
|
||||
|
||||
@@ -110,3 +111,49 @@ def gitlab_authentication(module):
|
||||
GitLab remove Session API now that private tokens are removed from user API endpoints since version 10.2." % to_native(e))
|
||||
|
||||
return gitlab_instance
|
||||
|
||||
|
||||
def filter_returned_variables(gitlab_variables):
|
||||
# pop properties we don't know
|
||||
existing_variables = [dict(x.attributes) for x in gitlab_variables]
|
||||
KNOWN = ['key', 'value', 'masked', 'protected', 'variable_type', 'environment_scope']
|
||||
for item in existing_variables:
|
||||
for key in list(item.keys()):
|
||||
if key not in KNOWN:
|
||||
item.pop(key)
|
||||
return existing_variables
|
||||
|
||||
|
||||
def vars_to_variables(vars, module):
|
||||
# transform old vars to new variables structure
|
||||
variables = list()
|
||||
for item, value in vars.items():
|
||||
if isinstance(value, (string_types, integer_types, float)):
|
||||
variables.append(
|
||||
{
|
||||
"name": item,
|
||||
"value": str(value),
|
||||
"masked": False,
|
||||
"protected": False,
|
||||
"variable_type": "env_var",
|
||||
}
|
||||
)
|
||||
|
||||
elif isinstance(value, dict):
|
||||
new_item = {
|
||||
"name": item,
|
||||
"value": value.get('value'),
|
||||
"masked": value.get('masked'),
|
||||
"protected": value.get('protected'),
|
||||
"variable_type": value.get('variable_type'),
|
||||
}
|
||||
|
||||
if value.get('environment_scope'):
|
||||
new_item['environment_scope'] = value.get('environment_scope')
|
||||
|
||||
variables.append(new_item)
|
||||
|
||||
else:
|
||||
module.fail_json(msg="value must be of type string, integer, float or dict")
|
||||
|
||||
return variables
|
||||
|
||||
@@ -42,12 +42,23 @@ URL_CLIENTTEMPLATE = "{url}/admin/realms/{realm}/client-templates/{id}"
|
||||
URL_CLIENTTEMPLATES = "{url}/admin/realms/{realm}/client-templates"
|
||||
URL_GROUPS = "{url}/admin/realms/{realm}/groups"
|
||||
URL_GROUP = "{url}/admin/realms/{realm}/groups/{groupid}"
|
||||
URL_GROUP_CHILDREN = "{url}/admin/realms/{realm}/groups/{groupid}/children"
|
||||
|
||||
URL_CLIENTSCOPES = "{url}/admin/realms/{realm}/client-scopes"
|
||||
URL_CLIENTSCOPE = "{url}/admin/realms/{realm}/client-scopes/{id}"
|
||||
URL_CLIENTSCOPE_PROTOCOLMAPPERS = "{url}/admin/realms/{realm}/client-scopes/{id}/protocol-mappers/models"
|
||||
URL_CLIENTSCOPE_PROTOCOLMAPPER = "{url}/admin/realms/{realm}/client-scopes/{id}/protocol-mappers/models/{mapper_id}"
|
||||
|
||||
URL_DEFAULT_CLIENTSCOPES = "{url}/admin/realms/{realm}/default-default-client-scopes"
|
||||
URL_DEFAULT_CLIENTSCOPE = "{url}/admin/realms/{realm}/default-default-client-scopes/{id}"
|
||||
URL_OPTIONAL_CLIENTSCOPES = "{url}/admin/realms/{realm}/default-optional-client-scopes"
|
||||
URL_OPTIONAL_CLIENTSCOPE = "{url}/admin/realms/{realm}/default-optional-client-scopes/{id}"
|
||||
|
||||
URL_CLIENT_DEFAULT_CLIENTSCOPES = "{url}/admin/realms/{realm}/clients/{cid}/default-client-scopes"
|
||||
URL_CLIENT_DEFAULT_CLIENTSCOPE = "{url}/admin/realms/{realm}/clients/{cid}/default-client-scopes/{id}"
|
||||
URL_CLIENT_OPTIONAL_CLIENTSCOPES = "{url}/admin/realms/{realm}/clients/{cid}/optional-client-scopes"
|
||||
URL_CLIENT_OPTIONAL_CLIENTSCOPE = "{url}/admin/realms/{realm}/clients/{cid}/optional-client-scopes/{id}"
|
||||
|
||||
URL_CLIENT_GROUP_ROLEMAPPINGS = "{url}/admin/realms/{realm}/groups/{id}/role-mappings/clients/{client}"
|
||||
URL_CLIENT_GROUP_ROLEMAPPINGS_AVAILABLE = "{url}/admin/realms/{realm}/groups/{id}/role-mappings/clients/{client}/available"
|
||||
URL_CLIENT_GROUP_ROLEMAPPINGS_COMPOSITE = "{url}/admin/realms/{realm}/groups/{id}/role-mappings/clients/{client}/composite"
|
||||
@@ -58,6 +69,8 @@ URL_CLIENT_USER_ROLEMAPPINGS = "{url}/admin/realms/{realm}/users/{id}/role-mappi
|
||||
URL_CLIENT_USER_ROLEMAPPINGS_AVAILABLE = "{url}/admin/realms/{realm}/users/{id}/role-mappings/clients/{client}/available"
|
||||
URL_CLIENT_USER_ROLEMAPPINGS_COMPOSITE = "{url}/admin/realms/{realm}/users/{id}/role-mappings/clients/{client}/composite"
|
||||
|
||||
URL_CLIENTSECRET = "{url}/admin/realms/{realm}/clients/{id}/client-secret"
|
||||
|
||||
URL_AUTHENTICATION_FLOWS = "{url}/admin/realms/{realm}/authentication/flows"
|
||||
URL_AUTHENTICATION_FLOW = "{url}/admin/realms/{realm}/authentication/flows/{id}"
|
||||
URL_AUTHENTICATION_FLOW_COPY = "{url}/admin/realms/{realm}/authentication/flows/{copyfrom}/copy"
|
||||
@@ -77,6 +90,9 @@ URL_IDENTITY_PROVIDER_MAPPER = "{url}/admin/realms/{realm}/identity-provider/ins
|
||||
URL_COMPONENTS = "{url}/admin/realms/{realm}/components"
|
||||
URL_COMPONENT = "{url}/admin/realms/{realm}/components/{id}"
|
||||
|
||||
URL_AUTHZ_AUTHORIZATION_SCOPE = "{url}/admin/realms/{realm}/clients/{client_id}/authz/resource-server/scope/{id}"
|
||||
URL_AUTHZ_AUTHORIZATION_SCOPES = "{url}/admin/realms/{realm}/clients/{client_id}/authz/resource-server/scope"
|
||||
|
||||
|
||||
def keycloak_argument_spec():
|
||||
"""
|
||||
@@ -606,7 +622,7 @@ class KeycloakAPI(object):
|
||||
"""
|
||||
available_rolemappings_url = URL_CLIENT_GROUP_ROLEMAPPINGS.format(url=self.baseurl, realm=realm, id=gid, client=cid)
|
||||
try:
|
||||
open_url(available_rolemappings_url, method="DELETE", http_agent=self.http_agent, headers=self.restheaders,
|
||||
open_url(available_rolemappings_url, method="DELETE", http_agent=self.http_agent, headers=self.restheaders, data=json.dumps(role_rep),
|
||||
validate_certs=self.validate_certs, timeout=self.connection_timeout)
|
||||
except Exception as e:
|
||||
self.module.fail_json(msg="Could not delete available rolemappings for client %s in group %s, realm %s: %s"
|
||||
@@ -1160,6 +1176,177 @@ class KeycloakAPI(object):
|
||||
self.module.fail_json(msg='Could not update protocolmappers for clientscope %s in realm %s: %s'
|
||||
% (mapper_rep, realm, str(e)))
|
||||
|
||||
def get_default_clientscopes(self, realm, client_id=None):
|
||||
"""Fetch the name and ID of all clientscopes on the Keycloak server.
|
||||
|
||||
To fetch the full data of the client scope, make a subsequent call to
|
||||
get_clientscope_by_clientscopeid, passing in the ID of the client scope you wish to return.
|
||||
|
||||
:param realm: Realm in which the clientscope resides.
|
||||
:param client_id: The client in which the clientscope resides.
|
||||
:return The default clientscopes of this realm or client
|
||||
"""
|
||||
url = URL_DEFAULT_CLIENTSCOPES if client_id is None else URL_CLIENT_DEFAULT_CLIENTSCOPES
|
||||
return self._get_clientscopes_of_type(realm, url, 'default', client_id)
|
||||
|
||||
def get_optional_clientscopes(self, realm, client_id=None):
|
||||
"""Fetch the name and ID of all clientscopes on the Keycloak server.
|
||||
|
||||
To fetch the full data of the client scope, make a subsequent call to
|
||||
get_clientscope_by_clientscopeid, passing in the ID of the client scope you wish to return.
|
||||
|
||||
:param realm: Realm in which the clientscope resides.
|
||||
:param client_id: The client in which the clientscope resides.
|
||||
:return The optinal clientscopes of this realm or client
|
||||
"""
|
||||
url = URL_OPTIONAL_CLIENTSCOPES if client_id is None else URL_CLIENT_OPTIONAL_CLIENTSCOPES
|
||||
return self._get_clientscopes_of_type(realm, url, 'optional', client_id)
|
||||
|
||||
def _get_clientscopes_of_type(self, realm, url_template, scope_type, client_id=None):
|
||||
"""Fetch the name and ID of all clientscopes on the Keycloak server.
|
||||
|
||||
To fetch the full data of the client scope, make a subsequent call to
|
||||
get_clientscope_by_clientscopeid, passing in the ID of the client scope you wish to return.
|
||||
|
||||
:param realm: Realm in which the clientscope resides.
|
||||
:param url_template the template for the right type
|
||||
:param scope_type this can be either optinal or default
|
||||
:param client_id: The client in which the clientscope resides.
|
||||
:return The clientscopes of the specified type of this realm
|
||||
"""
|
||||
if client_id is None:
|
||||
clientscopes_url = url_template.format(url=self.baseurl, realm=realm)
|
||||
try:
|
||||
return json.loads(to_native(open_url(clientscopes_url, method="GET", http_agent=self.http_agent, headers=self.restheaders,
|
||||
timeout=self.connection_timeout, validate_certs=self.validate_certs).read()))
|
||||
except Exception as e:
|
||||
self.module.fail_json(msg="Could not fetch list of %s clientscopes in realm %s: %s" % (scope_type, realm, str(e)))
|
||||
else:
|
||||
cid = self.get_client_id(client_id=client_id, realm=realm)
|
||||
clientscopes_url = url_template.format(url=self.baseurl, realm=realm, cid=cid)
|
||||
try:
|
||||
return json.loads(to_native(open_url(clientscopes_url, method="GET", http_agent=self.http_agent, headers=self.restheaders,
|
||||
timeout=self.connection_timeout, validate_certs=self.validate_certs).read()))
|
||||
except Exception as e:
|
||||
self.module.fail_json(msg="Could not fetch list of %s clientscopes in client %s: %s" % (scope_type, client_id, clientscopes_url))
|
||||
|
||||
def _decide_url_type_clientscope(self, client_id=None, scope_type="default"):
|
||||
"""Decides which url to use.
|
||||
:param scope_type this can be either optinal or default
|
||||
:param client_id: The client in which the clientscope resides.
|
||||
"""
|
||||
if client_id is None:
|
||||
if scope_type == "default":
|
||||
return URL_DEFAULT_CLIENTSCOPE
|
||||
if scope_type == "optional":
|
||||
return URL_OPTIONAL_CLIENTSCOPE
|
||||
else:
|
||||
if scope_type == "default":
|
||||
return URL_CLIENT_DEFAULT_CLIENTSCOPE
|
||||
if scope_type == "optional":
|
||||
return URL_CLIENT_OPTIONAL_CLIENTSCOPE
|
||||
|
||||
def add_default_clientscope(self, id, realm="master", client_id=None):
|
||||
"""Add a client scope as default either on realm or client level.
|
||||
|
||||
:param id: Client scope Id.
|
||||
:param realm: Realm in which the clientscope resides.
|
||||
:param client_id: The client in which the clientscope resides.
|
||||
"""
|
||||
self._action_type_clientscope(id, client_id, "default", realm, 'add')
|
||||
|
||||
def add_optional_clientscope(self, id, realm="master", client_id=None):
|
||||
"""Add a client scope as optional either on realm or client level.
|
||||
|
||||
:param id: Client scope Id.
|
||||
:param realm: Realm in which the clientscope resides.
|
||||
:param client_id: The client in which the clientscope resides.
|
||||
"""
|
||||
self._action_type_clientscope(id, client_id, "optional", realm, 'add')
|
||||
|
||||
def delete_default_clientscope(self, id, realm="master", client_id=None):
|
||||
"""Remove a client scope as default either on realm or client level.
|
||||
|
||||
:param id: Client scope Id.
|
||||
:param realm: Realm in which the clientscope resides.
|
||||
:param client_id: The client in which the clientscope resides.
|
||||
"""
|
||||
self._action_type_clientscope(id, client_id, "default", realm, 'delete')
|
||||
|
||||
def delete_optional_clientscope(self, id, realm="master", client_id=None):
|
||||
"""Remove a client scope as optional either on realm or client level.
|
||||
|
||||
:param id: Client scope Id.
|
||||
:param realm: Realm in which the clientscope resides.
|
||||
:param client_id: The client in which the clientscope resides.
|
||||
"""
|
||||
self._action_type_clientscope(id, client_id, "optional", realm, 'delete')
|
||||
|
||||
def _action_type_clientscope(self, id=None, client_id=None, scope_type="default", realm="master", action='add'):
|
||||
""" Delete or add a clientscope of type.
|
||||
:param name: The name of the clientscope. A lookup will be performed to retrieve the clientscope ID.
|
||||
:param client_id: The ID of the clientscope (preferred to name).
|
||||
:param scope_type 'default' or 'optional'
|
||||
:param realm: The realm in which this group resides, default "master".
|
||||
"""
|
||||
cid = None if client_id is None else self.get_client_id(client_id=client_id, realm=realm)
|
||||
# should have a good cid by here.
|
||||
clientscope_type_url = self._decide_url_type_clientscope(client_id, scope_type).format(realm=realm, id=id, cid=cid, url=self.baseurl)
|
||||
try:
|
||||
method = 'PUT' if action == "add" else 'DELETE'
|
||||
return open_url(clientscope_type_url, method=method, http_agent=self.http_agent, headers=self.restheaders, timeout=self.connection_timeout,
|
||||
validate_certs=self.validate_certs)
|
||||
|
||||
except Exception as e:
|
||||
place = 'realm' if client_id is None else 'client ' + client_id
|
||||
self.module.fail_json(msg="Unable to %s %s clientscope %s @ %s : %s" % (action, scope_type, id, place, str(e)))
|
||||
|
||||
def create_clientsecret(self, id, realm="master"):
|
||||
""" Generate a new client secret by id
|
||||
|
||||
:param id: id (not clientId) of client to be queried
|
||||
:param realm: client from this realm
|
||||
:return: dict of credential representation
|
||||
"""
|
||||
clientsecret_url = URL_CLIENTSECRET.format(url=self.baseurl, realm=realm, id=id)
|
||||
|
||||
try:
|
||||
return json.loads(to_native(open_url(clientsecret_url, method='POST', headers=self.restheaders, timeout=self.connection_timeout,
|
||||
validate_certs=self.validate_certs).read()))
|
||||
|
||||
except HTTPError as e:
|
||||
if e.code == 404:
|
||||
return None
|
||||
else:
|
||||
self.module.fail_json(msg='Could not obtain clientsecret of client %s for realm %s: %s'
|
||||
% (id, realm, str(e)))
|
||||
except Exception as e:
|
||||
self.module.fail_json(msg='Could not obtain clientsecret of client %s for realm %s: %s'
|
||||
% (id, realm, str(e)))
|
||||
|
||||
def get_clientsecret(self, id, realm="master"):
|
||||
""" Obtain client secret by id
|
||||
|
||||
:param id: id (not clientId) of client to be queried
|
||||
:param realm: client from this realm
|
||||
:return: dict of credential representation
|
||||
"""
|
||||
clientsecret_url = URL_CLIENTSECRET.format(url=self.baseurl, realm=realm, id=id)
|
||||
|
||||
try:
|
||||
return json.loads(to_native(open_url(clientsecret_url, method='GET', headers=self.restheaders, timeout=self.connection_timeout,
|
||||
validate_certs=self.validate_certs).read()))
|
||||
|
||||
except HTTPError as e:
|
||||
if e.code == 404:
|
||||
return None
|
||||
else:
|
||||
self.module.fail_json(msg='Could not obtain clientsecret of client %s for realm %s: %s'
|
||||
% (id, realm, str(e)))
|
||||
except Exception as e:
|
||||
self.module.fail_json(msg='Could not obtain clientsecret of client %s for realm %s: %s'
|
||||
% (id, realm, str(e)))
|
||||
|
||||
def get_groups(self, realm="master"):
|
||||
""" Fetch the name and ID of all groups on the Keycloak server.
|
||||
|
||||
@@ -1201,7 +1388,7 @@ class KeycloakAPI(object):
|
||||
self.module.fail_json(msg="Could not fetch group %s in realm %s: %s"
|
||||
% (gid, realm, str(e)))
|
||||
|
||||
def get_group_by_name(self, name, realm="master"):
|
||||
def get_group_by_name(self, name, realm="master", parents=None):
|
||||
""" Fetch a keycloak group within a realm based on its name.
|
||||
|
||||
The Keycloak API does not allow filtering of the Groups resource by name.
|
||||
@@ -1211,10 +1398,19 @@ class KeycloakAPI(object):
|
||||
If the group does not exist, None is returned.
|
||||
:param name: Name of the group to fetch.
|
||||
:param realm: Realm in which the group resides; default 'master'
|
||||
:param parents: Optional list of parents when group to look for is a subgroup
|
||||
"""
|
||||
groups_url = URL_GROUPS.format(url=self.baseurl, realm=realm)
|
||||
try:
|
||||
all_groups = self.get_groups(realm=realm)
|
||||
if parents:
|
||||
parent = self.get_subgroup_direct_parent(parents, realm)
|
||||
|
||||
if not parent:
|
||||
return None
|
||||
|
||||
all_groups = parent['subGroups']
|
||||
else:
|
||||
all_groups = self.get_groups(realm=realm)
|
||||
|
||||
for group in all_groups:
|
||||
if group['name'] == name:
|
||||
@@ -1226,6 +1422,102 @@ class KeycloakAPI(object):
|
||||
self.module.fail_json(msg="Could not fetch group %s in realm %s: %s"
|
||||
% (name, realm, str(e)))
|
||||
|
||||
def _get_normed_group_parent(self, parent):
|
||||
""" Converts parent dict information into a more easy to use form.
|
||||
|
||||
:param parent: parent describing dict
|
||||
"""
|
||||
if parent['id']:
|
||||
return (parent['id'], True)
|
||||
|
||||
return (parent['name'], False)
|
||||
|
||||
def get_subgroup_by_chain(self, name_chain, realm="master"):
|
||||
""" Access a subgroup API object by walking down a given name/id chain.
|
||||
|
||||
Groups can be given either as by name or by ID, the first element
|
||||
must either be a toplvl group or given as ID, all parents must exist.
|
||||
|
||||
If the group cannot be found, None is returned.
|
||||
:param name_chain: Topdown ordered list of subgroup parent (ids or names) + its own name at the end
|
||||
:param realm: Realm in which the group resides; default 'master'
|
||||
"""
|
||||
cp = name_chain[0]
|
||||
|
||||
# for 1st parent in chain we must query the server
|
||||
cp, is_id = self._get_normed_group_parent(cp)
|
||||
|
||||
if is_id:
|
||||
tmp = self.get_group_by_groupid(cp, realm=realm)
|
||||
else:
|
||||
# given as name, assume toplvl group
|
||||
tmp = self.get_group_by_name(cp, realm=realm)
|
||||
|
||||
if not tmp:
|
||||
return None
|
||||
|
||||
for p in name_chain[1:]:
|
||||
for sg in tmp['subGroups']:
|
||||
pv, is_id = self._get_normed_group_parent(p)
|
||||
|
||||
if is_id:
|
||||
cmpkey = "id"
|
||||
else:
|
||||
cmpkey = "name"
|
||||
|
||||
if pv == sg[cmpkey]:
|
||||
tmp = sg
|
||||
break
|
||||
|
||||
if not tmp:
|
||||
return None
|
||||
|
||||
return tmp
|
||||
|
||||
def get_subgroup_direct_parent(self, parents, realm="master", children_to_resolve=None):
|
||||
""" Get keycloak direct parent group API object for a given chain of parents.
|
||||
|
||||
To succesfully work the API for subgroups we actually dont need
|
||||
to "walk the whole tree" for nested groups but only need to know
|
||||
the ID for the direct predecessor of current subgroup. This
|
||||
method will guarantee us this information getting there with
|
||||
as minimal work as possible.
|
||||
|
||||
Note that given parent list can and might be incomplete at the
|
||||
upper levels as long as it starts with an ID instead of a name
|
||||
|
||||
If the group does not exist, None is returned.
|
||||
:param parents: Topdown ordered list of subgroup parents
|
||||
:param realm: Realm in which the group resides; default 'master'
|
||||
"""
|
||||
if children_to_resolve is None:
|
||||
# start recursion by reversing parents (in optimal cases
|
||||
# we dont need to walk the whole tree upwarts)
|
||||
parents = list(reversed(parents))
|
||||
children_to_resolve = []
|
||||
|
||||
if not parents:
|
||||
# walk complete parents list to the top, all names, no id's,
|
||||
# try to resolve it assuming list is complete and 1st
|
||||
# element is a toplvl group
|
||||
return self.get_subgroup_by_chain(list(reversed(children_to_resolve)), realm=realm)
|
||||
|
||||
cp = parents[0]
|
||||
unused, is_id = self._get_normed_group_parent(cp)
|
||||
|
||||
if is_id:
|
||||
# current parent is given as ID, we can stop walking
|
||||
# upwards searching for an entry point
|
||||
return self.get_subgroup_by_chain([cp] + list(reversed(children_to_resolve)), realm=realm)
|
||||
else:
|
||||
# current parent is given as name, it must be resolved
|
||||
# later, try next parent (recurse)
|
||||
children_to_resolve.append(cp)
|
||||
return self.get_subgroup_direct_parent(
|
||||
parents[1:],
|
||||
realm=realm, children_to_resolve=children_to_resolve
|
||||
)
|
||||
|
||||
def create_group(self, grouprep, realm="master"):
|
||||
""" Create a Keycloak group.
|
||||
|
||||
@@ -1240,6 +1532,34 @@ class KeycloakAPI(object):
|
||||
self.module.fail_json(msg="Could not create group %s in realm %s: %s"
|
||||
% (grouprep['name'], realm, str(e)))
|
||||
|
||||
def create_subgroup(self, parents, grouprep, realm="master"):
|
||||
""" Create a Keycloak subgroup.
|
||||
|
||||
:param parents: list of one or more parent groups
|
||||
:param grouprep: a GroupRepresentation of the group to be created. Must contain at minimum the field name.
|
||||
:return: HTTPResponse object on success
|
||||
"""
|
||||
parent_id = "---UNDETERMINED---"
|
||||
try:
|
||||
parent_id = self.get_subgroup_direct_parent(parents, realm)
|
||||
|
||||
if not parent_id:
|
||||
raise Exception(
|
||||
"Could not determine subgroup parent ID for given"
|
||||
" parent chain {0}. Assure that all parents exist"
|
||||
" already and the list is complete and properly"
|
||||
" ordered, starts with an ID or starts at the"
|
||||
" top level".format(parents)
|
||||
)
|
||||
|
||||
parent_id = parent_id["id"]
|
||||
url = URL_GROUP_CHILDREN.format(url=self.baseurl, realm=realm, groupid=parent_id)
|
||||
return open_url(url, method='POST', http_agent=self.http_agent, headers=self.restheaders, timeout=self.connection_timeout,
|
||||
data=json.dumps(grouprep), validate_certs=self.validate_certs)
|
||||
except Exception as e:
|
||||
self.module.fail_json(msg="Could not create subgroup %s for parent group %s in realm %s: %s"
|
||||
% (grouprep['name'], parent_id, realm, str(e)))
|
||||
|
||||
def update_group(self, grouprep, realm="master"):
|
||||
""" Update an existing group.
|
||||
|
||||
@@ -1613,6 +1933,9 @@ class KeycloakAPI(object):
|
||||
data=json.dumps(updatedExec),
|
||||
timeout=self.connection_timeout,
|
||||
validate_certs=self.validate_certs)
|
||||
except HTTPError as e:
|
||||
self.module.fail_json(msg="Unable to update execution '%s': %s: %s %s" %
|
||||
(flowAlias, repr(e), ";".join([e.url, e.msg, str(e.code), str(e.hdrs)]), str(updatedExec)))
|
||||
except Exception as e:
|
||||
self.module.fail_json(msg="Unable to update executions %s: %s" % (updatedExec, str(e)))
|
||||
|
||||
@@ -1637,7 +1960,7 @@ class KeycloakAPI(object):
|
||||
except Exception as e:
|
||||
self.module.fail_json(msg="Unable to add authenticationConfig %s: %s" % (executionId, str(e)))
|
||||
|
||||
def create_subflow(self, subflowName, flowAlias, realm='master'):
|
||||
def create_subflow(self, subflowName, flowAlias, realm='master', flowType='basic-flow'):
|
||||
""" Create new sublow on the flow
|
||||
|
||||
:param subflowName: name of the subflow to create
|
||||
@@ -1648,7 +1971,7 @@ class KeycloakAPI(object):
|
||||
newSubFlow = {}
|
||||
newSubFlow["alias"] = subflowName
|
||||
newSubFlow["provider"] = "registration-page-form"
|
||||
newSubFlow["type"] = "basic-flow"
|
||||
newSubFlow["type"] = flowType
|
||||
open_url(
|
||||
URL_AUTHENTICATION_FLOW_EXECUTIONS_FLOW.format(
|
||||
url=self.baseurl,
|
||||
@@ -1683,8 +2006,11 @@ class KeycloakAPI(object):
|
||||
data=json.dumps(newExec),
|
||||
timeout=self.connection_timeout,
|
||||
validate_certs=self.validate_certs)
|
||||
except HTTPError as e:
|
||||
self.module.fail_json(msg="Unable to create new execution '%s' %s: %s: %s %s" %
|
||||
(flowAlias, execution["providerId"], repr(e), ";".join([e.url, e.msg, str(e.code), str(e.hdrs)]), str(newExec)))
|
||||
except Exception as e:
|
||||
self.module.fail_json(msg="Unable to create new execution %s: %s" % (execution["provider"], str(e)))
|
||||
self.module.fail_json(msg="Unable to create new execution '%s' %s: %s" % (flowAlias, execution["providerId"], repr(e)))
|
||||
|
||||
def change_execution_priority(self, executionId, diff, realm='master'):
|
||||
""" Raise or lower execution priority of diff time
|
||||
@@ -2008,3 +2334,44 @@ class KeycloakAPI(object):
|
||||
except Exception as e:
|
||||
self.module.fail_json(msg='Unable to delete component %s in realm %s: %s'
|
||||
% (cid, realm, str(e)))
|
||||
|
||||
def get_authz_authorization_scope_by_name(self, name, client_id, realm):
|
||||
url = URL_AUTHZ_AUTHORIZATION_SCOPES.format(url=self.baseurl, client_id=client_id, realm=realm)
|
||||
search_url = "%s/search?name=%s" % (url, quote(name))
|
||||
|
||||
try:
|
||||
return json.loads(to_native(open_url(search_url, method='GET', http_agent=self.http_agent, headers=self.restheaders,
|
||||
timeout=self.connection_timeout,
|
||||
validate_certs=self.validate_certs).read()))
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def create_authz_authorization_scope(self, payload, client_id, realm):
|
||||
"""Create an authorization scope for a Keycloak client"""
|
||||
url = URL_AUTHZ_AUTHORIZATION_SCOPES.format(url=self.baseurl, client_id=client_id, realm=realm)
|
||||
|
||||
try:
|
||||
return open_url(url, method='POST', http_agent=self.http_agent, headers=self.restheaders, timeout=self.connection_timeout,
|
||||
data=json.dumps(payload), validate_certs=self.validate_certs)
|
||||
except Exception as e:
|
||||
self.module.fail_json(msg='Could not create authorization scope %s for client %s in realm %s: %s' % (payload['name'], client_id, realm, str(e)))
|
||||
|
||||
def update_authz_authorization_scope(self, payload, id, client_id, realm):
|
||||
"""Update an authorization scope for a Keycloak client"""
|
||||
url = URL_AUTHZ_AUTHORIZATION_SCOPE.format(url=self.baseurl, id=id, client_id=client_id, realm=realm)
|
||||
|
||||
try:
|
||||
return open_url(url, method='PUT', http_agent=self.http_agent, headers=self.restheaders, timeout=self.connection_timeout,
|
||||
data=json.dumps(payload), validate_certs=self.validate_certs)
|
||||
except Exception as e:
|
||||
self.module.fail_json(msg='Could not create update scope %s for client %s in realm %s: %s' % (payload['name'], client_id, realm, str(e)))
|
||||
|
||||
def remove_authz_authorization_scope(self, id, client_id, realm):
|
||||
"""Remove an authorization scope from a Keycloak client"""
|
||||
url = URL_AUTHZ_AUTHORIZATION_SCOPE.format(url=self.baseurl, id=id, client_id=client_id, realm=realm)
|
||||
|
||||
try:
|
||||
return open_url(url, method='DELETE', http_agent=self.http_agent, headers=self.restheaders, timeout=self.connection_timeout,
|
||||
validate_certs=self.validate_certs)
|
||||
except Exception as e:
|
||||
self.module.fail_json(msg='Could not delete scope %s for client %s in realm %s: %s' % (id, client_id, realm, str(e)))
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2022, John Cant <a.johncant@gmail.com>
|
||||
# GNU General Public License v3.0+ (see COPYING 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 ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
from ansible_collections.community.general.plugins.module_utils.identity.keycloak.keycloak import \
|
||||
keycloak_argument_spec
|
||||
|
||||
|
||||
def keycloak_clientsecret_module():
|
||||
"""
|
||||
Returns an AnsibleModule definition for modules that interact with a client
|
||||
secret.
|
||||
|
||||
:return: argument_spec dict
|
||||
"""
|
||||
argument_spec = keycloak_argument_spec()
|
||||
|
||||
meta_args = dict(
|
||||
realm=dict(default='master'),
|
||||
id=dict(type='str'),
|
||||
client_id=dict(type='str', aliases=['clientId']),
|
||||
)
|
||||
|
||||
argument_spec.update(meta_args)
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=argument_spec,
|
||||
supports_check_mode=True,
|
||||
required_one_of=([['id', 'client_id'],
|
||||
['token', 'auth_realm', 'auth_username', 'auth_password']]),
|
||||
required_together=([['auth_realm', 'auth_username', 'auth_password']]),
|
||||
mutually_exclusive=[
|
||||
['token', 'auth_realm'],
|
||||
['token', 'auth_username'],
|
||||
['token', 'auth_password']
|
||||
])
|
||||
|
||||
return module
|
||||
|
||||
|
||||
def keycloak_clientsecret_module_resolve_params(module, kc):
|
||||
"""
|
||||
Given an AnsibleModule definition for keycloak_clientsecret_*, and a
|
||||
KeycloakAPI client, resolve the params needed to interact with the Keycloak
|
||||
client secret, looking up the client by clientId if necessary via an API
|
||||
call.
|
||||
|
||||
:return: tuple of id, realm
|
||||
"""
|
||||
|
||||
realm = module.params.get('realm')
|
||||
id = module.params.get('id')
|
||||
client_id = module.params.get('client_id')
|
||||
|
||||
# only lookup the client_id if id isn't provided.
|
||||
# in the case that both are provided, prefer the ID, since it's one
|
||||
# less lookup.
|
||||
if id is None:
|
||||
# Due to the required_one_of spec, client_id is guaranteed to not be None
|
||||
client = kc.get_client_by_clientid(client_id, realm=realm)
|
||||
|
||||
if client is None:
|
||||
module.fail_json(
|
||||
msg='Client does not exist {client_id}'.format(client_id=client_id)
|
||||
)
|
||||
|
||||
id = client['id']
|
||||
|
||||
return id, realm
|
||||
@@ -8,6 +8,7 @@ from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
from ansible_collections.community.general.plugins.module_utils.redfish_utils import RedfishUtils
|
||||
import time
|
||||
|
||||
|
||||
class iLORedfishUtils(RedfishUtils):
|
||||
@@ -85,17 +86,16 @@ class iLORedfishUtils(RedfishUtils):
|
||||
|
||||
datetime_uri = self.manager_uri + "DateTime"
|
||||
|
||||
response = self.get_request(self.root_uri + datetime_uri)
|
||||
if not response['ret']:
|
||||
return response
|
||||
listofips = mgr_attributes['mgr_attr_value'].split(" ")
|
||||
if len(listofips) > 2:
|
||||
return {'ret': False, 'changed': False, 'msg': "More than 2 NTP Servers mentioned"}
|
||||
|
||||
data = response['data']
|
||||
ntp_list = []
|
||||
for ips in listofips:
|
||||
ntp_list.append(ips)
|
||||
|
||||
ntp_list = data[setkey]
|
||||
if len(ntp_list) == 2:
|
||||
ntp_list.pop(0)
|
||||
|
||||
ntp_list.append(mgr_attributes['mgr_attr_value'])
|
||||
while len(ntp_list) < 2:
|
||||
ntp_list.append("0.0.0.0")
|
||||
|
||||
payload = {setkey: ntp_list}
|
||||
|
||||
@@ -137,18 +137,16 @@ class iLORedfishUtils(RedfishUtils):
|
||||
nic_info = self.get_manager_ethernet_uri()
|
||||
uri = nic_info["nic_addr"]
|
||||
|
||||
response = self.get_request(self.root_uri + uri)
|
||||
if not response['ret']:
|
||||
return response
|
||||
listofips = attr['mgr_attr_value'].split(" ")
|
||||
if len(listofips) > 3:
|
||||
return {'ret': False, 'changed': False, 'msg': "More than 3 DNS Servers mentioned"}
|
||||
|
||||
data = response['data']
|
||||
dns_list = []
|
||||
for ips in listofips:
|
||||
dns_list.append(ips)
|
||||
|
||||
dns_list = data["Oem"]["Hpe"]["IPv4"][key]
|
||||
|
||||
if len(dns_list) == 3:
|
||||
dns_list.pop(0)
|
||||
|
||||
dns_list.append(attr['mgr_attr_value'])
|
||||
while len(dns_list) < 3:
|
||||
dns_list.append("0.0.0.0")
|
||||
|
||||
payload = {
|
||||
"Oem": {
|
||||
@@ -231,3 +229,79 @@ class iLORedfishUtils(RedfishUtils):
|
||||
if not response['ret']:
|
||||
return response
|
||||
return {'ret': True, 'changed': True, 'msg': "Modified %s" % mgrattr['mgr_attr_name']}
|
||||
|
||||
def get_server_poststate(self):
|
||||
# Get server details
|
||||
response = self.get_request(self.root_uri + self.systems_uri)
|
||||
if not response["ret"]:
|
||||
return response
|
||||
server_data = response["data"]
|
||||
|
||||
if "Hpe" in server_data["Oem"]:
|
||||
return {
|
||||
"ret": True,
|
||||
"server_poststate": server_data["Oem"]["Hpe"]["PostState"]
|
||||
}
|
||||
else:
|
||||
return {
|
||||
"ret": True,
|
||||
"server_poststate": server_data["Oem"]["Hp"]["PostState"]
|
||||
}
|
||||
|
||||
def wait_for_ilo_reboot_completion(self, polling_interval=60, max_polling_time=1800):
|
||||
# This method checks if OOB controller reboot is completed
|
||||
time.sleep(10)
|
||||
|
||||
# Check server poststate
|
||||
state = self.get_server_poststate()
|
||||
if not state["ret"]:
|
||||
return state
|
||||
|
||||
count = int(max_polling_time / polling_interval)
|
||||
times = 0
|
||||
|
||||
# When server is powered OFF
|
||||
pcount = 0
|
||||
while state["server_poststate"] in ["PowerOff", "Off"] and pcount < 5:
|
||||
time.sleep(10)
|
||||
state = self.get_server_poststate()
|
||||
if not state["ret"]:
|
||||
return state
|
||||
|
||||
if state["server_poststate"] not in ["PowerOff", "Off"]:
|
||||
break
|
||||
pcount = pcount + 1
|
||||
if state["server_poststate"] in ["PowerOff", "Off"]:
|
||||
return {
|
||||
"ret": False,
|
||||
"changed": False,
|
||||
"msg": "Server is powered OFF"
|
||||
}
|
||||
|
||||
# When server is not rebooting
|
||||
if state["server_poststate"] in ["InPostDiscoveryComplete", "FinishedPost"]:
|
||||
return {
|
||||
"ret": True,
|
||||
"changed": False,
|
||||
"msg": "Server is not rebooting"
|
||||
}
|
||||
|
||||
while state["server_poststate"] not in ["InPostDiscoveryComplete", "FinishedPost"] and count > times:
|
||||
state = self.get_server_poststate()
|
||||
if not state["ret"]:
|
||||
return state
|
||||
|
||||
if state["server_poststate"] in ["InPostDiscoveryComplete", "FinishedPost"]:
|
||||
return {
|
||||
"ret": True,
|
||||
"changed": True,
|
||||
"msg": "Server reboot is completed"
|
||||
}
|
||||
time.sleep(polling_interval)
|
||||
times = times + 1
|
||||
|
||||
return {
|
||||
"ret": False,
|
||||
"changed": False,
|
||||
"msg": "Server Reboot has failed, server state: {state} ".format(state=state)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ from ansible_collections.community.general.plugins.module_utils.version import L
|
||||
|
||||
REQUESTS_IMP_ERR = None
|
||||
try:
|
||||
import requests.exceptions
|
||||
import requests.exceptions # noqa: F401, pylint: disable=unused-import
|
||||
HAS_REQUESTS = True
|
||||
except ImportError:
|
||||
REQUESTS_IMP_ERR = traceback.format_exc()
|
||||
@@ -25,7 +25,7 @@ INFLUXDB_IMP_ERR = None
|
||||
try:
|
||||
from influxdb import InfluxDBClient
|
||||
from influxdb import __version__ as influxdb_version
|
||||
from influxdb import exceptions
|
||||
from influxdb import exceptions # noqa: F401, pylint: disable=unused-import
|
||||
HAS_INFLUXDB = True
|
||||
except ImportError:
|
||||
INFLUXDB_IMP_ERR = traceback.format_exc()
|
||||
|
||||
35
plugins/module_utils/jenkins.py
Normal file
35
plugins/module_utils/jenkins.py
Normal file
@@ -0,0 +1,35 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2022, 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
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
import os
|
||||
import time
|
||||
|
||||
|
||||
def download_updates_file(updates_expiration):
|
||||
updates_filename = 'jenkins-plugin-cache.json'
|
||||
updates_dir = os.path.expanduser('~/.ansible/tmp')
|
||||
updates_file = os.path.join(updates_dir, updates_filename)
|
||||
download_updates = True
|
||||
|
||||
# Make sure the destination directory exists
|
||||
if not os.path.isdir(updates_dir):
|
||||
os.makedirs(updates_dir, 0o700)
|
||||
|
||||
# Check if we need to download new updates file
|
||||
if os.path.isfile(updates_file):
|
||||
# Get timestamp when the file was changed last time
|
||||
ts_file = os.stat(updates_file).st_mtime
|
||||
ts_now = time.time()
|
||||
|
||||
if ts_now - ts_file < updates_expiration:
|
||||
download_updates = False
|
||||
|
||||
return updates_file, download_updates
|
||||
@@ -10,6 +10,7 @@
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
import re
|
||||
import traceback
|
||||
from ansible.module_utils.common.text.converters import to_native
|
||||
|
||||
@@ -33,12 +34,14 @@ def gen_specs(**specs):
|
||||
specs.update({
|
||||
'bind_dn': dict(),
|
||||
'bind_pw': dict(default='', no_log=True),
|
||||
'ca_path': dict(type='path'),
|
||||
'dn': dict(required=True),
|
||||
'referrals_chasing': dict(type='str', default='anonymous', choices=['disabled', 'anonymous']),
|
||||
'server_uri': dict(default='ldapi:///'),
|
||||
'start_tls': dict(default=False, type='bool'),
|
||||
'validate_certs': dict(default=True, type='bool'),
|
||||
'sasl_class': dict(choices=['external', 'gssapi'], default='external', type='str'),
|
||||
'xorder_discovery': dict(choices=['enable', 'auto', 'disable'], default='auto', type='str'),
|
||||
})
|
||||
|
||||
return specs
|
||||
@@ -50,17 +53,22 @@ class LdapGeneric(object):
|
||||
self.module = module
|
||||
self.bind_dn = self.module.params['bind_dn']
|
||||
self.bind_pw = self.module.params['bind_pw']
|
||||
self.ca_path = self.module.params['ca_path']
|
||||
self.referrals_chasing = self.module.params['referrals_chasing']
|
||||
self.server_uri = self.module.params['server_uri']
|
||||
self.start_tls = self.module.params['start_tls']
|
||||
self.verify_cert = self.module.params['validate_certs']
|
||||
self.sasl_class = self.module.params['sasl_class']
|
||||
self.xorder_discovery = self.module.params['xorder_discovery']
|
||||
|
||||
# Establish connection
|
||||
self.connection = self._connect_to_ldap()
|
||||
|
||||
# Try to find the X_ORDERed version of the DN
|
||||
self.dn = self._find_dn()
|
||||
if self.xorder_discovery == "enable" or (self.xorder_discovery == "auto" and not self._xorder_dn()):
|
||||
# Try to find the X_ORDERed version of the DN
|
||||
self.dn = self._find_dn()
|
||||
else:
|
||||
self.dn = self.module.params['dn']
|
||||
|
||||
def fail(self, msg, exn):
|
||||
self.module.fail_json(
|
||||
@@ -91,6 +99,9 @@ class LdapGeneric(object):
|
||||
if not self.verify_cert:
|
||||
ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
|
||||
|
||||
if self.ca_path:
|
||||
ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, self.ca_path)
|
||||
|
||||
connection = ldap.initialize(self.server_uri)
|
||||
|
||||
if self.referrals_chasing == 'disabled':
|
||||
@@ -113,3 +124,8 @@ class LdapGeneric(object):
|
||||
self.fail("Cannot bind to the server.", e)
|
||||
|
||||
return connection
|
||||
|
||||
def _xorder_dn(self):
|
||||
# match X_ORDERed DNs
|
||||
regex = r"\w+=\{\d+\}.+"
|
||||
return re.match(regex, self.module.params['dn']) is not None
|
||||
|
||||
@@ -8,8 +8,10 @@ from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
import os
|
||||
import socket
|
||||
import ssl
|
||||
import json
|
||||
|
||||
from ansible.module_utils.urls import generic_urlparse
|
||||
from ansible.module_utils.six.moves.urllib.parse import urlparse
|
||||
@@ -20,8 +22,6 @@ from ansible.module_utils.common.text.converters import to_text
|
||||
HTTPConnection = http_client.HTTPConnection
|
||||
HTTPSConnection = http_client.HTTPSConnection
|
||||
|
||||
import json
|
||||
|
||||
|
||||
class UnixHTTPConnection(HTTPConnection):
|
||||
def __init__(self, path):
|
||||
@@ -60,7 +60,7 @@ class LXDClient(object):
|
||||
self.cert_file = cert_file
|
||||
self.key_file = key_file
|
||||
parts = generic_urlparse(urlparse(self.url))
|
||||
ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
||||
ctx = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
|
||||
ctx.load_cert_chain(cert_file, keyfile=key_file)
|
||||
self.connection = HTTPSConnection(parts.get('netloc'), context=ctx)
|
||||
elif url.startswith('unix:'):
|
||||
@@ -124,3 +124,11 @@ class LXDClient(object):
|
||||
if err is None:
|
||||
err = resp_json.get('error', None)
|
||||
return err
|
||||
|
||||
|
||||
def default_key_file():
|
||||
return os.path.expanduser('~/.config/lxc/client.key')
|
||||
|
||||
|
||||
def default_cert_file():
|
||||
return os.path.expanduser('~/.config/lxc/client.crt')
|
||||
|
||||
@@ -26,6 +26,7 @@ class Response(object):
|
||||
def __init__(self):
|
||||
self.content = None
|
||||
self.status_code = None
|
||||
self.stderr = None
|
||||
|
||||
def json(self):
|
||||
return json.loads(self.content)
|
||||
@@ -75,6 +76,10 @@ def memset_api_call(api_key, api_method, payload=None):
|
||||
msg = "Memset API returned a {0} response ({1}, {2})." . format(response.status_code, response.json()['error_type'], response.json()['error'])
|
||||
else:
|
||||
msg = "Memset API returned an error ({0}, {1})." . format(response.json()['error_type'], response.json()['error'])
|
||||
except urllib_error.URLError as e:
|
||||
has_failed = True
|
||||
msg = "An URLError occured ({0})." . format(type(e))
|
||||
response.stderr = "{0}" . format(e)
|
||||
|
||||
if msg is None:
|
||||
msg = response.json()
|
||||
|
||||
@@ -37,8 +37,17 @@ def cause_changes(on_success=None, on_failure=None):
|
||||
|
||||
|
||||
def module_fails_on_exception(func):
|
||||
conflict_list = ('msg', 'exception', 'output', 'vars', 'changed')
|
||||
|
||||
@wraps(func)
|
||||
def wrapper(self, *args, **kwargs):
|
||||
def fix_var_conflicts(output):
|
||||
result = dict([
|
||||
(k if k not in conflict_list else "_" + k, v)
|
||||
for k, v in output.items()
|
||||
])
|
||||
return result
|
||||
|
||||
try:
|
||||
func(self, *args, **kwargs)
|
||||
except SystemExit:
|
||||
@@ -46,12 +55,16 @@ def module_fails_on_exception(func):
|
||||
except ModuleHelperException as e:
|
||||
if e.update_output:
|
||||
self.update_output(e.update_output)
|
||||
# patchy solution to resolve conflict with output variables
|
||||
output = fix_var_conflicts(self.output)
|
||||
self.module.fail_json(msg=e.msg, exception=traceback.format_exc(),
|
||||
output=self.output, vars=self.vars.output(), **self.output)
|
||||
output=self.output, vars=self.vars.output(), **output)
|
||||
except Exception as e:
|
||||
# patchy solution to resolve conflict with output variables
|
||||
output = fix_var_conflicts(self.output)
|
||||
msg = "Module failed with exception: {0}".format(str(e).strip())
|
||||
self.module.fail_json(msg=msg, exception=traceback.format_exc(),
|
||||
output=self.output, vars=self.vars.output(), **self.output)
|
||||
output=self.output, vars=self.vars.output(), **output)
|
||||
return wrapper
|
||||
|
||||
|
||||
|
||||
@@ -38,6 +38,12 @@ class DependencyCtxMgr(object):
|
||||
|
||||
|
||||
class DependencyMixin(ModuleHelperBase):
|
||||
"""
|
||||
THIS CLASS IS BEING DEPRECATED.
|
||||
See the deprecation notice in ``DependencyMixin.fail_on_missing_deps()`` below.
|
||||
|
||||
Mixin for mapping module options to running a CLI command with its arguments.
|
||||
"""
|
||||
_dependencies = []
|
||||
|
||||
@classmethod
|
||||
@@ -46,6 +52,12 @@ class DependencyMixin(ModuleHelperBase):
|
||||
return cls._dependencies[-1]
|
||||
|
||||
def fail_on_missing_deps(self):
|
||||
self.module.deprecate(
|
||||
'The DependencyMixin is being deprecated. '
|
||||
'Modules should use community.general.plugins.module_utils.deps instead.',
|
||||
version='9.0.0',
|
||||
collection_name='community.general',
|
||||
)
|
||||
for d in self._dependencies:
|
||||
if not d.has_it:
|
||||
self.module.fail_json(changed=False,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user