mirror of
https://opendev.org/openstack/ansible-collections-openstack.git
synced 2026-03-27 05:53:02 +00:00
Compare commits
431 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b03f918ac | ||
|
|
c435002734 | ||
|
|
e8bba38e2e | ||
|
|
058bd87f2a | ||
|
|
7772bf125d | ||
|
|
17e78e5173 | ||
|
|
0e9a6f26c2 | ||
|
|
8dfcd17731 | ||
|
|
39bb4909ee | ||
|
|
ce60e71bde | ||
|
|
b579d03968 | ||
|
|
8743f24c4b | ||
|
|
7a9837dfb5 | ||
|
|
26b53e78b2 | ||
|
|
b8c2310963 | ||
|
|
915a78d7af | ||
|
|
60c39d495f | ||
|
|
2052a47324 | ||
|
|
3ecd3b6e64 | ||
|
|
c4a296c07c | ||
|
|
6b58d28a4e | ||
|
|
620956c61d | ||
|
|
970fb2489c | ||
|
|
8cc678acc1 | ||
|
|
75558c5c2e | ||
|
|
b4bde6af5c | ||
|
|
b935f21f44 | ||
|
|
3c047406dc | ||
|
|
be8965c7fc | ||
|
|
acf64a1f72 | ||
|
|
a4894337d4 | ||
|
|
0b0a80796f | ||
|
|
c63ff6fbc8 | ||
|
|
4f8f6ffaf4 | ||
|
|
0204bbeede | ||
|
|
5626a8d4c9 | ||
|
|
a3bb143f34 | ||
|
|
9c16ee4df3 | ||
|
|
a70a4c3424 | ||
|
|
708ed756ca | ||
|
|
c83884e5c8 | ||
|
|
655ed21ffa | ||
|
|
e64211213a | ||
|
|
39676b664a | ||
|
|
220f2b7dca | ||
|
|
0af7a252bd | ||
|
|
e8f9457893 | ||
|
|
29831685d8 | ||
|
|
82311440b5 | ||
|
|
57012cbaa3 | ||
|
|
5b453c62d1 | ||
|
|
8e1f1d6475 | ||
|
|
4b9e2295e0 | ||
|
|
5bb8312171 | ||
|
|
b3ac841442 | ||
|
|
37c52c321d | ||
|
|
6edc70f965 | ||
|
|
cc8cd08c03 | ||
|
|
b572bf8ae9 | ||
|
|
b3e0d610ea | ||
|
|
291e8b8640 | ||
|
|
f70a50e363 | ||
|
|
befcc4353d | ||
|
|
8a91352a38 | ||
|
|
1d7fd25ac0 | ||
|
|
44fa06cba1 | ||
|
|
26bc8a0666 | ||
|
|
19d0562551 | ||
|
|
07c3ed0c17 | ||
|
|
8708167b5f | ||
|
|
a9565779b5 | ||
|
|
5c2069c47d | ||
|
|
583df2a8a9 | ||
|
|
0f532d10f3 | ||
|
|
87858ab976 | ||
|
|
09c3e4bdc9 | ||
|
|
ebffbe4fe8 | ||
|
|
cbcfce2e23 | ||
|
|
406558dae9 | ||
|
|
c8d89f81a5 | ||
|
|
c0e1f56894 | ||
|
|
a031968f80 | ||
|
|
2e78559cc1 | ||
|
|
bf939a4ce0 | ||
|
|
24d6f36602 | ||
|
|
dd9cdde3d8 | ||
|
|
da4a68c188 | ||
|
|
a7a190f3c0 | ||
|
|
ce73c9db34 | ||
|
|
0e102b1411 | ||
|
|
9f58d54721 | ||
|
|
79d7827d17 | ||
|
|
ba9aa9967f | ||
|
|
617e8fb552 | ||
|
|
5abf89d805 | ||
|
|
0599d05103 | ||
|
|
9c28af7d12 | ||
|
|
bcb5d18492 | ||
|
|
7aa626377b | ||
|
|
0a7889b9a2 | ||
|
|
a1b920742f | ||
|
|
bd55e1f905 | ||
|
|
20329c0329 | ||
|
|
bdf472a53f | ||
|
|
b7fb23b097 | ||
|
|
6ed02eff2d | ||
|
|
cb396cf03d | ||
|
|
20c2633ea3 | ||
|
|
6569e07023 | ||
|
|
031475d42e | ||
|
|
5e2ab3d8c3 | ||
|
|
f3b12fed68 | ||
|
|
39a627d4a0 | ||
|
|
4eb7c43539 | ||
|
|
8c6d1041fa | ||
|
|
26530ac97b | ||
|
|
b3e07a1864 | ||
|
|
94933250e8 | ||
|
|
1582956dcd | ||
|
|
b1952e0c4b | ||
|
|
9cd6d2f69a | ||
|
|
86a57498e8 | ||
|
|
15f73aa72e | ||
|
|
22a7f516f3 | ||
|
|
de54be5ecd | ||
|
|
3f1a693bd6 | ||
|
|
8e87ad651f | ||
|
|
b2f3cf3210 | ||
|
|
11c7cd23f8 | ||
|
|
59d0e4c3a4 | ||
|
|
014665ddac | ||
|
|
21b70f6b9b | ||
|
|
ecaff2a798 | ||
|
|
02e9e87964 | ||
|
|
980536c32e | ||
|
|
a9a0d23441 | ||
|
|
011515de2d | ||
|
|
4292a00f75 | ||
|
|
bbefa8c156 | ||
|
|
b023aa337a | ||
|
|
c13f02fd54 | ||
|
|
ae4e7f3c06 | ||
|
|
2d554d1e22 | ||
|
|
770b283593 | ||
|
|
42921c6d9f | ||
|
|
292aabb477 | ||
|
|
3a08a9c07c | ||
|
|
0e370b2c51 | ||
|
|
0441403c42 | ||
|
|
4160888887 | ||
|
|
07374a1f0d | ||
|
|
8a395a04cf | ||
|
|
441a61fd8c | ||
|
|
c05b1fdbaf | ||
|
|
9cd92208d6 | ||
|
|
5ef192f1f2 | ||
|
|
aed60716ee | ||
|
|
938b90ea19 | ||
|
|
ce853a8f9f | ||
|
|
9911c7f93a | ||
|
|
8c890e656b | ||
|
|
b839f9e25d | ||
|
|
b7765776a7 | ||
|
|
4490e008c4 | ||
|
|
f376d4679e | ||
|
|
12ec8c63c2 | ||
|
|
72f371c157 | ||
|
|
ce421fe370 | ||
|
|
f20ec3a151 | ||
|
|
a89ec027b0 | ||
|
|
322f96c4db | ||
|
|
50b55560fc | ||
|
|
0c0013504e | ||
|
|
e651838f3e | ||
|
|
4553282545 | ||
|
|
235628dace | ||
|
|
4ee8621b37 | ||
|
|
d07039a7ec | ||
|
|
54728a83fa | ||
|
|
8431232eeb | ||
|
|
b21b8b1084 | ||
|
|
e2ffed388e | ||
|
|
ff44a1d1e5 | ||
|
|
9f893824c5 | ||
|
|
b9df964149 | ||
|
|
0c8fe9002e | ||
|
|
e010db6273 | ||
|
|
88277a59af | ||
|
|
1a4d0128c7 | ||
|
|
03a86669de | ||
|
|
fa7526a0ec | ||
|
|
7446ab23b8 | ||
|
|
4171ee52b7 | ||
|
|
60f1b8e2a5 | ||
|
|
0bff3f286f | ||
|
|
5188e281b9 | ||
|
|
966b6597f3 | ||
|
|
5636d502ce | ||
|
|
4db925b452 | ||
|
|
3ce4455bc8 | ||
|
|
309c3025ba | ||
|
|
637d321a9a | ||
|
|
74c18f34f3 | ||
|
|
00be40a462 | ||
|
|
1eb5d85b68 | ||
|
|
d0a4d6e8cc | ||
|
|
29c03592cc | ||
|
|
7888b51053 | ||
|
|
0e4dc21bab | ||
|
|
623b4afbd1 | ||
|
|
80e6597f96 | ||
|
|
8f1512166e | ||
|
|
eabe945194 | ||
|
|
06115c77b7 | ||
|
|
4a1b092efb | ||
|
|
da1fab6629 | ||
|
|
0efb855c68 | ||
|
|
329a5ef50d | ||
|
|
47708e0172 | ||
|
|
17d5c7de8e | ||
|
|
82792ab5d5 | ||
|
|
d4033b4cea | ||
|
|
426b6e782a | ||
|
|
75b2c60960 | ||
|
|
c9527889a0 | ||
|
|
42a5cb5601 | ||
|
|
aa387aab3a | ||
|
|
af79857bfb | ||
|
|
a51d922bee | ||
|
|
0cbaeb6fbb | ||
|
|
532857c0b2 | ||
|
|
acd9bc993b | ||
|
|
0904ddd2fe | ||
|
|
2120814356 | ||
|
|
ad70a20af5 | ||
|
|
a32cff23c7 | ||
|
|
f29a8407af | ||
|
|
555178ecc6 | ||
|
|
f93172677c | ||
|
|
2a461cadd9 | ||
|
|
e3c61aeefd | ||
|
|
3e4413ec31 | ||
|
|
37afe5f2e6 | ||
|
|
7e190d12b4 | ||
|
|
3d9f9a0f87 | ||
|
|
57e1087177 | ||
|
|
6cb6e70645 | ||
|
|
662ac61640 | ||
|
|
891fb6df53 | ||
|
|
0c6752215b | ||
|
|
a6f1177584 | ||
|
|
2dc2806c57 | ||
|
|
59df183660 | ||
|
|
2c287d754c | ||
|
|
28d32b53e8 | ||
|
|
2cb67620aa | ||
|
|
5217b6bdc4 | ||
|
|
96ea60a883 | ||
|
|
0eef3cb978 | ||
|
|
e695000daa | ||
|
|
0258878400 | ||
|
|
ea7ba854d5 | ||
|
|
6b3bf3bba0 | ||
|
|
daaa6bf561 | ||
|
|
2027eb1f46 | ||
|
|
944f9ca498 | ||
|
|
ca6824bffe | ||
|
|
a10be98638 | ||
|
|
6787924f13 | ||
|
|
d1d6b4d2dd | ||
|
|
06e76a1687 | ||
|
|
464d7767bb | ||
|
|
718f3a6b3a | ||
|
|
3320c662c8 | ||
|
|
77acba047b | ||
|
|
890401b605 | ||
|
|
8da4e852f0 | ||
|
|
f3e9c78c18 | ||
|
|
47382d52ed | ||
|
|
0e2058988e | ||
|
|
ab1a2a19d7 | ||
|
|
17a1d72b1c | ||
|
|
58ec1030a4 | ||
|
|
da01746e53 | ||
|
|
c329f65b41 | ||
|
|
18b03e1971 | ||
|
|
16a81fc221 | ||
|
|
50deae71f4 | ||
|
|
b1e5ca91cf | ||
|
|
185d0a5eca | ||
|
|
2b8aa2cb08 | ||
|
|
3c8fbc6b27 | ||
|
|
d212be018b | ||
|
|
573e219e30 | ||
|
|
5c3750df2c | ||
|
|
94e0e10e49 | ||
|
|
db9a8d5a18 | ||
|
|
7e20a8fc97 | ||
|
|
c7969aa052 | ||
|
|
179a500903 | ||
|
|
ab3e136867 | ||
|
|
8d2391d873 | ||
|
|
e1d62ff73a | ||
|
|
c3261d9813 | ||
|
|
1d8605fbf7 | ||
|
|
0843990dee | ||
|
|
6f8b39bb16 | ||
|
|
c39c8f9d74 | ||
|
|
e4c7bd3df8 | ||
|
|
8a4974025f | ||
|
|
51a9731cef | ||
|
|
051b270d36 | ||
|
|
ca234d7e42 | ||
|
|
5967e1ad0a | ||
|
|
bca980c115 | ||
|
|
a55b817968 | ||
|
|
b7c22515b7 | ||
|
|
70c773fe6d | ||
|
|
a3f809eb99 | ||
|
|
049a2de725 | ||
|
|
69947cd9fd | ||
|
|
c68b33f79f | ||
|
|
62f0da75bb | ||
|
|
6e2bde4060 | ||
|
|
e4a223d160 | ||
|
|
6d4d8d4b0c | ||
|
|
a4e6d1b67c | ||
|
|
3aaf7ff03a | ||
|
|
f6a5433503 | ||
|
|
92c10638a9 | ||
|
|
e3317db56d | ||
|
|
870f82d97b | ||
|
|
87c305907e | ||
|
|
c532560d1b | ||
|
|
ea1f1df805 | ||
|
|
40a32c1e8b | ||
|
|
5881f5423a | ||
|
|
51eba6de02 | ||
|
|
93faf4f1c3 | ||
|
|
c03284abec | ||
|
|
49c95804ba | ||
|
|
c8a5be6b30 | ||
|
|
8255ec4c80 | ||
|
|
36ce09a781 | ||
|
|
0ac75add62 | ||
|
|
d004e0af05 | ||
|
|
b040392238 | ||
|
|
19f24568a2 | ||
|
|
9783fbb972 | ||
|
|
b87e474192 | ||
|
|
c1b8786160 | ||
|
|
981d268039 | ||
|
|
af27a79312 | ||
|
|
e504d807de | ||
|
|
faada98ed9 | ||
|
|
c914c42799 | ||
|
|
d5c403cded | ||
|
|
d36ac1f125 | ||
|
|
15675ce23f | ||
|
|
8180fe8af8 | ||
|
|
88f03fa1df | ||
|
|
565f7fd369 | ||
|
|
47a0d625dc | ||
|
|
b09d8248f7 | ||
|
|
bce3eea5c0 | ||
|
|
134a8e9d23 | ||
|
|
9ed9b1d399 | ||
|
|
80abd782da | ||
|
|
ee9a5c564e | ||
|
|
393b484e5a | ||
|
|
6117f7062e | ||
|
|
f89eea10b4 | ||
|
|
e1178fde34 | ||
|
|
8b35c64fda | ||
|
|
8b98452cbb | ||
|
|
d081bb5378 | ||
|
|
2ce1adad4a | ||
|
|
8ca8df1a84 | ||
|
|
058cb4ff3f | ||
|
|
1c6663999d | ||
|
|
ab96eb6a11 | ||
|
|
38e61994c7 | ||
|
|
d416a27112 | ||
|
|
631e1412a0 | ||
|
|
4c31ea152e | ||
|
|
a39470ac2b | ||
|
|
39a8362d7a | ||
|
|
05da83520e | ||
|
|
a6b52612de | ||
|
|
a67272d1f5 | ||
|
|
f448c78dd4 | ||
|
|
33ce7ab9c7 | ||
|
|
03fadf3b43 | ||
|
|
86a5cc3b42 | ||
|
|
8731fcc64b | ||
|
|
f6a7cf5343 | ||
|
|
284d7871ce | ||
|
|
fcf6fae499 | ||
|
|
88b86be33e | ||
|
|
1f3417cdef | ||
|
|
8792b2b527 | ||
|
|
4a930cf0ec | ||
|
|
e1fe3f6067 | ||
|
|
40ce8103f4 | ||
|
|
bbe1d84448 | ||
|
|
9600baec6e | ||
|
|
abebbe722c | ||
|
|
94e518e42c | ||
|
|
a96d28dfbc | ||
|
|
32ef77d9fd | ||
|
|
4b64ebe623 | ||
|
|
01c2499fb6 | ||
|
|
5e3a91a7c6 | ||
|
|
fc852da4bc | ||
|
|
5717f05102 | ||
|
|
4d0df9f022 | ||
|
|
f8c768ae61 | ||
|
|
4d1017d5d9 | ||
|
|
c75ab0924a | ||
|
|
dfa7983a78 | ||
|
|
8e2e5966b7 | ||
|
|
c9da50e7e7 | ||
|
|
f3610ad0e1 | ||
|
|
7e4fbcf568 | ||
|
|
f89644973d | ||
|
|
b4f015ebd7 | ||
|
|
f0da22da7e | ||
|
|
d206ea000a | ||
|
|
5667600420 | ||
|
|
98ce765383 | ||
|
|
ad7d6ea668 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,7 +1,6 @@
|
||||
.tox
|
||||
build_artifact
|
||||
ansible_collections
|
||||
galaxy.yml
|
||||
FILES.json
|
||||
MANIFEST.json
|
||||
importer_result.json
|
||||
|
||||
697
.zuul.yaml
697
.zuul.yaml
@@ -1,239 +1,594 @@
|
||||
# yamllint disable
|
||||
---
|
||||
# Keep parent jobs in sync between branches to avoid issues e.g. with job scheduling. Zuul CI will search in master
|
||||
# branch first when collecting job variants during job freeze which can have unwanted side effects. For example, when
|
||||
# parent job *-base has been changed in stable/1.0.0 branch, Zuul could still use *-base variants from master branch
|
||||
# during job freeze on child jobs such as *-ussuri-ansible-2.11 etc.
|
||||
#
|
||||
# Do not share job definitions with the job.branches attribute across multiple branches. Do not define jobs which are
|
||||
# specific to other branches, except for parent jobs which are shared across branches. For example, to not add a job
|
||||
# which is specific for the stable/1.0.0 branch to the .zuul.yaml in master branch. In particular do not use the
|
||||
# job.branches directive on a job which will be copied to multiple branches. When you have multiple copies of a job with
|
||||
# the job.branches attribute, Zuul CI could pick any of the job definitions which might not be the one you expected.
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack
|
||||
name: ansible-collections-openstack-functional-devstack-base
|
||||
parent: openstacksdk-functional-devstack
|
||||
# Do not restrict branches in base jobs because else Zuul would not find a matching
|
||||
# parent job variant during job freeze when child jobs are on other branches.
|
||||
post-run: ci/playbooks/postlog.yaml
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using master of openstacksdk with latest ansible release
|
||||
Run openstack collections functional tests against a devstack
|
||||
# Do not set job.override-checkout or job.required-projects.override-checkout in base job because
|
||||
# else Zuul will use this branch when matching variants for parent jobs during job freeze
|
||||
required-projects:
|
||||
- openstack/ansible-collections-openstack
|
||||
- openstack/designate
|
||||
# openstack/devstack is required through parent job openstacksdk-functional-devstack
|
||||
# openstack/os-client-config is required through parent job openstacksdk-functional-devstack
|
||||
# openstack/openstacksdk is required through parent job openstacksdk-functional-devstack
|
||||
irrelevant-files: &ignore_files
|
||||
- changelogs/.*
|
||||
- galaxy.*
|
||||
- COPYING
|
||||
- docs/.*
|
||||
- .*\.md
|
||||
- .*\.rst
|
||||
- tools/run-ansible-sanity.sh
|
||||
- tests/sanity/.*
|
||||
- contrib/.*
|
||||
- .zuul.yaml
|
||||
vars:
|
||||
zuul_work_dir: src/opendev.org/openstack/ansible-collections-openstack
|
||||
tox_envlist: ansible
|
||||
tox_install_siblings: true
|
||||
fetch_subunit: false
|
||||
devstack_plugins:
|
||||
designate: https://opendev.org/openstack/designate
|
||||
devstack_services:
|
||||
designate: true
|
||||
neutron-dns: true
|
||||
zuul_copy_output:
|
||||
'{{ devstack_log_dir }}/test_output.log': 'logs'
|
||||
extensions_to_txt:
|
||||
log: true
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-octavia-base
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
# Do not restrict branches in base jobs because else Zuul would not find a matching
|
||||
# parent job variant during job freeze when child jobs are on other branches.
|
||||
description: |
|
||||
Run openstack collections functional tests against a devstack with Octavia plugin enabled
|
||||
pre-run: ci/playbooks/get_amphora_tarball.yaml
|
||||
# Do not set job.override-checkout or job.required-projects.override-checkout in base job because
|
||||
# else Zuul will use this branch when matching variants for parent jobs during job freeze
|
||||
required-projects:
|
||||
- openstack/octavia
|
||||
files:
|
||||
- ^ci/roles/loadbalancer/.*$
|
||||
- ^plugins/modules/lb_health_monitor.py
|
||||
- ^plugins/modules/lb_listener.py
|
||||
- ^plugins/modules/lb_member.py
|
||||
- ^plugins/modules/lb_pool.py
|
||||
- ^plugins/modules/loadbalancer.py
|
||||
vars:
|
||||
configure_swap_size: 8192
|
||||
tox_install_siblings: false
|
||||
devstack_plugins:
|
||||
designate: https://opendev.org/openstack/designate
|
||||
octavia: https://opendev.org/openstack/octavia
|
||||
devstack_services:
|
||||
designate: true
|
||||
neutron-dns: true
|
||||
octavia: true
|
||||
o-api: true
|
||||
o-cw: true
|
||||
o-hk: true
|
||||
o-hm: true
|
||||
devstack_localrc:
|
||||
OCTAVIA_AMP_IMAGE_FILE: "/tmp/test-only-amphora-x64-haproxy-ubuntu-bionic.qcow2"
|
||||
OCTAVIA_AMP_IMAGE_SIZE: 3
|
||||
OCTAVIA_AMP_IMAGE_NAME: "test-only-amphora-x64-haproxy-ubuntu-bionic"
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-octavia
|
||||
parent: ansible-collections-openstack-functional-devstack-octavia-base
|
||||
branches: stable/1.0.0
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
with Octavia plugin enabled, using 0.*.* releases of openstacksdk
|
||||
and latest ansible release. Run it only on Load Balancer changes.
|
||||
required-projects:
|
||||
- # Choose parent devstack job from master branch instead of non-existing stable/1.0.0 branch
|
||||
name: openstack/devstack
|
||||
override-checkout: master
|
||||
- # Choose parent devstack job from master branch instead of non-existing stable/1.0.0 branch
|
||||
name: openstack/openstacksdk
|
||||
override-checkout: master
|
||||
vars:
|
||||
tox_constraints_file: '{{ ansible_user_dir }}/{{ zuul.project.src_dir }}/tests/constraints-openstacksdk-0.x.x.txt'
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-releases
|
||||
parent: ansible-collections-openstack-functional-devstack
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
branches: stable/1.0.0
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using releases of openstacksdk and latest ansible release
|
||||
using 0.*.* releases of openstacksdk and latest ansible release
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.9
|
||||
- # Choose parent devstack job from master branch instead of non-existing stable/1.0.0 branch
|
||||
name: openstack/devstack
|
||||
override-checkout: master
|
||||
- # Choose parent devstack job from master branch instead of non-existing stable/1.0.0 branch
|
||||
name: openstack/openstacksdk
|
||||
override-checkout: master
|
||||
vars:
|
||||
tox_constraints_file: '{{ ansible_user_dir }}/{{ zuul.project.src_dir }}/tests/constraints-openstacksdk-0.x.x.txt'
|
||||
tox_install_siblings: false
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
parent: ansible-collections-openstack-functional-devstack
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using master of openstacksdk and devel branch of ansible
|
||||
# non-voting because we can't prevent ansible devel from breaking us
|
||||
voting: false
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: devel
|
||||
|
||||
# Job with Ansible 2.9 for checking backward compatibility
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-2.9
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
branches: stable/1.0.0
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using master of openstacksdk and stable 2.9 branch of ansible
|
||||
voting: true
|
||||
using 0.*.* releases of openstacksdk and stable 2.9 branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.9
|
||||
- # Choose parent devstack job from master branch instead of non-existing stable/1.0.0 branch
|
||||
name: openstack/devstack
|
||||
override-checkout: master
|
||||
- name: openstack/openstacksdk
|
||||
# Yoga has the latest SDK release of the 0.*.* series atm
|
||||
override-checkout: stable/yoga
|
||||
vars:
|
||||
tox_envlist: ansible-2.9
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-train-ansible-devel
|
||||
parent: ansible-collections-openstack-functional-devstack
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-2.11
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
branches: stable/1.0.0
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using 0.*.* releases of openstacksdk and stable 2.12 branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.11
|
||||
- # Choose parent devstack job from master branch instead of non-existing stable/1.0.0 branch
|
||||
name: openstack/devstack
|
||||
override-checkout: master
|
||||
- name: openstack/openstacksdk
|
||||
# Yoga has the latest SDK release of the 0.*.* series atm
|
||||
override-checkout: stable/yoga
|
||||
vars:
|
||||
tox_envlist: ansible-2.11
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-2.12
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
branches: stable/1.0.0
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using 0.*.* releases of openstacksdk and stable 2.12 branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.12
|
||||
- # Choose parent devstack job from master branch instead of non-existing stable/1.0.0 branch
|
||||
name: openstack/devstack
|
||||
override-checkout: master
|
||||
- name: openstack/openstacksdk
|
||||
# Yoga has the latest SDK release of the 0.*.* series atm
|
||||
override-checkout: stable/yoga
|
||||
vars:
|
||||
tox_envlist: ansible-2.12
|
||||
|
||||
# Stable branches tests
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-xena-ansible-2.12
|
||||
# Do not inherit from any parent job which does not run for branch stable/1.0.0 because Zuul would dismiss this job
|
||||
# when collecting parent job variants. For example, when job.branches is set to master in a parent job, then Zuul
|
||||
# will not match that job when it collects job variants.
|
||||
#
|
||||
# Do not inherit from any parent job which sets job.required-projects.override-checkout on openstack/devstack
|
||||
# because Zuul would use that git ref instead of stable branch defined below to checkout projects of parent devstack
|
||||
# jobs when collecting variants for parent jobs.
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
description: |
|
||||
Run openstack collections functional tests against a xena devstack
|
||||
using xena branch of openstacksdk and stable 2.12 branch of ansible
|
||||
branches: stable/1.0.0
|
||||
override-checkout: stable/xena
|
||||
# job.override-checkout will not override job.required-projects.override-checkout in parent jobs
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.12
|
||||
- # Choose parent devstack job from stable/1.0.0 branch instead of non-existing stable/xena branch
|
||||
name: openstack/ansible-collections-openstack
|
||||
override-checkout: stable/1.0.0
|
||||
- # Choose parent devstack job from stable/xena branch
|
||||
name: openstack/devstack
|
||||
override-checkout: stable/xena
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/xena
|
||||
vars:
|
||||
tox_envlist: ansible-2.12
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-wallaby-ansible-2.12
|
||||
# Do not inherit from any parent job which does not run for branch stable/1.0.0 because Zuul would dismiss this job
|
||||
# when collecting parent job variants. For example, when job.branches is set to master in a parent job, then Zuul
|
||||
# will not match that job when it collects job variants.
|
||||
#
|
||||
# Do not inherit from any parent job which sets job.required-projects.override-checkout on openstack/devstack
|
||||
# because Zuul would use that git ref instead of stable branch defined below to checkout projects of parent devstack
|
||||
# jobs when collecting variants for parent jobs.
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
description: |
|
||||
Run openstack collections functional tests against a wallaby devstack
|
||||
using wallaby branch of openstacksdk and stable 2.12 branch of ansible
|
||||
branches: stable/1.0.0
|
||||
override-checkout: stable/wallaby
|
||||
# job.override-checkout will not override job.required-projects.override-checkout in parent jobs
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.12
|
||||
- # Choose parent devstack job from stable/1.0.0 branch instead of non-existing stable/wallaby branch
|
||||
name: openstack/ansible-collections-openstack
|
||||
override-checkout: stable/1.0.0
|
||||
- # Choose parent devstack job from stable/wallaby branch
|
||||
name: openstack/devstack
|
||||
override-checkout: stable/wallaby
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/wallaby
|
||||
vars:
|
||||
tox_envlist: ansible-2.12
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-victoria-ansible-2.12
|
||||
# Do not inherit from any parent job which does not run for branch stable/1.0.0 because Zuul would dismiss this job
|
||||
# when collecting parent job variants. For example, when job.branches is set to master in a parent job, then Zuul
|
||||
# will not match that job when it collects job variants.
|
||||
#
|
||||
# Do not inherit from any parent job which sets job.required-projects.override-checkout on openstack/devstack
|
||||
# because Zuul would use that git ref instead of stable branch defined below to checkout projects of parent devstack
|
||||
# jobs when collecting variants for parent jobs.
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
description: |
|
||||
Run openstack collections functional tests against a victoria devstack
|
||||
using victoria branch of openstacksdk and stable 2.12 branch of ansible
|
||||
branches: stable/1.0.0
|
||||
override-checkout: stable/victoria
|
||||
# job.override-checkout will not override job.required-projects.override-checkout in parent jobs
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.12
|
||||
- # Choose parent devstack job from stable/1.0.0 branch instead of non-existing stable/victoria branch
|
||||
name: openstack/ansible-collections-openstack
|
||||
override-checkout: stable/1.0.0
|
||||
- # Choose parent devstack job from stable/victoria branch
|
||||
name: openstack/devstack
|
||||
override-checkout: stable/victoria
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/victoria
|
||||
vars:
|
||||
tox_envlist: ansible-2.12
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ussuri-ansible-2.11
|
||||
# Do not inherit from any parent job which does not run for branch stable/1.0.0 because Zuul would dismiss this job
|
||||
# when collecting parent job variants. For example, when job.branches is set to master in a parent job, then Zuul
|
||||
# will not match that job when it collects job variants.
|
||||
#
|
||||
# Do not inherit from any parent job which sets job.required-projects.override-checkout on openstack/devstack
|
||||
# because Zuul would use that git ref instead of stable branch defined below to checkout projects of parent devstack
|
||||
# jobs when collecting variants for parent jobs.
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
description: |
|
||||
Run openstack collections functional tests against a ussuri devstack
|
||||
using ussuri branch of openstacksdk and stable 2.11 branch of ansible
|
||||
branches: stable/1.0.0
|
||||
override-checkout: stable/ussuri
|
||||
# job.override-checkout will not override job.required-projects.override-checkout in parent jobs
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.11
|
||||
- # Choose parent devstack job from stable/1.0.0 branch instead of non-existing stable/ussuri branch
|
||||
name: openstack/ansible-collections-openstack
|
||||
override-checkout: stable/1.0.0
|
||||
- # Choose parent devstack job from stable/ussuri branch
|
||||
name: openstack/devstack
|
||||
override-checkout: stable/ussuri
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/ussuri
|
||||
vars:
|
||||
tox_envlist: ansible-2.11
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-train-ansible-2.11
|
||||
# Do not inherit from any parent job which does not run for branch stable/1.0.0 because Zuul would dismiss this job
|
||||
# when collecting parent job variants. For example, when job.branches is set to master in a parent job, then Zuul
|
||||
# will not match that job when it collects job variants.
|
||||
#
|
||||
# Do not inherit from any parent job which sets job.required-projects.override-checkout on openstack/devstack
|
||||
# because Zuul would use that git ref instead of stable branch defined below to checkout projects of parent devstack
|
||||
# jobs when collecting variants for parent jobs.
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
description: |
|
||||
Run openstack collections functional tests against a train devstack
|
||||
using train brach of openstacksdk and devel branch of ansible
|
||||
# non-voting because we can't prevent ansible devel from breaking us
|
||||
voting: false
|
||||
using train branch of openstacksdk and stable 2.11 branch of ansible
|
||||
branches: stable/1.0.0
|
||||
override-checkout: stable/train
|
||||
# job.override-checkout will not override job.required-projects.override-checkout in parent jobs
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.11
|
||||
- # Choose parent devstack job from stable/1.0.0 branch instead of non-existing stable/train branch
|
||||
name: openstack/ansible-collections-openstack
|
||||
override-checkout: stable/1.0.0
|
||||
- # Choose parent devstack job from stable/train branch
|
||||
name: openstack/devstack
|
||||
override-checkout: stable/train
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/train
|
||||
vars:
|
||||
tox_envlist: ansible-2.11
|
||||
|
||||
# Linters
|
||||
- job:
|
||||
name: openstack-tox-linters-ansible
|
||||
parent: openstack-tox-linters
|
||||
nodeset: ubuntu-focal
|
||||
description: |
|
||||
Run openstack collections linter tests using the devel branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: devel
|
||||
- name: openstack/openstacksdk
|
||||
override-branch: train
|
||||
- name: openstack/devstack
|
||||
override-checkout: train
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-train-ansible-2.9
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
description: |
|
||||
Run openstack collections functional tests against a train devstack
|
||||
using train brach of openstacksdk and stable 2.9 branch of ansible
|
||||
voting: true
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.9
|
||||
- name: openstack/openstacksdk
|
||||
override-branch: train
|
||||
- name: openstack/devstack
|
||||
override-checkout: train
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-stein-ansible-devel
|
||||
parent: ansible-collections-openstack-functional-devstack
|
||||
description: |
|
||||
Run openstack collections functional tests against a stein devstack
|
||||
using stein brach of openstacksdk and devel branch of ansible
|
||||
# non-voting because we can't prevent ansible devel from breaking us
|
||||
voting: false
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: devel
|
||||
- name: openstack/openstacksdk
|
||||
override-branch: stein
|
||||
- name: openstack/devstack
|
||||
override-checkout: stein
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-stein-ansible-2.9
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
description: |
|
||||
Run openstack collections functional tests against a stein devstack
|
||||
using stein brach of openstacksdk and stable 2.9 branch of ansible
|
||||
voting: true
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.9
|
||||
- name: openstack/openstacksdk
|
||||
override-branch: stein
|
||||
- name: openstack/devstack
|
||||
override-checkout: stein
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-rocky-ansible-devel
|
||||
parent: ansible-collections-openstack-functional-devstack
|
||||
description: |
|
||||
Run openstack collections functional tests against a rocky devstack
|
||||
using rocky brach of openstacksdk and devel branch of ansible
|
||||
# non-voting because we can't prevent ansible devel from breaking us
|
||||
voting: false
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: devel
|
||||
- name: openstack/openstacksdk
|
||||
override-branch: rocky
|
||||
- name: openstack/devstack
|
||||
override-checkout: rocky
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-rocky-ansible-2.9
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
description: |
|
||||
Run openstack collections functional tests against a rocky devstack
|
||||
using rocky brach of openstacksdk and stable 2.9 branch of ansible
|
||||
voting: true
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.9
|
||||
- name: openstack/openstacksdk
|
||||
override-branch: rocky
|
||||
- name: openstack/devstack
|
||||
override-checkout: rocky
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-queens-ansible-2.9
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
description: |
|
||||
Run openstack collections functional tests against a queens devstack
|
||||
using master brach of openstacksdk and stable 2.9 branch of ansible
|
||||
voting: true
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.9
|
||||
- name: openstack/openstacksdk
|
||||
override-branch: master
|
||||
- name: openstack/devstack
|
||||
override-checkout: queens
|
||||
vars:
|
||||
# override tox_constraints_file from parent job
|
||||
tox_constraints_file: '{{ ansible_user_dir }}/{{ zuul.project.src_dir }}/tests/constraints-none.txt'
|
||||
tox_envlist: linters
|
||||
tox_install_siblings: true
|
||||
|
||||
- job:
|
||||
name: openstack-tox-linters-ansible-devel
|
||||
parent: openstack-tox-linters
|
||||
parent: openstack-tox-linters-ansible
|
||||
nodeset: ubuntu-jammy
|
||||
description: |
|
||||
Run openstack collections linter tests using the devel branch of ansible
|
||||
# non-voting because we can't prevent ansible devel from breaking us
|
||||
voting: false
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: devel
|
||||
vars:
|
||||
python_version: '3.10'
|
||||
bindep_profile: test py310
|
||||
|
||||
- job:
|
||||
name: openstack-tox-linters-ansible-2.9
|
||||
parent: openstack-tox-linters
|
||||
name: openstack-tox-linters-ansible-2.12
|
||||
parent: openstack-tox-linters-ansible
|
||||
description: |
|
||||
Run openstack collections linter tests using the 2.9 branch of ansible
|
||||
voting: true
|
||||
Run openstack collections linter tests using the 2.12 branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.9
|
||||
override-checkout: stable-2.12
|
||||
vars:
|
||||
tox_envlist: linters-2.12
|
||||
python_version: 3.8
|
||||
bindep_profile: test py38
|
||||
|
||||
# Cross-checks with other projects
|
||||
- job:
|
||||
name: bifrost-collections-src
|
||||
parent: bifrost-integration-tinyipa-ubuntu-focal
|
||||
override-checkout: stable/yoga
|
||||
# job.override-checkout will not override job.required-projects.override-checkout in parent jobs
|
||||
required-projects:
|
||||
- openstack/ansible-collections-openstack
|
||||
- # always use existing branch when collecting parent job variants, refer to git blame for rationale.
|
||||
name: openstack/bifrost
|
||||
# Yoga has the latest SDK release of the 0.*.* series atm
|
||||
override-checkout: stable/yoga
|
||||
- job:
|
||||
name: bifrost-keystone-collections-src
|
||||
parent: bifrost-integration-tinyipa-keystone-ubuntu-focal
|
||||
override-checkout: stable/yoga
|
||||
# job.override-checkout will not override job.required-projects.override-checkout in parent jobs
|
||||
required-projects:
|
||||
- openstack/ansible-collections-openstack
|
||||
- # always use existing branch when collecting parent job variants, refer to git blame for rationale.
|
||||
name: openstack/bifrost
|
||||
# Yoga has the latest SDK release of the 0.*.* series atm
|
||||
override-checkout: stable/yoga
|
||||
|
||||
# TripleO jobs
|
||||
- job:
|
||||
name: tripleo-ci-centos-8-standalone-osa-pre-zed
|
||||
parent: tripleo-ci-centos-8-standalone-build
|
||||
# Do not restrict branches in base jobs because else Zuul would not find a matching
|
||||
# parent job variant during job freeze when child jobs are on other branches.
|
||||
vars: &tripleo_vars
|
||||
consumer_job: false
|
||||
# Define branch_override in child jobs, e.g. branch_override: stable/yoga
|
||||
force_non_periodic: true
|
||||
required-projects: &tripleo_required_projects
|
||||
- # Required for TripleO Quickstart to install current patchset of the collection
|
||||
# Ref.: https://opendev.org/openstack/tripleo-quickstart/src/commit/b48d869e14de40444d69a107a0b718b5f721e912/quickstart.sh#L123
|
||||
openstack/ansible-collections-openstack
|
||||
- # always use master branch when collecting parent job variants, refer to git blame for rationale.
|
||||
name: openstack/tripleo-ci
|
||||
override-checkout: master
|
||||
irrelevant-files: &tripleo_irrelevant_files
|
||||
- .*molecule.*
|
||||
- ^.*\.md$
|
||||
- ^.*\.rst$
|
||||
- ^changelogs/.*$
|
||||
- ^contrib/.*$
|
||||
- ^docs/.*$
|
||||
- ^meta/.*$
|
||||
- ^requirements.*$
|
||||
- ^setup.*$
|
||||
- ^tests/.*$
|
||||
- ^tools/.*$
|
||||
- tox.ini
|
||||
# Run only on files used in TripleO
|
||||
files: &tripleo_files
|
||||
- ^.zuul.yaml$
|
||||
- ^plugins/module_utils/openstack.*$
|
||||
- ^plugins/modules/catalog_service.*$
|
||||
- ^plugins/modules/compute_flavor.*$
|
||||
- ^plugins/modules/endpoint.*$
|
||||
- ^plugins/modules/identity_domain.*$
|
||||
- ^plugins/modules/identity_domain_info.*$
|
||||
- ^plugins/modules/identity_role.*$
|
||||
- ^plugins/modules/identity_user.*$
|
||||
- ^plugins/modules/image.*$
|
||||
- ^plugins/modules/keypair.*$
|
||||
- ^plugins/modules/network.*$
|
||||
- ^plugins/modules/project.*$
|
||||
- ^plugins/modules/role_assignment.*$
|
||||
- ^plugins/modules/router.*$
|
||||
- ^plugins/modules/stack.*$
|
||||
- ^plugins/modules/subnet.*$
|
||||
|
||||
- job:
|
||||
name: tripleo-ci-centos-9-standalone-osa-pre-zed
|
||||
parent: tripleo-ci-centos-9-standalone-build
|
||||
# Do not restrict branches in base jobs because else Zuul would not find a matching
|
||||
# parent job variant during job freeze when child jobs are on other branches.
|
||||
vars: *tripleo_vars
|
||||
required-projects: *tripleo_required_projects
|
||||
irrelevant-files: *tripleo_irrelevant_files
|
||||
files: *tripleo_files
|
||||
|
||||
- job:
|
||||
name: tripleo-ci-centos-8-standalone-osa-train
|
||||
parent: tripleo-ci-centos-8-standalone-osa-pre-zed
|
||||
branches: stable/1.0.0
|
||||
override-checkout: stable/train
|
||||
vars:
|
||||
branch_override: stable/train
|
||||
|
||||
- job:
|
||||
name: tripleo-ci-centos-8-standalone-osa-wallaby
|
||||
parent: tripleo-ci-centos-8-standalone-osa-pre-zed
|
||||
branches: stable/1.0.0
|
||||
override-checkout: stable/wallaby
|
||||
vars:
|
||||
branch_override: stable/wallaby
|
||||
|
||||
- job:
|
||||
name: tripleo-ci-centos-9-standalone-osa-wallaby
|
||||
parent: tripleo-ci-centos-9-standalone-osa-pre-zed
|
||||
branches: stable/1.0.0
|
||||
override-checkout: stable/wallaby
|
||||
vars:
|
||||
branch_override: stable/wallaby
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-release
|
||||
parent: base
|
||||
run: ci/publish/publish_collection.yml
|
||||
secrets:
|
||||
- ansible_galaxy_info
|
||||
|
||||
- secret:
|
||||
name: ansible_galaxy_info
|
||||
data:
|
||||
url: https://galaxy.ansible.com
|
||||
token: !encrypted/pkcs1-oaep
|
||||
- lZFzfoCbuwqV1k6qRfl/VS7E+knUW7+zpg7BptrenK4n0g7UY0HtdVkYq0pV0Tj/LbhzG
|
||||
jHD0mehcV1iS6B7ORKg4criJkdDfEx09BD8z8yv0EleiIMmhlrCoMcY593OZMBtVbGi0D
|
||||
CwQtNO98QIsfZogChfLfvRNiBmUV98mEb/p6p3EtGx8J7qcAsqfWxc/CzB8GCleLAHHHT
|
||||
FuikMM03ZnV0ew7E+TPkHbzzPhBZOqS5HYF0HtgttHwIXdfIWp/XdTuEEk7uRRgYZ2Iao
|
||||
ifWRzoKaOQmhM++e1ydCqw9D4y9dZEFNMQLwSqcrvtb8cNwT1kl7SCFqYNE2lbutj4ne6
|
||||
PTBQRsKegMB4Y3ena14fNF6tCynvJLPhF/cjPH2Jhs+B19XQhWkL3TgiOY02W24YHwRcP
|
||||
+LdkM8inAvyVi3DEbEqdjBPO9OFJcBOKPlCdkGvuwdNCuEpEwctWs0gV3voflG2CDKzmJ
|
||||
wu9JJOAWnq/0l1WpuDqWreKeQ/BUGZC2Gb4xRAqofulgvhs4WuYoEccjH4EJFIZ90S1EP
|
||||
R/ZLadqZaEhmjwGM5sMWbBbjT23XsRgg0Tzt9m8DENYMuYDqkMdRbt2jYZa+32p4hyxVe
|
||||
Y6H/pqYq5b9uOzumnShaK4WlmkQyXcNPkoSlMC1h4OGvqX/WUixpI38jyMA5Tc=
|
||||
|
||||
- project:
|
||||
check:
|
||||
jobs:
|
||||
- tox-pep8
|
||||
- openstack-tox-linters-ansible-devel
|
||||
- openstack-tox-linters-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack:
|
||||
- openstack-tox-linters-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-releases:
|
||||
dependencies: &deps_unit_lint
|
||||
- tox-pep8
|
||||
- openstack-tox-linters-ansible-2.9
|
||||
irrelevant-files: &ignore_files
|
||||
- changelogs/.*
|
||||
- COPYING
|
||||
- docs/.*
|
||||
- README.md
|
||||
- tools/run-ansible-sanity.sh
|
||||
- tests/sanity/.*
|
||||
|
||||
- ansible-collections-openstack-functional-devstack-releases:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-ansible-devel:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- openstack-tox-linters-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.9:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-train-ansible-devel:
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.12:
|
||||
dependencies: *deps_unit_lint
|
||||
- ansible-collections-openstack-functional-devstack-ansible-devel:
|
||||
dependencies: *deps_unit_lint
|
||||
- ansible-collections-openstack-functional-devstack-xena-ansible-2.12:
|
||||
dependencies: *deps_unit_lint
|
||||
- ansible-collections-openstack-functional-devstack-wallaby-ansible-2.12:
|
||||
dependencies: *deps_unit_lint
|
||||
- ansible-collections-openstack-functional-devstack-train-ansible-2.11:
|
||||
dependencies: *deps_unit_lint
|
||||
- ansible-collections-openstack-functional-devstack-octavia:
|
||||
dependencies: *deps_unit_lint
|
||||
|
||||
- bifrost-collections-src:
|
||||
voting: false
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-train-ansible-2.9:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-stein-ansible-devel:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-stein-ansible-2.9:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-rocky-ansible-devel:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-rocky-ansible-2.9:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-queens-ansible-2.9:
|
||||
- bifrost-keystone-collections-src:
|
||||
voting: false
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
|
||||
- tripleo-ci-centos-8-standalone-osa-wallaby:
|
||||
dependencies: *deps_unit_lint
|
||||
- tripleo-ci-centos-9-standalone-osa-wallaby:
|
||||
voting: false
|
||||
dependencies: *deps_unit_lint
|
||||
|
||||
gate:
|
||||
jobs:
|
||||
- tox-pep8
|
||||
- openstack-tox-linters
|
||||
- ansible-collections-openstack-functional-devstack
|
||||
- openstack-tox-linters-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-releases
|
||||
# - ansible-collections-openstack-functional-devstack-ansible-2.9
|
||||
# - ansible-collections-openstack-functional-devstack-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-wallaby-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-xena-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-train-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-octavia
|
||||
- tripleo-ci-centos-8-standalone-osa-wallaby
|
||||
|
||||
periodic:
|
||||
jobs:
|
||||
- openstack-tox-linters-ansible-devel
|
||||
- openstack-tox-linters-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-releases
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack-train-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack-stein-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack-rocky-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack-queens-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
- ansible-collections-openstack-functional-devstack-xena-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-wallaby-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-victoria-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-train-ansible-2.11
|
||||
- bifrost-collections-src
|
||||
- bifrost-keystone-collections-src
|
||||
- ansible-collections-openstack-functional-devstack-octavia
|
||||
- tripleo-ci-centos-9-standalone-osa-wallaby
|
||||
- tripleo-ci-centos-8-standalone-osa-wallaby
|
||||
|
||||
experimental:
|
||||
jobs:
|
||||
- tripleo-ci-centos-8-standalone-osa-train
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-victoria-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-ussuri-ansible-2.11
|
||||
|
||||
tag:
|
||||
jobs:
|
||||
- ansible-collections-openstack-release
|
||||
|
||||
534
CHANGELOG.rst
Normal file
534
CHANGELOG.rst
Normal file
@@ -0,0 +1,534 @@
|
||||
=============================================
|
||||
Openstack Cloud Ansilbe modules Release Notes
|
||||
=============================================
|
||||
|
||||
.. contents:: Topics
|
||||
|
||||
|
||||
v1.10.0
|
||||
=======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Enable logging of openstacksdk activities and warn users about incompatible openstacksdk releases when using inventory plugin
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Add SDK logging option for openstack ansible collections
|
||||
- Don't use deprecated distutils from python 3.10
|
||||
- Ensure openstacksdk compatibility in inventory plugin
|
||||
- Lowered maximum OpenStack SDK version to 0.98.999 in inventory plugin
|
||||
|
||||
Known Issues
|
||||
------------
|
||||
|
||||
- For compatibility with OpenStack SDK >= 0.99.0 use Ansible OpenStack collection 2.0.0 or later which is currently under development.
|
||||
- Release series 1.x.x of this collection is compatible to OpenStack SDK prior to 0.99.0 only.
|
||||
|
||||
v1.9.1
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfix in keypair module
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Do not remove trailing spaces when reading public key in keypair module
|
||||
|
||||
Known Issues
|
||||
------------
|
||||
|
||||
- For compatibility with OpenStack SDK >= 0.99.0 use Ansible OpenStack collection 2.0.0 or later which is currently under development.
|
||||
- Release series 1.x.x of this collection is compatible to OpenStack SDK prior to 0.99.0 only.
|
||||
|
||||
v1.9.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
This release will enforce openstacksdk<0.99.0, has a dozen modules refactored and several bugs fixed.
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Added support for specifying a maximum version of the OpenStack SDK
|
||||
- Constrain filters in compute_service_info to SDK >= 0.53.0
|
||||
- Drop username from return values of identity_user_info
|
||||
- Fix logic in routers_info
|
||||
- Fixed return value disable{d,s}_reason in compute_service_info module
|
||||
- Fixed return values in compute_service_info module again
|
||||
- Follow up to bump of minimum required OpenStack SDK release to SDK 0.36.0 (Train)
|
||||
- Lowered maximum OpenStack SDK version to 0.98.999
|
||||
- Move dns zone info to use proxy layer
|
||||
- Refactored catalog_service module
|
||||
- Refactored endpoint module
|
||||
- Refactored host_aggregate module
|
||||
- Refactored identity_domain_info module
|
||||
- Refactored identity_group_info module
|
||||
- Refactored identity_role module
|
||||
- Refactored identity_role_info module
|
||||
- Refactored identity_user module
|
||||
- Refactored identity_user_info module
|
||||
- Refactored image_info module
|
||||
- Refactored keypair_info module
|
||||
- Refactored recordset module
|
||||
- Refactored role_assignment module
|
||||
- Set owner in image module
|
||||
- Support description in sg-rule creation
|
||||
- Warn users about us breaking backward compatibility
|
||||
|
||||
Known Issues
|
||||
------------
|
||||
|
||||
- For compatibility with OpenStack SDK >= 0.99.0 use Ansible OpenStack collection 2.0.0 or later which is currently under development.
|
||||
- Release series 1.x.x of this collection is compatible to OpenStack SDK prior to 0.99.0 only.
|
||||
|
||||
v1.8.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Subnet pool module and bugfixes
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Add 'all_projects' to server_action module
|
||||
- Add subnet pool module
|
||||
- Bumped minimum required OpenStack SDK release to SDK 0.36.0 (Train)
|
||||
- Changed compute_flavor_info module to use OpenStack SDK's proxy layer
|
||||
- Dropped deprecated return values in floating_ip_info and assert remaining fields
|
||||
- Fix ansible-lint issues for the newest version
|
||||
- Fix assertion after stack deletion
|
||||
- Handle aggregate host list set to None
|
||||
- Reenabled check-import.sh which tests imports to Ansible Galaxy
|
||||
- Remove old, unsupported parameters from documentation in image_info module
|
||||
- Router - Remove unneeded 'filter' parameter
|
||||
- Updated return value docs of compute_service_info module
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.subnet_pool - Create or Delete subnet pools from OpenStack.
|
||||
|
||||
v1.7.2
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfixes
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Fix collection guidelines
|
||||
|
||||
v1.7.1
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfixes
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- lb_member - Add monitor_[address,port] parameter
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- openstack_inventory - Fix documentation
|
||||
- quota - Fix description of volumes_types parameter
|
||||
|
||||
v1.7.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
New modules for Ironic and bugfixes
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- openstack_inventory - Adds use_name variable
|
||||
- port - Add dns_[name,domain] to the port module
|
||||
- project - Remove project properties tests and support
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- identity_user_info - Fix identity user lookup with a domain
|
||||
- keystone_domain - Move identity domain to use proxy layer
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.baremetal_node_info - Retrieve information about Bare Metal nodes from OpenStack an object.
|
||||
- openstack.cloud.baremetal_port - Create, Update, Remove ironic ports from OpenStack
|
||||
- openstack.cloud.baremetal_port_info - Retrieve information about Bare Metal ports from OpenStack an object.
|
||||
|
||||
v1.6.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
New modules for RBAC and Nova services
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- quota - Adds metadata_items parameter
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.compute_service_info - Retrieve information about one or more OpenStack compute services
|
||||
- openstack.cloud.neutron_rbac_policies_info - Fetch Neutron policies.
|
||||
- openstack.cloud.neutron_rbac_policy - Create or delete a Neutron policy to apply a RBAC rule against an object.
|
||||
|
||||
v1.5.3
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfixes
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Don't require allowed_address_pairs for port
|
||||
- server_volume - check specified server is found
|
||||
|
||||
v1.5.2
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfixes
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add documentation links to README.md
|
||||
- Don't run functional jobs on galaxy.yml change
|
||||
- Move CI to use Ansible 2.12 version as main
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Add client and member listener timeouts for persistence (Ex. SSH)
|
||||
- Added missing warn() used in cloud.openstack.quota
|
||||
- Fix issue with same host and group names
|
||||
- Flavor properties are not deleted on changes and id will stay
|
||||
|
||||
v1.5.1
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfixes for networking modules
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Changed minversion in tox to 3.18.0
|
||||
- Update IRC server in README
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Add mandatory requires_ansible version to metadata
|
||||
- Add protocol listener octavia
|
||||
- Add support check mode for all info modules
|
||||
- Allow to attach multiple floating ips to a server
|
||||
- Only add or remove router interfaces when needed
|
||||
- Wait for pool to be active and online
|
||||
|
||||
v1.5.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
New modules for DNS and FIPs and bugfixes.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add bindep.txt for ansible-builder
|
||||
- Add check_mode attribute to OpenstackModule
|
||||
- Migrating image module from AnsibleModule to OpenStackModule
|
||||
- Switch KeystoneFederationProtocolInfo module to OpenStackModule
|
||||
- Switch ProjectAccess module to OpenStackModule
|
||||
- Switch Quota module to OpenStackModule
|
||||
- Switch Recordset module to OpenStackModule
|
||||
- Switch ServerGroup module to OpenStackModule
|
||||
- Switch ServerMetadata module to OpenStackModule
|
||||
- Switch Snapshot module to OpenStackModule
|
||||
- Switch Stack module to OpenStackModule
|
||||
- Switch auth module to OpenStackModule
|
||||
- Switch catalog_service module to OpenStackModule
|
||||
- Switch coe_cluster module to OpenStackModule
|
||||
- Switch coe_cluster_template module to OpenStackModule
|
||||
- Switch endpoint module to OpenStackModule
|
||||
- Switch federation_idp module to OpenStackModule
|
||||
- Switch federation_idp_info module to OpenStackModule
|
||||
- Switch federation_mapping module to OpenStackModule
|
||||
- Switch federation_mapping_info module to OpenStackModule
|
||||
- Switch federation_protocol module to OpenStackModule
|
||||
- Switch flavor module to OpenStackModule
|
||||
- Switch flavor_info module to OpenStackModule
|
||||
- Switch floating_ip module to OpenStackModule
|
||||
- Switch group_assignment module to OpenStackModule
|
||||
- Switch hostaggregate module to OpenStackModule
|
||||
- Switch identity_domain module to OpenStackModule
|
||||
- Switch identity_domain_info module to OpenStackModule
|
||||
- Switch identity_group module to OpenStackModule
|
||||
- Switch identity_group_info module to OpenStackModule
|
||||
- Switch identity_role module to OpenStackModule
|
||||
- Switch identity_user module to OpenStackModule
|
||||
- Switch lb_listener module to OpenStackModule
|
||||
- Switch lb_member module to OpenStackModule
|
||||
- Switch lb_pool module to OpenStackModule
|
||||
- Switch object module to OpenStackModule
|
||||
- Switch port module to OpenStackModule
|
||||
- Switch port_info module to OpenStackModule
|
||||
- Switch project and project_info module to OpenStackModule
|
||||
- Switch role_assignment module to OpenStackModule
|
||||
- Switch user_info module to OpenStackModule
|
||||
- image - Add support to setting image tags
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Update checks for validate_certs in openstack_cloud_from_module
|
||||
- compute_flavor - Fix the idempotent of compute_flavor module
|
||||
- host_aggregate - Fix host_aggregate to tolerate aggregate.hosts being None
|
||||
- inventory/openstack - Fix inventory plugin on Ansible 2.11
|
||||
- port - fix update on empty list of allowed address pairs
|
||||
- setup.cfg Replace dashes with underscores
|
||||
- subnet - Only apply necessary changes to subnets
|
||||
- volume - Fail if referenced source image for a new volume does not exist
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.address_scope - Create or delete address scopes from OpenStack
|
||||
- openstack.cloud.dns_zone_info - Getting information about dns zones
|
||||
- openstack.cloud.floating_ip_info - Get information about floating ips
|
||||
|
||||
v1.4.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
New object_container module and bugfixes.
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Add Octavia job for testing Load Balancer
|
||||
- Add binding profile to port module
|
||||
- Add execution environment metadata
|
||||
- Fix CI for latest ansible-test with no_log
|
||||
- Fix issues with newest ansible-test 2.11
|
||||
- Prepare for Ansible 2.11 tests
|
||||
- add option to exclude legacy groups
|
||||
- security_group_rule add support ipv6-icmp
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.object_container - Manage Swift container
|
||||
|
||||
v1.3.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
New modules and bugfixes.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Fix some typos in readme
|
||||
- Guidelines Fix links and formatting
|
||||
- baremetal_node - Add support for new features
|
||||
- baremetal_node - ironic deprecate sub-options of driver_info
|
||||
- baremetal_node - ironic stop putting meaningless values to properties
|
||||
- image_info - Migrating image_info module from AnsibleModule to OpenStackModule
|
||||
- recordset - Update recordset docu
|
||||
- server - Allow description field to be set with os_server
|
||||
- server_action - Added shelve and unshelve as new server actions
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- port - Fixed check for None in os_port
|
||||
- project - Fix setting custom property on os_project
|
||||
- security_group_rule - Remove protocols choice in security rules
|
||||
- volume_info - Fix volume_info result for SDK < 0.19
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.identity_role_info - Retrieve information about Openstack Identity roles.
|
||||
- openstack.cloud.keypair_info - Retrieve information about Openstack key pairs.
|
||||
- openstack.cloud.security_group_info - Retrieve information about Openstack Security Groups.
|
||||
- openstack.cloud.security_group_rule_info - Retrieve information about Openstack Security Group rules.
|
||||
- openstack.cloud.stack_info - Retrieve information about Openstack Heat stacks.
|
||||
|
||||
v1.2.1
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Porting modules to new OpenstackModule class and fixes.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- dns_zone - Migrating dns_zone from AnsibleModule to OpenStackModule
|
||||
- dns_zone, recordset - Enable update for recordset and add tests for dns and recordset module
|
||||
- endpoint - Do not fail when endpoint state is absent
|
||||
- ironic - Refactor ironic authentication into a new module_utils module
|
||||
- loadbalancer - Refactor loadbalancer module
|
||||
- network - Migrating network from AnsibleModule to OpenStackModule
|
||||
- networks_info - Migrating networks_info from AnsibleModule to OpenStackModule
|
||||
- openstack - Add galaxy.yml to support install from git
|
||||
- openstack - Fix docs-args mismatch in modules
|
||||
- openstack - OpenStackModule Support defining a minimum version of the SDK
|
||||
- router - Migrating routers from AnsibleModule to OpenStackModule
|
||||
- routers_info - Added deprecated_names for router_info module
|
||||
- routers_info - Migrating routers_info from AnsibleModule to OpenStackModule
|
||||
- security_group.py - Migrating security_group from AnsibleModule to OpenStackModule
|
||||
- security_group_rule - Refactor TCP/UDP port check
|
||||
- server.py - Improve "server" module with OpenstackModule class
|
||||
- server_volume - Migrating server_volume from AnsibleModule to OpenStackModule
|
||||
- subnet - Fix subnets update and idempotency
|
||||
- subnet - Migrating subnet module from AnsibleModule to OpenStackModule
|
||||
- subnets_info - Migrating subnets_info from AnsibleModule to OpenStackModule
|
||||
- volume.py - Migrating volume from AnsibleModule to OpenStackModule
|
||||
- volume_info - Fix volume_info arguments for SDK 0.19
|
||||
|
||||
v1.2.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
New volume backup modules.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- lb_health_monitor - Make it possible to create a health monitor to a pool
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.volume_backup module - Add/Delete Openstack volumes backup.
|
||||
- openstack.cloud.volume_backup_info module - Retrieve information about Openstack volume backups.
|
||||
- openstack.cloud.volume_snapshot_info module - Retrieve information about Openstack volume snapshots.
|
||||
|
||||
v1.1.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Starting redesign modules and bugfixes.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- A basic module subclass was introduced and a few modules moved to inherit from it.
|
||||
- Add more useful information from exception
|
||||
- Added pip installation option for collection.
|
||||
- Added template for generation of artibtrary module.
|
||||
- baremetal modules - Do not require ironic_url if cloud or auth.endpoint is provided
|
||||
- inventory_openstack - Add openstack logger and Ansible display utility
|
||||
- loadbalancer - Add support for setting the Flavor when creating a load balancer
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Fix non existing attribuites in SDK exception
|
||||
- security_group_rule - Don't pass tenant_id for remote group
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.volume_info - Retrieve information about Openstack volumes.
|
||||
|
||||
v1.0.1
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfix for server_info
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- server_info - Fix broken server_info module and add tests
|
||||
|
||||
v1.0.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Initial release of collection.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Renaming all modules and removing "os" prefix from names.
|
||||
- baremetal_node_action - Support json type for the ironic_node config_drive parameter
|
||||
- config - Update os_client_config to use openstacksdk
|
||||
- host_aggregate - Add support for not 'purging' missing hosts
|
||||
- project - Add properties for os_project
|
||||
- server_action - pass imageRef to rebuild
|
||||
- subnet - Updated allocation pool checks
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- baremetal_node - Correct parameter name
|
||||
- coe_cluster - Retrive id/uuid correctly
|
||||
- federation_mapping - Fixup some minor nits found in followup reviews
|
||||
- inventory_openstack - Fix constructed compose
|
||||
- network - Bump minimum openstacksdk version when using os_network/dns_domain
|
||||
- role_assignment - Fix os_user_role for groups in multidomain context
|
||||
- role_assignment - Fix os_user_role issue to grant a role in a domain
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.federation_idp - Add support for Keystone Identity Providers
|
||||
- openstack.cloud.federation_idp_info - Add support for fetching the information about federation IDPs
|
||||
- openstack.cloud.federation_mapping - Add support for Keystone mappings
|
||||
- openstack.cloud.federation_mapping_info - Add support for fetching the information about Keystone mappings
|
||||
- openstack.cloud.keystone_federation_protocol - Add support for Keystone federation Protocols
|
||||
- openstack.cloud.keystone_federation_protocol_info - Add support for getting information about Keystone federation Protocols
|
||||
- openstack.cloud.routers_info - Retrieve information about one or more OpenStack routers.
|
||||
77
README.md
77
README.md
@@ -2,20 +2,77 @@
|
||||
|
||||
# Ansible Collection: openstack.cloud
|
||||
|
||||
|
||||
This repo hosts the `openstack.cloud` Ansible Collection.
|
||||
|
||||
The collection includes the Openstack modules and plugins supported by Openstack community to help the management of Openstack infrastructure.
|
||||
|
||||
## Breaking backward compatibility :warning:
|
||||
|
||||
Dear contributors and users of the Ansible OpenStack collection!
|
||||
Our codebase has been split into two separate release series:
|
||||
|
||||
* `2.x.x` releases of Ansible OpenStack collection are compatible with OpenStack SDK `1.x.x` and its release candidates
|
||||
`0.99.x` *only* (OpenStack Zed and later). Our `master` branch tracks our `2.x.x` releases.
|
||||
* `1.x.x` releases of Ansible OpenStack collection are compatible with OpenStack SDK `0.x.x` prior to `0.99.0` *only*
|
||||
(OpenStack Yoga and earlier). Our `stable/1.0.0` branch tracks our `1.x.x` releases.
|
||||
|
||||
Both branches will be developed in parallel for the time being. Patches from `master` will be backported to
|
||||
`stable/1.0.0` on a best effort basis but expect new features to be introduced in our `master` branch only.
|
||||
Contributions are welcome for both branches!
|
||||
Differences between both branches are mainly renamed and sometimes dropped module return values. We try to keep our
|
||||
module parameters backward compatible by offering aliases but e.g. the semantics of `filters` parameters in `*_info`
|
||||
modules have changed due to updates in the OpenStack SDK.
|
||||
|
||||
Our decision to break backward compatibility was not taken lightly. OpenStack SDK's first major release (`1.0.0` and its
|
||||
release candidates `0.99.x`) has streamlined and improved large parts of its codebase. For example, its Connection
|
||||
interface now consistently uses the Resource interfaces under the hood. This required breaking changes from older SDK
|
||||
releases though. The Ansible OpenStack collection is heavily based on OpenStack SDK. With OpenStack SDK becoming
|
||||
backward incompatible, so does our Ansible OpenStack collection. We simply lack the devpower to maintain a backward
|
||||
compatible interface in Ansible OpenStack collection across several SDK releases.
|
||||
|
||||
Our first `2.0.0` release is currently under development and we still have a long way to go. If you use modules of the
|
||||
Ansible OpenStack collection and want to join us in porting them to the upcoming OpenStack SDK, please contact us!
|
||||
Ping Jakob Meng <mail@jakobmeng.de> (jm1) or Rafael Castillo <rcastill@redhat.com> (rcastillo) and we will give you a
|
||||
quick introduction. We are also hanging around on `irc.oftc.net/#openstack-ansible-sig` and `irc.oftc.net/#oooq` 😎
|
||||
|
||||
We have extensive documentation on [why, what and how we are adopting and reviewing the new modules](
|
||||
https://hackmd.io/szgyWa5qSUOWw3JJBXLmOQ?view), [how to set up a working DevStack environment for hacking on the
|
||||
collection](https://hackmd.io/PI10x-iCTBuO09duvpeWgQ?view) and, most importantly, [a list of modules where we are
|
||||
coordinating our porting efforts](https://hackmd.io/7NtovjRkRn-tKraBXfz9jw?view).
|
||||
|
||||
## Installation and Usage
|
||||
|
||||
### Installing dependencies
|
||||
|
||||
For using the Openstack Cloud collection firstly you need to install `ansible` and `openstacksdk` Python modules on your Ansible controller.
|
||||
For example with pip:
|
||||
|
||||
```bash
|
||||
pip install "ansible>=2.9" "openstacksdk>=0.36,<0.99.0"
|
||||
```
|
||||
|
||||
OpenStackSDK has to be available to Ansible and to the Python interpreter on the host, where Ansible executes the module (target host).
|
||||
Please note, that under some circumstances Ansible might invoke a non-standard Python interpreter on the target host.
|
||||
Using Python version 3 is highly recommended for OpenstackSDK and strongly required from OpenstackSDK version 0.39.0.
|
||||
|
||||
---
|
||||
|
||||
#### NOTE
|
||||
|
||||
OpenstackSDK is better to be the last stable version. It should NOT be installed on Openstack nodes,
|
||||
but rather on operators host (aka "Ansible controller"). OpenstackSDK from last version supports
|
||||
operations on all Openstack cloud versions. Therefore OpenstackSDK module version doesn't have to match
|
||||
Openstack cloud version usually.
|
||||
|
||||
---
|
||||
|
||||
### Installing the Collection from Ansible Galaxy
|
||||
|
||||
Before using the Openstack Cloud collection, you need to install the collection with the `ansible-galaxy` CLI:
|
||||
|
||||
`ansible-galaxy collection install openstack.cloud`
|
||||
|
||||
You can also include it in a `requirements.yml` file and install it via `ansible-galaxy collection install -r requirements.yml` using the format:
|
||||
You can also include it in a `requirements.yml` file and install it through `ansible-galaxy collection install -r requirements.yml` using the format:
|
||||
|
||||
```yaml
|
||||
collections:
|
||||
@@ -24,7 +81,7 @@ collections:
|
||||
|
||||
### Playbooks
|
||||
|
||||
To use a module from Openstack Cloud collection, please reference the full namespace, collection name, and modules name that you want to use:
|
||||
To use a module from the Openstack Cloud collection, please reference the full namespace, collection name, and module name that you want to use:
|
||||
|
||||
```yaml
|
||||
---
|
||||
@@ -42,7 +99,7 @@ To use a module from Openstack Cloud collection, please reference the full names
|
||||
volume_size: 75
|
||||
```
|
||||
|
||||
Or you can add full namepsace and collecton name in the `collections` element:
|
||||
Or you can add the full namespace and collection name in the `collections` element:
|
||||
|
||||
```yaml
|
||||
---
|
||||
@@ -59,13 +116,21 @@ Or you can add full namepsace and collecton name in the `collections` element:
|
||||
device: /dev/vdb
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
See the collection docs at Ansible site:
|
||||
|
||||
* [openstack.cloud collection docs (version released in Ansible package)](https://docs.ansible.com/ansible/latest/collections/openstack/cloud/index.html)
|
||||
|
||||
* [openstack.cloud collection docs (devel version)](https://docs.ansible.com/ansible/devel/collections/openstack/cloud/index.html)
|
||||
|
||||
## Contributing
|
||||
|
||||
For information on contributing, please see [CONTRIBUTING](https://opendev.org/openstack/ansible-collections-openstack/src/branch/master/CONTRIBUTING.rst)
|
||||
|
||||
There are many ways in which you can participate in the project, for example:
|
||||
|
||||
- Submit bugs and feature requests, and help us verify them
|
||||
- Submit [bugs and feature requests](https://storyboard.openstack.org/#!/project/openstack/ansible-collections-openstack), and help us verify them
|
||||
- Submit and review source code changes in [Openstack Gerrit](https://review.opendev.org/#/q/project:openstack/ansible-collections-openstack)
|
||||
- Add new modules for Openstack Cloud
|
||||
|
||||
@@ -90,7 +155,7 @@ TBD
|
||||
## Communication
|
||||
|
||||
We have a dedicated Interest Group for Openstack Ansible modules.
|
||||
You can find other people interested in this in `#openstack-ansible-sig` on Freenode IRC.
|
||||
You can find other people interested in this in `#openstack-ansible-sig` on [OFTC IRC](https://www.oftc.net/).
|
||||
|
||||
## License
|
||||
|
||||
|
||||
7
bindep.txt
Normal file
7
bindep.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
# This is a cross-platform list tracking distribution packages needed by tests;
|
||||
# see https://docs.openstack.org/infra/bindep/ for additional information.
|
||||
|
||||
gcc [compile platform:centos-8 platform:rhel-8]
|
||||
python38-cryptography [platform:centos-8 platform:rhel-8]
|
||||
python38-devel [compile platform:centos-8 platform:rhel-8]
|
||||
python38-requests [platform:centos-8 platform:rhel-8]
|
||||
406
changelogs/changelog.yaml
Normal file
406
changelogs/changelog.yaml
Normal file
@@ -0,0 +1,406 @@
|
||||
ancestor: null
|
||||
releases:
|
||||
1.0.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- baremetal_node - Correct parameter name
|
||||
- coe_cluster - Retrive id/uuid correctly
|
||||
- federation_mapping - Fixup some minor nits found in followup reviews
|
||||
- inventory_openstack - Fix constructed compose
|
||||
- network - Bump minimum openstacksdk version when using os_network/dns_domain
|
||||
- role_assignment - Fix os_user_role for groups in multidomain context
|
||||
- role_assignment - Fix os_user_role issue to grant a role in a domain
|
||||
minor_changes:
|
||||
- Renaming all modules and removing "os" prefix from names.
|
||||
- baremetal_node_action - Support json type for the ironic_node config_drive
|
||||
parameter
|
||||
- config - Update os_client_config to use openstacksdk
|
||||
- host_aggregate - Add support for not 'purging' missing hosts
|
||||
- project - Add properties for os_project
|
||||
- server_action - pass imageRef to rebuild
|
||||
- subnet - Updated allocation pool checks
|
||||
release_summary: Initial release of collection.
|
||||
modules:
|
||||
- description: Add support for Keystone Identity Providers
|
||||
name: federation_idp
|
||||
namespace: ''
|
||||
- description: Add support for fetching the information about federation IDPs
|
||||
name: federation_idp_info
|
||||
namespace: ''
|
||||
- description: Add support for Keystone mappings
|
||||
name: federation_mapping
|
||||
namespace: ''
|
||||
- description: Add support for fetching the information about Keystone mappings
|
||||
name: federation_mapping_info
|
||||
namespace: ''
|
||||
- description: Add support for Keystone federation Protocols
|
||||
name: keystone_federation_protocol
|
||||
namespace: ''
|
||||
- description: Add support for getting information about Keystone federation Protocols
|
||||
name: keystone_federation_protocol_info
|
||||
namespace: ''
|
||||
- description: Retrieve information about one or more OpenStack routers.
|
||||
name: routers_info
|
||||
namespace: ''
|
||||
release_date: '2020-05-19'
|
||||
1.0.1:
|
||||
changes:
|
||||
bugfixes:
|
||||
- server_info - Fix broken server_info module and add tests
|
||||
release_summary: Bugfix for server_info
|
||||
release_date: '2020-05-22'
|
||||
1.1.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Fix non existing attribuites in SDK exception
|
||||
- security_group_rule - Don't pass tenant_id for remote group
|
||||
minor_changes:
|
||||
- A basic module subclass was introduced and a few modules moved to inherit
|
||||
from it.
|
||||
- Add more useful information from exception
|
||||
- Added pip installation option for collection.
|
||||
- Added template for generation of artibtrary module.
|
||||
- baremetal modules - Do not require ironic_url if cloud or auth.endpoint is
|
||||
provided
|
||||
- inventory_openstack - Add openstack logger and Ansible display utility
|
||||
- loadbalancer - Add support for setting the Flavor when creating a load balancer
|
||||
release_summary: Starting redesign modules and bugfixes.
|
||||
modules:
|
||||
- description: Retrieve information about Openstack volumes.
|
||||
name: volume_info
|
||||
namespace: ''
|
||||
release_date: '2020-08-17'
|
||||
1.10.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Add SDK logging option for openstack ansible collections
|
||||
- Don't use deprecated distutils from python 3.10
|
||||
- Ensure openstacksdk compatibility in inventory plugin
|
||||
- Lowered maximum OpenStack SDK version to 0.98.999 in inventory plugin
|
||||
known_issues:
|
||||
- For compatibility with OpenStack SDK >= 0.99.0 use Ansible OpenStack collection
|
||||
2.0.0 or later which is currently under development.
|
||||
- Release series 1.x.x of this collection is compatible to OpenStack SDK prior
|
||||
to 0.99.0 only.
|
||||
release_summary: Enable logging of openstacksdk activities and warn users about
|
||||
incompatible openstacksdk releases when using inventory plugin
|
||||
release_date: '2022-10-04'
|
||||
1.2.0:
|
||||
changes:
|
||||
minor_changes:
|
||||
- lb_health_monitor - Make it possible to create a health monitor to a pool
|
||||
release_summary: New volume backup modules.
|
||||
modules:
|
||||
- description: Add/Delete Openstack volumes backup.
|
||||
name: volume_backup module
|
||||
namespace: ''
|
||||
- description: Retrieve information about Openstack volume backups.
|
||||
name: volume_backup_info module
|
||||
namespace: ''
|
||||
- description: Retrieve information about Openstack volume snapshots.
|
||||
name: volume_snapshot_info module
|
||||
namespace: ''
|
||||
release_date: '2020-10-13'
|
||||
1.2.1:
|
||||
changes:
|
||||
minor_changes:
|
||||
- dns_zone - Migrating dns_zone from AnsibleModule to OpenStackModule
|
||||
- dns_zone, recordset - Enable update for recordset and add tests for dns and
|
||||
recordset module
|
||||
- endpoint - Do not fail when endpoint state is absent
|
||||
- ironic - Refactor ironic authentication into a new module_utils module
|
||||
- loadbalancer - Refactor loadbalancer module
|
||||
- network - Migrating network from AnsibleModule to OpenStackModule
|
||||
- networks_info - Migrating networks_info from AnsibleModule to OpenStackModule
|
||||
- openstack - Add galaxy.yml to support install from git
|
||||
- openstack - Fix docs-args mismatch in modules
|
||||
- openstack - OpenStackModule Support defining a minimum version of the SDK
|
||||
- router - Migrating routers from AnsibleModule to OpenStackModule
|
||||
- routers_info - Added deprecated_names for router_info module
|
||||
- routers_info - Migrating routers_info from AnsibleModule to OpenStackModule
|
||||
- security_group.py - Migrating security_group from AnsibleModule to OpenStackModule
|
||||
- security_group_rule - Refactor TCP/UDP port check
|
||||
- server.py - Improve "server" module with OpenstackModule class
|
||||
- server_volume - Migrating server_volume from AnsibleModule to OpenStackModule
|
||||
- subnet - Fix subnets update and idempotency
|
||||
- subnet - Migrating subnet module from AnsibleModule to OpenStackModule
|
||||
- subnets_info - Migrating subnets_info from AnsibleModule to OpenStackModule
|
||||
- volume.py - Migrating volume from AnsibleModule to OpenStackModule
|
||||
- volume_info - Fix volume_info arguments for SDK 0.19
|
||||
release_summary: Porting modules to new OpenstackModule class and fixes.
|
||||
release_date: '2021-01-03'
|
||||
1.3.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- port - Fixed check for None in os_port
|
||||
- project - Fix setting custom property on os_project
|
||||
- security_group_rule - Remove protocols choice in security rules
|
||||
- volume_info - Fix volume_info result for SDK < 0.19
|
||||
minor_changes:
|
||||
- Fix some typos in readme
|
||||
- Guidelines Fix links and formatting
|
||||
- baremetal_node - Add support for new features
|
||||
- baremetal_node - ironic deprecate sub-options of driver_info
|
||||
- baremetal_node - ironic stop putting meaningless values to properties
|
||||
- image_info - Migrating image_info module from AnsibleModule to OpenStackModule
|
||||
- recordset - Update recordset docu
|
||||
- server - Allow description field to be set with os_server
|
||||
- server_action - Added shelve and unshelve as new server actions
|
||||
release_summary: New modules and bugfixes.
|
||||
modules:
|
||||
- description: Retrieve information about Openstack Identity roles.
|
||||
name: identity_role_info
|
||||
namespace: ''
|
||||
- description: Retrieve information about Openstack key pairs.
|
||||
name: keypair_info
|
||||
namespace: ''
|
||||
- description: Retrieve information about Openstack Security Groups.
|
||||
name: security_group_info
|
||||
namespace: ''
|
||||
- description: Retrieve information about Openstack Security Group rules.
|
||||
name: security_group_rule_info
|
||||
namespace: ''
|
||||
- description: Retrieve information about Openstack Heat stacks.
|
||||
name: stack_info
|
||||
namespace: ''
|
||||
release_date: '2021-02-16'
|
||||
1.4.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Add Octavia job for testing Load Balancer
|
||||
- Add binding profile to port module
|
||||
- Add execution environment metadata
|
||||
- Fix CI for latest ansible-test with no_log
|
||||
- Fix issues with newest ansible-test 2.11
|
||||
- Prepare for Ansible 2.11 tests
|
||||
- add option to exclude legacy groups
|
||||
- security_group_rule add support ipv6-icmp
|
||||
release_summary: New object_container module and bugfixes.
|
||||
modules:
|
||||
- description: Manage Swift container
|
||||
name: object_container
|
||||
namespace: ''
|
||||
release_date: '2021-04-08'
|
||||
1.5.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Update checks for validate_certs in openstack_cloud_from_module
|
||||
- compute_flavor - Fix the idempotent of compute_flavor module
|
||||
- host_aggregate - Fix host_aggregate to tolerate aggregate.hosts being None
|
||||
- inventory/openstack - Fix inventory plugin on Ansible 2.11
|
||||
- port - fix update on empty list of allowed address pairs
|
||||
- setup.cfg Replace dashes with underscores
|
||||
- subnet - Only apply necessary changes to subnets
|
||||
- volume - Fail if referenced source image for a new volume does not exist
|
||||
minor_changes:
|
||||
- Add bindep.txt for ansible-builder
|
||||
- Add check_mode attribute to OpenstackModule
|
||||
- Migrating image module from AnsibleModule to OpenStackModule
|
||||
- Switch KeystoneFederationProtocolInfo module to OpenStackModule
|
||||
- Switch ProjectAccess module to OpenStackModule
|
||||
- Switch Quota module to OpenStackModule
|
||||
- Switch Recordset module to OpenStackModule
|
||||
- Switch ServerGroup module to OpenStackModule
|
||||
- Switch ServerMetadata module to OpenStackModule
|
||||
- Switch Snapshot module to OpenStackModule
|
||||
- Switch Stack module to OpenStackModule
|
||||
- Switch auth module to OpenStackModule
|
||||
- Switch catalog_service module to OpenStackModule
|
||||
- Switch coe_cluster module to OpenStackModule
|
||||
- Switch coe_cluster_template module to OpenStackModule
|
||||
- Switch endpoint module to OpenStackModule
|
||||
- Switch federation_idp module to OpenStackModule
|
||||
- Switch federation_idp_info module to OpenStackModule
|
||||
- Switch federation_mapping module to OpenStackModule
|
||||
- Switch federation_mapping_info module to OpenStackModule
|
||||
- Switch federation_protocol module to OpenStackModule
|
||||
- Switch flavor module to OpenStackModule
|
||||
- Switch flavor_info module to OpenStackModule
|
||||
- Switch floating_ip module to OpenStackModule
|
||||
- Switch group_assignment module to OpenStackModule
|
||||
- Switch hostaggregate module to OpenStackModule
|
||||
- Switch identity_domain module to OpenStackModule
|
||||
- Switch identity_domain_info module to OpenStackModule
|
||||
- Switch identity_group module to OpenStackModule
|
||||
- Switch identity_group_info module to OpenStackModule
|
||||
- Switch identity_role module to OpenStackModule
|
||||
- Switch identity_user module to OpenStackModule
|
||||
- Switch lb_listener module to OpenStackModule
|
||||
- Switch lb_member module to OpenStackModule
|
||||
- Switch lb_pool module to OpenStackModule
|
||||
- Switch object module to OpenStackModule
|
||||
- Switch port module to OpenStackModule
|
||||
- Switch port_info module to OpenStackModule
|
||||
- Switch project and project_info module to OpenStackModule
|
||||
- Switch role_assignment module to OpenStackModule
|
||||
- Switch user_info module to OpenStackModule
|
||||
- image - Add support to setting image tags
|
||||
release_summary: New modules for DNS and FIPs and bugfixes.
|
||||
modules:
|
||||
- description: Create or delete address scopes from OpenStack
|
||||
name: address_scope
|
||||
namespace: ''
|
||||
- description: Getting information about dns zones
|
||||
name: dns_zone_info
|
||||
namespace: ''
|
||||
- description: Get information about floating ips
|
||||
name: floating_ip_info
|
||||
namespace: ''
|
||||
release_date: '2021-06-23'
|
||||
1.5.1:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Add mandatory requires_ansible version to metadata
|
||||
- Add protocol listener octavia
|
||||
- Add support check mode for all info modules
|
||||
- Allow to attach multiple floating ips to a server
|
||||
- Only add or remove router interfaces when needed
|
||||
- Wait for pool to be active and online
|
||||
minor_changes:
|
||||
- Changed minversion in tox to 3.18.0
|
||||
- Update IRC server in README
|
||||
release_summary: Bugfixes for networking modules
|
||||
release_date: '2021-09-02'
|
||||
1.5.2:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Add client and member listener timeouts for persistence (Ex. SSH)
|
||||
- Added missing warn() used in cloud.openstack.quota
|
||||
- Fix issue with same host and group names
|
||||
- Flavor properties are not deleted on changes and id will stay
|
||||
minor_changes:
|
||||
- Add documentation links to README.md
|
||||
- Don't run functional jobs on galaxy.yml change
|
||||
- Move CI to use Ansible 2.12 version as main
|
||||
release_summary: Bugfixes
|
||||
release_date: '2021-11-09'
|
||||
1.5.3:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Don't require allowed_address_pairs for port
|
||||
- server_volume - check specified server is found
|
||||
release_summary: Bugfixes
|
||||
release_date: '2021-11-11'
|
||||
1.6.0:
|
||||
changes:
|
||||
minor_changes:
|
||||
- quota - Adds metadata_items parameter
|
||||
release_summary: New modules for RBAC and Nova services
|
||||
modules:
|
||||
- description: Retrieve information about one or more OpenStack compute services
|
||||
name: compute_service_info
|
||||
namespace: ''
|
||||
- description: Fetch Neutron policies.
|
||||
name: neutron_rbac_policies_info
|
||||
namespace: ''
|
||||
- description: Create or delete a Neutron policy to apply a RBAC rule against
|
||||
an object.
|
||||
name: neutron_rbac_policy
|
||||
namespace: ''
|
||||
release_date: '2022-01-13'
|
||||
1.7.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- identity_user_info - Fix identity user lookup with a domain
|
||||
- keystone_domain - Move identity domain to use proxy layer
|
||||
minor_changes:
|
||||
- openstack_inventory - Adds use_name variable
|
||||
- port - Add dns_[name,domain] to the port module
|
||||
- project - Remove project properties tests and support
|
||||
release_summary: New modules for Ironic and bugfixes
|
||||
modules:
|
||||
- description: Retrieve information about Bare Metal nodes from OpenStack an object.
|
||||
name: baremetal_node_info
|
||||
namespace: ''
|
||||
- description: Create, Update, Remove ironic ports from OpenStack
|
||||
name: baremetal_port
|
||||
namespace: ''
|
||||
- description: Retrieve information about Bare Metal ports from OpenStack an object.
|
||||
name: baremetal_port_info
|
||||
namespace: ''
|
||||
release_date: '2022-02-15'
|
||||
1.7.1:
|
||||
changes:
|
||||
bugfixes:
|
||||
- openstack_inventory - Fix documentation
|
||||
- quota - Fix description of volumes_types parameter
|
||||
minor_changes:
|
||||
- lb_member - Add monitor_[address,port] parameter
|
||||
release_summary: Bugfixes
|
||||
release_date: '2022-03-08'
|
||||
1.7.2:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Fix collection guidelines
|
||||
release_summary: Bugfixes
|
||||
release_date: '2022-03-10'
|
||||
1.8.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Add 'all_projects' to server_action module
|
||||
- Add subnet pool module
|
||||
- Bumped minimum required OpenStack SDK release to SDK 0.36.0 (Train)
|
||||
- Changed compute_flavor_info module to use OpenStack SDK's proxy layer
|
||||
- Dropped deprecated return values in floating_ip_info and assert remaining
|
||||
fields
|
||||
- Fix ansible-lint issues for the newest version
|
||||
- Fix assertion after stack deletion
|
||||
- Handle aggregate host list set to None
|
||||
- Reenabled check-import.sh which tests imports to Ansible Galaxy
|
||||
- Remove old, unsupported parameters from documentation in image_info module
|
||||
- Router - Remove unneeded 'filter' parameter
|
||||
- Updated return value docs of compute_service_info module
|
||||
release_summary: Subnet pool module and bugfixes
|
||||
modules:
|
||||
- description: Create or Delete subnet pools from OpenStack.
|
||||
name: subnet_pool
|
||||
namespace: ''
|
||||
release_date: '2022-04-08'
|
||||
1.9.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Added support for specifying a maximum version of the OpenStack SDK
|
||||
- Constrain filters in compute_service_info to SDK >= 0.53.0
|
||||
- Drop username from return values of identity_user_info
|
||||
- Fix logic in routers_info
|
||||
- Fixed return value disable{d,s}_reason in compute_service_info module
|
||||
- Fixed return values in compute_service_info module again
|
||||
- Follow up to bump of minimum required OpenStack SDK release to SDK 0.36.0
|
||||
(Train)
|
||||
- Lowered maximum OpenStack SDK version to 0.98.999
|
||||
- Move dns zone info to use proxy layer
|
||||
- Refactored catalog_service module
|
||||
- Refactored endpoint module
|
||||
- Refactored host_aggregate module
|
||||
- Refactored identity_domain_info module
|
||||
- Refactored identity_group_info module
|
||||
- Refactored identity_role module
|
||||
- Refactored identity_role_info module
|
||||
- Refactored identity_user module
|
||||
- Refactored identity_user_info module
|
||||
- Refactored image_info module
|
||||
- Refactored keypair_info module
|
||||
- Refactored recordset module
|
||||
- Refactored role_assignment module
|
||||
- Set owner in image module
|
||||
- Support description in sg-rule creation
|
||||
- Warn users about us breaking backward compatibility
|
||||
known_issues:
|
||||
- For compatibility with OpenStack SDK >= 0.99.0 use Ansible OpenStack collection
|
||||
2.0.0 or later which is currently under development.
|
||||
- Release series 1.x.x of this collection is compatible to OpenStack SDK prior
|
||||
to 0.99.0 only.
|
||||
release_summary: This release will enforce openstacksdk<0.99.0, has a dozen
|
||||
modules refactored and several bugs fixed.
|
||||
release_date: '2022-08-25'
|
||||
1.9.1:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Do not remove trailing spaces when reading public key in keypair module
|
||||
known_issues:
|
||||
- For compatibility with OpenStack SDK >= 0.99.0 use Ansible OpenStack collection
|
||||
2.0.0 or later which is currently under development.
|
||||
- Release series 1.x.x of this collection is compatible to OpenStack SDK prior
|
||||
to 0.99.0 only.
|
||||
release_summary: Bugfix in keypair module
|
||||
release_date: '2022-09-08'
|
||||
31
changelogs/config.yaml
Normal file
31
changelogs/config.yaml
Normal file
@@ -0,0 +1,31 @@
|
||||
changelog_filename_template: ../CHANGELOG.rst
|
||||
changelog_filename_version_depth: 0
|
||||
changes_file: changelog.yaml
|
||||
changes_format: combined
|
||||
ignore_other_fragment_extensions: true
|
||||
keep_fragments: false
|
||||
mention_ancestor: true
|
||||
new_plugins_after_name: removed_features
|
||||
notesdir: fragments
|
||||
prelude_section_name: release_summary
|
||||
prelude_section_title: Release Summary
|
||||
sections:
|
||||
- - major_changes
|
||||
- Major Changes
|
||||
- - minor_changes
|
||||
- Minor Changes
|
||||
- - breaking_changes
|
||||
- Breaking Changes / Porting Guide
|
||||
- - deprecated_features
|
||||
- Deprecated Features
|
||||
- - removed_features
|
||||
- Removed Features (previously deprecated)
|
||||
- - security_fixes
|
||||
- Security Fixes
|
||||
- - bugfixes
|
||||
- Bugfixes
|
||||
- - known_issues
|
||||
- Known Issues
|
||||
title: Openstack Cloud Ansilbe modules
|
||||
trivial_section_name: trivial
|
||||
use_fqcn: true
|
||||
@@ -1,3 +0,0 @@
|
||||
bugfixes:
|
||||
- Bump the minimum openstacksdk version to 0.18.0 when os_network
|
||||
uses the port_security_enabled or mtu arguments.
|
||||
@@ -1,3 +0,0 @@
|
||||
bugfixes:
|
||||
- Bump the minimum openstacksdk version to 0.29.0 when os_network
|
||||
uses the dns_domain argument.
|
||||
@@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- os_coe_cluster: Retrieve the correct id/uuid depending on whether it is a create/get request.
|
||||
@@ -1,2 +0,0 @@
|
||||
minor_changes:
|
||||
- Moved Openstack inventory script from Ansible community.general to openstack collection.
|
||||
6
ci/playbooks/get_amphora_tarball.yaml
Normal file
6
ci/playbooks/get_amphora_tarball.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
- hosts: all
|
||||
tasks:
|
||||
- name: Download amphora tarball
|
||||
get_url:
|
||||
url: "https://tarballs.openstack.org/octavia/test-images/test-only-amphora-x64-haproxy-ubuntu-bionic.qcow2"
|
||||
dest: /tmp/test-only-amphora-x64-haproxy-ubuntu-bionic.qcow2
|
||||
8
ci/playbooks/postlog.yaml
Normal file
8
ci/playbooks/postlog.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
- hosts: all
|
||||
tasks:
|
||||
- zuul_return:
|
||||
data:
|
||||
zuul:
|
||||
artifacts:
|
||||
- name: Test log
|
||||
url: controller/logs/test_output_log.txt
|
||||
84
ci/publish/publish_collection.yml
Normal file
84
ci/publish/publish_collection.yml
Normal file
@@ -0,0 +1,84 @@
|
||||
---
|
||||
- hosts: all
|
||||
vars:
|
||||
collection_path: "{{ ansible_user_dir }}/{{ zuul.project.src_dir }}"
|
||||
build_collection_path: /tmp/collection_built/
|
||||
ansible_galaxy_path: "~/.local/bin/ansible-galaxy"
|
||||
|
||||
tasks:
|
||||
|
||||
- name: Include role for pip
|
||||
include_role:
|
||||
name: ensure-pip
|
||||
|
||||
- name: Install ansible
|
||||
pip:
|
||||
name: ansible-core<2.12
|
||||
|
||||
- name: Discover tag version
|
||||
set_fact:
|
||||
version_tag: "{{ zuul.tag|default('no_version', true) }}"
|
||||
|
||||
- name: Fail if no tag version found
|
||||
fail:
|
||||
msg: "No tag was found in Zuul vars!"
|
||||
when: version_tag == 'no_version'
|
||||
|
||||
- name: Create a directory for collection
|
||||
file:
|
||||
state: "{{ item }}"
|
||||
path: "{{ build_collection_path }}"
|
||||
loop:
|
||||
- absent
|
||||
- directory
|
||||
|
||||
- name: Set galaxy.yml for right version from tag
|
||||
lineinfile:
|
||||
path: '{{ collection_path }}/galaxy.yml'
|
||||
regexp: '^version:.*'
|
||||
line: 'version: {{ version_tag }}'
|
||||
|
||||
- name: Build collection
|
||||
command: "{{ ansible_galaxy_path }} collection build --output-path {{ build_collection_path }} --force"
|
||||
args:
|
||||
chdir: "{{ collection_path }}"
|
||||
|
||||
- name: Publish content to Ansible Galaxy
|
||||
block:
|
||||
- name: Create ansible.cfg configuration file tempfile
|
||||
tempfile:
|
||||
state: file
|
||||
suffix: .cfg
|
||||
register: _ansiblecfg_tmp
|
||||
|
||||
- name: Create ansible.cfg configuration file
|
||||
copy:
|
||||
dest: "{{ _ansiblecfg_tmp.path }}"
|
||||
mode: 0600
|
||||
content: |
|
||||
[galaxy]
|
||||
server_list = release_galaxy
|
||||
|
||||
[galaxy_server.release_galaxy]
|
||||
url = {{ ansible_galaxy_info.url }}
|
||||
token = {{ ansible_galaxy_info.token }}
|
||||
|
||||
- name: Get content of galaxy.yml
|
||||
slurp:
|
||||
src: "{{ collection_path }}/galaxy.yml"
|
||||
register: galaxy_vars
|
||||
|
||||
- name: Parse yaml into variable
|
||||
set_fact:
|
||||
galaxy_yaml: "{{ galaxy_vars['content'] | b64decode | from_yaml }}"
|
||||
|
||||
- name: Publish collection to Ansible Galaxy / Automation Hub
|
||||
environment:
|
||||
ANSIBLE_CONFIG: "{{ _ansiblecfg_tmp.path }}"
|
||||
shell: >-
|
||||
{{ ansible_galaxy_path }} collection publish -vvv
|
||||
{{ build_collection_path }}/{{ galaxy_yaml.namespace }}-{{ galaxy_yaml.name }}-{{ version_tag }}.tar.gz
|
||||
|
||||
always:
|
||||
- name: Shred ansible-galaxy credentials
|
||||
command: "shred {{ _ansiblecfg_tmp.path }}"
|
||||
1
ci/roles/address_scope/defaults/main.yml
Normal file
1
ci/roles/address_scope/defaults/main.yml
Normal file
@@ -0,0 +1 @@
|
||||
address_scope_name: "adrdess_scope"
|
||||
40
ci/roles/address_scope/tasks/main.yml
Normal file
40
ci/roles/address_scope/tasks/main.yml
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
- name: Create address_scope
|
||||
openstack.cloud.address_scope:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ address_scope_name }}"
|
||||
shared: False
|
||||
ip_version: "4"
|
||||
register: create_address_scope
|
||||
|
||||
- name: Verify address scope
|
||||
assert:
|
||||
that:
|
||||
- create_address_scope is successful
|
||||
- create_address_scope is changed
|
||||
- create_address_scope.address_scope.name == address_scope_name
|
||||
- create_address_scope.address_scope.is_shared == False
|
||||
- create_address_scope.address_scope.ip_version == 4
|
||||
|
||||
- name: Update address scope
|
||||
openstack.cloud.address_scope:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ address_scope_name }}"
|
||||
shared: True
|
||||
ip_version: "4"
|
||||
register: update_address_scope
|
||||
|
||||
- name: Verify updated IPv4 address scope
|
||||
assert:
|
||||
that:
|
||||
- update_address_scope is successful
|
||||
- update_address_scope is changed
|
||||
- update_address_scope.address_scope.name == address_scope_name
|
||||
- update_address_scope.address_scope.is_shared == True
|
||||
- update_address_scope.address_scope.ip_version == 4
|
||||
|
||||
- name: Delete created address scope
|
||||
openstack.cloud.address_scope:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ address_scope_name }}"
|
||||
state: absent
|
||||
94
ci/roles/catalog_service/tasks/main.yml
Normal file
94
ci/roles/catalog_service/tasks/main.yml
Normal file
@@ -0,0 +1,94 @@
|
||||
---
|
||||
- name: Delete service test
|
||||
openstack.cloud.catalog_service:
|
||||
cloud: "{{ cloud }}"
|
||||
service_type: test
|
||||
name: test
|
||||
state: absent
|
||||
register: service_delete
|
||||
|
||||
- name: Assert changed is set to false
|
||||
assert:
|
||||
that:
|
||||
- not service_delete.changed
|
||||
|
||||
- name: Create a service for test
|
||||
openstack.cloud.catalog_service:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "test_service"
|
||||
state: present
|
||||
service_type: test_type
|
||||
description: "Test service"
|
||||
register: service_test
|
||||
|
||||
- name: Verify returned values
|
||||
assert:
|
||||
that:
|
||||
- item in service_test.service
|
||||
loop:
|
||||
- description
|
||||
- id
|
||||
- enabled
|
||||
- name
|
||||
- service_type
|
||||
- type
|
||||
|
||||
- name: Check if the service test was created successfully
|
||||
openstack.cloud.catalog_service:
|
||||
cloud: "{{ cloud }}"
|
||||
service_type: test
|
||||
name: test
|
||||
register: service_created
|
||||
|
||||
- name: Verify returned values
|
||||
assert:
|
||||
that:
|
||||
- item in service_created.service
|
||||
loop:
|
||||
- description
|
||||
- id
|
||||
- enabled
|
||||
- name
|
||||
- type
|
||||
- service_type
|
||||
|
||||
- name: Update service test
|
||||
openstack.cloud.catalog_service:
|
||||
cloud: "{{ cloud }}"
|
||||
service_type: test
|
||||
description: "A new description"
|
||||
is_enabled: False
|
||||
name: test
|
||||
register: service_test
|
||||
|
||||
- name: Check if description and enabled were updated
|
||||
assert:
|
||||
that:
|
||||
- service_test.service.description == "A new description"
|
||||
- not (service_test.service.enabled|bool)
|
||||
|
||||
- name: Delete service test
|
||||
openstack.cloud.catalog_service:
|
||||
cloud: "{{ cloud }}"
|
||||
service_type: test
|
||||
name: test
|
||||
state: absent
|
||||
register: service_deleted
|
||||
|
||||
- name: Verify if service was deleted
|
||||
assert:
|
||||
that:
|
||||
- service_deleted.changed
|
||||
|
||||
- name: Delete service test again
|
||||
openstack.cloud.catalog_service:
|
||||
cloud: "{{ cloud }}"
|
||||
service_type: test
|
||||
name: test
|
||||
state: absent
|
||||
register: service_deleted
|
||||
|
||||
- name: Assert changed is set to false
|
||||
assert:
|
||||
that:
|
||||
- not service_deleted.changed
|
||||
33
ci/roles/compute_flavor_info/tasks/main.yml
Normal file
33
ci/roles/compute_flavor_info/tasks/main.yml
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
- name: List flavors
|
||||
openstack.cloud.compute_flavor_info:
|
||||
cloud: "{{ cloud }}"
|
||||
|
||||
- name: List flavors with filter
|
||||
openstack.cloud.compute_flavor_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "m1.tiny"
|
||||
register: flavor_name
|
||||
|
||||
- name: Check output of list flavors with filter
|
||||
assert:
|
||||
that:
|
||||
- flavor_name.openstack_flavors | length == 1
|
||||
|
||||
- name: Assert fields on SDK 0.*
|
||||
when: sdk_version is version(1.0, '<')
|
||||
assert:
|
||||
that:
|
||||
- '["name", "description", "disk", "is_public", "ram",
|
||||
"vcpus", "swap", "ephemeral", "is_disabled", "rxtx_factor", "id",
|
||||
"extra_specs"] | difference(flavor_name.openstack_flavors.0.keys())
|
||||
| length == 0'
|
||||
|
||||
- name: Assert fields on SDK 1.*
|
||||
when: sdk_version is version(1.0, '>=')
|
||||
assert:
|
||||
that:
|
||||
- '["name", "original_name", "description", "disk", "is_public", "ram",
|
||||
"vcpus", "swap", "ephemeral", "is_disabled", "rxtx_factor", "id",
|
||||
"extra_specs"] | difference(flavor_name.openstack_flavors.0.keys())
|
||||
| length == 0'
|
||||
4
ci/roles/dns/defaults/main.yml
Normal file
4
ci/roles/dns/defaults/main.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
dns_zone_name: test.dns.zone.
|
||||
recordset_name: testrecordset.test.dns.zone.
|
||||
records: ['10.0.0.0']
|
||||
updated_records: ['10.1.1.1']
|
||||
32
ci/roles/dns/tasks/main.yml
Normal file
32
ci/roles/dns/tasks/main.yml
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
- name: Create dns zone
|
||||
openstack.cloud.dns_zone:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ dns_zone_name }}"
|
||||
zone_type: "primary"
|
||||
email: test@example.net
|
||||
register: dns_zone
|
||||
|
||||
- debug: var=dns_zone
|
||||
|
||||
- name: Update dns zone
|
||||
openstack.cloud.dns_zone:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ dns_zone.zone.name }}"
|
||||
description: "New descirption"
|
||||
register: updated_dns_zone
|
||||
|
||||
- debug: var=updated_dns_zone
|
||||
|
||||
- name: Delete dns zone
|
||||
openstack.cloud.dns_zone:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ updated_dns_zone.zone.name }}"
|
||||
state: absent
|
||||
register: deleted_dns_zone
|
||||
|
||||
- name: Verify dns zone
|
||||
assert:
|
||||
that:
|
||||
- deleted_dns_zone is successful
|
||||
- deleted_dns_zone is changed
|
||||
49
ci/roles/dns_zone_info/tasks/main.yml
Normal file
49
ci/roles/dns_zone_info/tasks/main.yml
Normal file
@@ -0,0 +1,49 @@
|
||||
---
|
||||
- name: Set random prefix
|
||||
set_fact:
|
||||
prefix: "{{ 99999999 | random | to_uuid | hash('md5') }}"
|
||||
|
||||
- name: Create dns zone
|
||||
openstack.cloud.dns_zone:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ (prefix + '.test.zone.') }}"
|
||||
email: test@example.net
|
||||
|
||||
- name: Getting info about dns zones
|
||||
openstack.cloud.dns_zone_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: zones
|
||||
|
||||
- name: assert result
|
||||
assert:
|
||||
that:
|
||||
- zones is success
|
||||
- zones is not changed
|
||||
- zones | length > 0
|
||||
|
||||
- name: Getting info about created zone
|
||||
openstack.cloud.dns_zone_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ (prefix + '.test.zone.') }}"
|
||||
register: zone
|
||||
|
||||
- name: assert result
|
||||
assert:
|
||||
that:
|
||||
- zone is success
|
||||
- zone is not changed
|
||||
- zone.zones | length == 1
|
||||
|
||||
- name: Assert keys exist
|
||||
assert:
|
||||
that:
|
||||
- '["action", "attributes", "created_at", "description", "email",
|
||||
"links", "masters", "name", "pool_id", "project_id", "serial",
|
||||
"status", "ttl", "type", "updated_at", "id"] |
|
||||
difference(zone.zones.0.keys()) | length == 0'
|
||||
|
||||
- name: Drop created dns zone
|
||||
openstack.cloud.dns_zone:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ (prefix + '.test.zone.') }}"
|
||||
state: absent
|
||||
65
ci/roles/endpoint/tasks/main.yml
Normal file
65
ci/roles/endpoint/tasks/main.yml
Normal file
@@ -0,0 +1,65 @@
|
||||
---
|
||||
- name: Create a service for compute
|
||||
openstack.cloud.endpoint:
|
||||
cloud: "{{ cloud }}"
|
||||
service: nova
|
||||
endpoint_interface: internal
|
||||
url: http://controller:9292
|
||||
region: RegionOne
|
||||
state: present
|
||||
register: endpoint_test
|
||||
|
||||
- name: Ensure service was created
|
||||
assert:
|
||||
that:
|
||||
- endpoint_test.endpoint.id is defined
|
||||
|
||||
- name: Ensure service have the proper endpoint
|
||||
assert:
|
||||
that:
|
||||
- endpoint_test.endpoint.url == "http://controller:9292"
|
||||
|
||||
- name: Create service for compute again
|
||||
openstack.cloud.endpoint:
|
||||
cloud: "{{ cloud }}"
|
||||
service: nova
|
||||
endpoint_interface: internal
|
||||
url: http://controller:9292
|
||||
region: RegionOne
|
||||
state: present
|
||||
register: endpoint_again
|
||||
|
||||
- name: Ensure changed is false
|
||||
assert:
|
||||
that:
|
||||
- not endpoint_again.changed
|
||||
|
||||
- name: Update endpoint url
|
||||
openstack.cloud.endpoint:
|
||||
cloud: "{{ cloud }}"
|
||||
service: nova
|
||||
endpoint_interface: internal
|
||||
url: http://controller:9393
|
||||
region: RegionOne
|
||||
state: present
|
||||
register: endpoint_updated
|
||||
|
||||
- name: Ensure endpoint was updated
|
||||
assert:
|
||||
that:
|
||||
- endpoint_updated.endpoint.url == "http://controller:9393"
|
||||
|
||||
- name: Delete endpoint
|
||||
openstack.cloud.endpoint:
|
||||
cloud: "{{ cloud }}"
|
||||
service: nova
|
||||
endpoint_interface: internal
|
||||
url: http://controller:9393
|
||||
region: RegionOne
|
||||
state: absent
|
||||
register: endpoint_deleted
|
||||
|
||||
- name: Ensure endpoint was deleted
|
||||
assert:
|
||||
that:
|
||||
- endpoint_deleted.changed
|
||||
466
ci/roles/floating_ip/tasks/main.yml
Normal file
466
ci/roles/floating_ip/tasks/main.yml
Normal file
@@ -0,0 +1,466 @@
|
||||
---
|
||||
# Prepare environment
|
||||
- name: Gather information about public network
|
||||
openstack.cloud.networks_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: public
|
||||
register: public_network
|
||||
|
||||
- name: Assert that public network exists
|
||||
assert:
|
||||
that: public_network.openstack_networks|length == 1
|
||||
|
||||
- name: Create external network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_external
|
||||
external: true
|
||||
|
||||
- name: Create external subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
network_name: ansible_external
|
||||
name: ansible_external_subnet
|
||||
cidr: 10.6.6.0/24
|
||||
|
||||
- name: Create external port 1
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_external_port1
|
||||
network: ansible_external
|
||||
fixed_ips:
|
||||
- ip_address: 10.6.6.50
|
||||
|
||||
- name: Create external port 2
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_external_port2
|
||||
network: ansible_external
|
||||
fixed_ips:
|
||||
- ip_address: 10.6.6.51
|
||||
|
||||
- name: Create internal network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_internal
|
||||
external: false
|
||||
|
||||
- name: Create internal subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
network_name: ansible_internal
|
||||
name: ansible_internal_subnet
|
||||
cidr: 10.7.7.0/24
|
||||
|
||||
- name: Create internal port 1
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_internal_port1
|
||||
network: ansible_internal
|
||||
fixed_ips:
|
||||
- ip_address: 10.7.7.100
|
||||
|
||||
- name: Create internal port 2
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_internal_port2
|
||||
network: ansible_internal
|
||||
fixed_ips:
|
||||
- ip_address: 10.7.7.101
|
||||
|
||||
- name: Create internal port 3
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_internal_port3
|
||||
network: ansible_internal
|
||||
fixed_ips:
|
||||
- ip_address: 10.7.7.102
|
||||
|
||||
- name: Create router 1
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_router1
|
||||
network: ansible_external
|
||||
external_fixed_ips:
|
||||
- subnet: ansible_external_subnet
|
||||
ip: 10.6.6.10
|
||||
interfaces:
|
||||
- net: ansible_internal
|
||||
subnet: ansible_internal_subnet
|
||||
portip: 10.7.7.1
|
||||
|
||||
# Router 2 is required for the simplest, first test that assigns a new floating IP to server
|
||||
# from first available external network or nova pool which is DevStack's public network
|
||||
- name: Create router 2
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_router2
|
||||
network: public
|
||||
interfaces:
|
||||
- net: ansible_internal
|
||||
subnet: ansible_internal_subnet
|
||||
portip: 10.7.7.10
|
||||
|
||||
- name: Get all floating ips
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: fips
|
||||
|
||||
- name: Check if public network has any floating ips
|
||||
set_fact:
|
||||
public_network_had_fips: "{{ fips.floating_ips|
|
||||
selectattr('floating_network_id', '==', public_network.openstack_networks.0.id)|
|
||||
list|length > 0 }}"
|
||||
|
||||
# TODO: Replace with appropriate Ansible module once available
|
||||
- name: Create a floating ip on public network (required for simplest, first floating ip test)
|
||||
command: openstack --os-cloud={{ cloud }} floating ip create public
|
||||
when: not public_network_had_fips
|
||||
|
||||
# TODO: Replace with appropriate Ansible module once available
|
||||
- name: Create floating ip 1 on external network
|
||||
command: >
|
||||
openstack --os-cloud={{ cloud }} floating ip create
|
||||
--subnet ansible_external_subnet
|
||||
--floating-ip-address 10.6.6.150
|
||||
ansible_external
|
||||
when: fips.floating_ips|length == 0 or
|
||||
"10.6.6.150" not in fips.floating_ips|map(attribute="floating_ip_address")|list
|
||||
|
||||
- name: Create server with one nic
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_server1
|
||||
image: "{{ image }}"
|
||||
flavor: m1.tiny
|
||||
nics:
|
||||
# one nic only else simple, first floating ip test does not work
|
||||
- port-name: ansible_internal_port1
|
||||
auto_ip: false
|
||||
wait: true
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: ansible_server1
|
||||
register: info
|
||||
|
||||
- name: Assert one internal port and no floating ips on server 1
|
||||
# If this assertion fails because server has an public ipv4 address (public_v4) then make sure
|
||||
# that no floating ip on public network is associated with "10.7.7.100" before running this role
|
||||
assert:
|
||||
that:
|
||||
- info.openstack_servers|length == 1
|
||||
- info.openstack_servers.0.public_v4|length == 0
|
||||
- info.openstack_servers.0.public_v6|length == 0
|
||||
- info.openstack_servers.0.addresses.ansible_internal|length == 1
|
||||
- info.openstack_servers.0.addresses.ansible_internal|map(attribute="addr")|sort|list == ["10.7.7.100"]
|
||||
|
||||
- name: Create server with two nics
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_server2
|
||||
image: "{{ image }}"
|
||||
flavor: m1.tiny
|
||||
nics:
|
||||
- port-name: ansible_internal_port2
|
||||
- port-name: ansible_internal_port3
|
||||
auto_ip: false
|
||||
wait: true
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: ansible_server2
|
||||
register: info
|
||||
|
||||
- name: Assert two internal ports and no floating ips on server 2
|
||||
assert:
|
||||
that:
|
||||
- info.openstack_servers|length == 1
|
||||
- info.openstack_servers.0.public_v4|length == 0
|
||||
- info.openstack_servers.0.public_v6|length == 0
|
||||
- info.openstack_servers.0.addresses.ansible_internal|length == 2
|
||||
- info.openstack_servers.0.addresses.ansible_internal|map(attribute="addr")|sort|list ==
|
||||
["10.7.7.101", "10.7.7.102"]
|
||||
|
||||
# Tests
|
||||
- name: Assign new floating IP to server from first available external network or nova pool
|
||||
openstack.cloud.floating_ip:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
server: ansible_server1
|
||||
wait: true
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: ansible_server1
|
||||
register: info
|
||||
|
||||
- name: Assert one internal port and one floating ip on server 1
|
||||
assert:
|
||||
that:
|
||||
- info.openstack_servers.0.addresses.ansible_internal|length == 2
|
||||
- info.openstack_servers.0.addresses.ansible_internal|map(attribute="OS-EXT-IPS:type")|sort|list ==
|
||||
["fixed", "floating"]
|
||||
|
||||
- name: Detach floating IP from server
|
||||
openstack.cloud.floating_ip:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
server: ansible_server1
|
||||
network: public
|
||||
floating_ip_address: "{{ (info.openstack_servers.0.addresses.ansible_internal|
|
||||
selectattr('OS-EXT-IPS:type', '==', 'floating')|map(attribute='addr')|list)[0] }}"
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: ansible_server1
|
||||
register: info
|
||||
# When detaching a floating ip from an instance there might be a delay until openstack.cloud.server_info
|
||||
# does not list it any more in info.openstack_servers.0.addresses.ansible_internal, so retry if necessary.
|
||||
retries: 10
|
||||
delay: 3
|
||||
until: info.openstack_servers.0.addresses.ansible_internal|length == 1
|
||||
|
||||
- name: Assert one internal port on server 1
|
||||
assert:
|
||||
that:
|
||||
- info.openstack_servers.0.addresses.ansible_internal|length == 1
|
||||
- info.openstack_servers.0.addresses.ansible_internal|map(attribute="addr")|list == ["10.7.7.100"]
|
||||
|
||||
- name: Assign floating IP to server
|
||||
openstack.cloud.floating_ip:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
reuse: yes
|
||||
server: ansible_server2
|
||||
network: public
|
||||
fixed_address: 10.7.7.101
|
||||
wait: true
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: ansible_server2
|
||||
register: info
|
||||
|
||||
- name: Assert two internal ports and one floating ip on server 2
|
||||
assert:
|
||||
that:
|
||||
- info.openstack_servers.0.addresses.ansible_internal|length == 3
|
||||
- info.openstack_servers.0.addresses.ansible_internal|map(attribute="OS-EXT-IPS:type")|sort|list ==
|
||||
["fixed", "fixed", "floating"]
|
||||
|
||||
- name: Assign a second, specific floating IP to server
|
||||
openstack.cloud.floating_ip:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
reuse: yes
|
||||
server: ansible_server2
|
||||
network: ansible_external
|
||||
fixed_address: 10.7.7.102
|
||||
floating_ip_address: "10.6.6.150"
|
||||
|
||||
# We cannot wait for second floating ip to be attached because OpenStackSDK checks only for first floating ip
|
||||
# Ref.: https://github.com/openstack/openstacksdk/blob/e0372b72af8c5f471fc17e53434d7a814ca958bd/openstack/cloud/_floating_ip.py#L733
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: ansible_server2
|
||||
register: info
|
||||
# retry because we cannot wait for second floating ip
|
||||
retries: 10
|
||||
delay: 3
|
||||
until: info.openstack_servers.0.addresses.ansible_internal|length == 4
|
||||
|
||||
- name: Assert two internal ports and two floating ips on server 2
|
||||
assert:
|
||||
that:
|
||||
- info.openstack_servers.0.addresses.ansible_internal|length == 4
|
||||
- ("10.6.6.150" in info.openstack_servers.0.addresses.ansible_internal|map(attribute="addr")|sort|list)
|
||||
|
||||
- name: Detach second floating IP from server
|
||||
openstack.cloud.floating_ip:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
server: ansible_server2
|
||||
network: ansible_external
|
||||
floating_ip_address: "10.6.6.150"
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: ansible_server2
|
||||
register: info
|
||||
# When detaching a floating ip from an instance there might be a delay until openstack.cloud.server_info
|
||||
# does not list it any more in info.openstack_servers.0.addresses.ansible_internal, so retry if necessary.
|
||||
retries: 10
|
||||
delay: 3
|
||||
until: info.openstack_servers.0.addresses.ansible_internal|length == 3
|
||||
|
||||
- name: Assert two internal ports and one floating ip on server 2
|
||||
assert:
|
||||
that:
|
||||
- info.openstack_servers.0.addresses.ansible_internal|length == 3
|
||||
|
||||
- name: Detach remaining floating IP from server
|
||||
openstack.cloud.floating_ip:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
server: ansible_server2
|
||||
network: public
|
||||
floating_ip_address: "{{ (info.openstack_servers.0.addresses.ansible_internal|
|
||||
selectattr('OS-EXT-IPS:type', '==', 'floating')|map(attribute='addr')|list)[0] }}"
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: ansible_server2
|
||||
register: info
|
||||
# When detaching a floating ip from an instance there might be a delay until openstack.cloud.server_info
|
||||
# does not list it any more in info.openstack_servers.0.addresses.ansible_internal, so retry if necessary.
|
||||
retries: 10
|
||||
delay: 3
|
||||
until: info.openstack_servers.0.addresses.ansible_internal|length == 2
|
||||
|
||||
- name: Assert two internal ports on server 2
|
||||
assert:
|
||||
that:
|
||||
- info.openstack_servers.0.addresses.ansible_internal|length == 2
|
||||
- info.openstack_servers.0.addresses.ansible_internal|map(attribute="addr")|list == ["10.7.7.101", "10.7.7.102"]
|
||||
|
||||
# Clean environment
|
||||
- name: Delete server with two nics
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_server2
|
||||
wait: true
|
||||
|
||||
- name: Delete server with one nic
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_server1
|
||||
wait: true
|
||||
|
||||
- name: Get all floating ips
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: fips
|
||||
|
||||
# TODO: Replace with appropriate Ansible module once available
|
||||
- name: Delete floating ip on public network if we created it
|
||||
when: not public_network_had_fips
|
||||
command: >
|
||||
openstack --os-cloud={{ cloud }} floating ip delete
|
||||
{{ fips.floating_ips|selectattr('floating_network_id', '==', public_network.openstack_networks.0.id)|
|
||||
map(attribute="floating_ip_address")|list|join(' ') }}
|
||||
|
||||
# TODO: Replace with appropriate Ansible module once available
|
||||
- name: Delete floating ip 1
|
||||
command: openstack --os-cloud={{ cloud }} floating ip delete 10.6.6.150
|
||||
when: fips.floating_ips|length > 0 and "10.6.6.150" in fips.floating_ips|map(attribute="floating_ip_address")|list
|
||||
|
||||
- name: Get remaining floating ips on external network
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
floating_network: ansible_external
|
||||
register: fips
|
||||
|
||||
# TODO: Replace with appropriate Ansible module once available
|
||||
# The first, simple floating ip test might have allocated a floating ip on the external network.
|
||||
# This floating ip must be removed before external network can be deleted.
|
||||
- name: Delete remaining floating ips on external network
|
||||
when: fips.floating_ips|length > 0
|
||||
command: >
|
||||
openstack --os-cloud={{ cloud }} floating ip delete
|
||||
{{ fips.floating_ips|map(attribute="floating_ip_address")|list|join(' ') }}
|
||||
|
||||
# Remove routers after floating ips have been detached and disassociated else removal fails with
|
||||
# Error detaching interface from router ***: Client Error for url: ***,
|
||||
# Router interface for subnet *** on router *** cannot be deleted,
|
||||
# as it is required by one or more floating IPs.
|
||||
|
||||
- name: Delete router 2
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_router2
|
||||
|
||||
- name: Delete router 1
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_router1
|
||||
|
||||
- name: Delete internal port 3
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_internal_port3
|
||||
|
||||
- name: Delete internal port 2
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_internal_port2
|
||||
|
||||
- name: Delete internal port 1
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_internal_port1
|
||||
|
||||
- name: Delete internal subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_internal_subnet
|
||||
|
||||
- name: Delete internal network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_internal
|
||||
|
||||
- name: Delete external port 2
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_external_port2
|
||||
|
||||
- name: Delete external port 1
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_external_port1
|
||||
|
||||
- name: Delete external subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_external_subnet
|
||||
|
||||
- name: Delete external network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_external
|
||||
21
ci/roles/floating_ip_info/tasks/main.yml
Normal file
21
ci/roles/floating_ip_info/tasks/main.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
- name: Getting info about allocated ips
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: fips
|
||||
|
||||
- name: assert result
|
||||
assert:
|
||||
that:
|
||||
- fips is success
|
||||
- fips is not changed
|
||||
|
||||
- name: assert fields
|
||||
when: fips.floating_ips|length > 0
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- '["created_at", "description", "dns_domain", "dns_name", "fixed_ip_address", "floating_ip_address",
|
||||
"floating_network_id", "id", "name", "port_details", "port_id", "project_id", "qos_policy_id",
|
||||
"revision_number", "router_id", "status", "subnet_id", "tags", "updated_at"]|
|
||||
difference(fips.floating_ips.0.keys())|length == 0'
|
||||
10
ci/roles/host_aggregate/defaults/main.yml
Normal file
10
ci/roles/host_aggregate/defaults/main.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
# Parameter deleted has been renamed to is_deleted in openstacksdk 0.52.0,
|
||||
# hence we cannot test with this list here.
|
||||
# Ref.: https://github.com/openstack/openstacksdk/commit/b60915aab3ee0348f3e3cc8aa548f94d2a68b7eb
|
||||
expected_fields:
|
||||
- availability_zone
|
||||
- hosts
|
||||
- id
|
||||
- location
|
||||
- metadata
|
||||
- name
|
||||
99
ci/roles/host_aggregate/tasks/main.yml
Normal file
99
ci/roles/host_aggregate/tasks/main.yml
Normal file
@@ -0,0 +1,99 @@
|
||||
---
|
||||
- name: ensure aggregate doesn't exist before tests
|
||||
openstack.cloud.host_aggregate:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: test_aggregate
|
||||
register: aggregate
|
||||
|
||||
- block:
|
||||
- name: create aggregate
|
||||
openstack.cloud.host_aggregate:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: test_aggregate
|
||||
hosts:
|
||||
- "{{ ansible_hostname }}"
|
||||
register: aggregate
|
||||
|
||||
- name: assert aggregate is changed
|
||||
assert:
|
||||
that: aggregate is changed
|
||||
|
||||
- name: assert aggregate fields
|
||||
assert:
|
||||
that: item in aggregate.aggregate
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- block:
|
||||
- name: recreate aggregate
|
||||
openstack.cloud.host_aggregate:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: test_aggregate
|
||||
hosts:
|
||||
- "{{ ansible_hostname }}"
|
||||
register: aggregate
|
||||
|
||||
- name: assert aggregate is not changed
|
||||
assert:
|
||||
that: aggregate is not changed
|
||||
|
||||
- name: assert aggregate fields
|
||||
assert:
|
||||
that: item in aggregate.aggregate
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- block:
|
||||
- name: update aggregate
|
||||
openstack.cloud.host_aggregate:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: test_aggregate
|
||||
metadata:
|
||||
ssd: "true"
|
||||
hosts:
|
||||
- "{{ ansible_hostname }}"
|
||||
register: aggregate
|
||||
|
||||
- name: assert aggregate is changed
|
||||
assert:
|
||||
that: aggregate is changed
|
||||
|
||||
- name: assert aggregate fields
|
||||
assert:
|
||||
that: item in aggregate.aggregate
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- block:
|
||||
- name: purge hosts
|
||||
openstack.cloud.host_aggregate:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: test_aggregate
|
||||
hosts: []
|
||||
purge_hosts: true
|
||||
register: aggregate
|
||||
|
||||
- name: assert hosts were purged
|
||||
assert:
|
||||
that:
|
||||
- aggregate is changed
|
||||
- aggregate.aggregate.hosts | length == 0
|
||||
|
||||
- name: assert aggregate fields
|
||||
assert:
|
||||
that: item in aggregate.aggregate
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- block:
|
||||
- name: delete aggregate
|
||||
openstack.cloud.host_aggregate:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: test_aggregate
|
||||
register: aggregate
|
||||
|
||||
- name: assert aggregate is changed
|
||||
assert:
|
||||
that: aggregate is changed
|
||||
8
ci/roles/identity_domain_info/defaults/main.yml
Normal file
8
ci/roles/identity_domain_info/defaults/main.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
domain_name: domain_info_test_domain
|
||||
unexistent_domain_name: domain_info_unexistent_domain
|
||||
disabled_domain_name: test_domain_disabled
|
||||
domain_info_fields:
|
||||
- description
|
||||
- id
|
||||
- enabled
|
||||
- name
|
||||
72
ci/roles/identity_domain_info/tasks/main.yml
Normal file
72
ci/roles/identity_domain_info/tasks/main.yml
Normal file
@@ -0,0 +1,72 @@
|
||||
---
|
||||
- block:
|
||||
- name: Ensure domain does not exist
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ unexistent_domain_name }}"
|
||||
- name: Get unexistent domain
|
||||
openstack.cloud.identity_domain_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ unexistent_domain_name }}"
|
||||
register: domain_info
|
||||
- name: Assert no results returned
|
||||
assert:
|
||||
that: not domain_info.openstack_domains
|
||||
|
||||
|
||||
- block:
|
||||
- name: Ensure domain exists
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ domain_name }}"
|
||||
description: "test description"
|
||||
register: domain
|
||||
- name: Get domain
|
||||
openstack.cloud.identity_domain_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ domain_name }}"
|
||||
register: domain_info
|
||||
- name: Assert one result exists
|
||||
assert:
|
||||
that: domain_info.openstack_domains | length == 1
|
||||
- name: Assert fields are present
|
||||
assert:
|
||||
that: item in domain_info.openstack_domains[0]
|
||||
loop: "{{ domain_info_fields }}"
|
||||
- name: Assert returned value
|
||||
assert:
|
||||
that:
|
||||
- domain_info.openstack_domains[0].description == domain.domain.description
|
||||
|
||||
- block:
|
||||
- name: Get all domains
|
||||
openstack.cloud.identity_domain_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: domain_info
|
||||
|
||||
- block:
|
||||
- name: Ensure disabled domain exists
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ disabled_domain_name }}"
|
||||
enabled: false
|
||||
description: "test description"
|
||||
register: domain
|
||||
- name: Get filtered domains
|
||||
openstack.cloud.identity_domain_info:
|
||||
cloud: "{{ cloud }}"
|
||||
filters:
|
||||
enabled: true
|
||||
register: domain_info
|
||||
- name: Assert at least one result
|
||||
assert:
|
||||
that: domain_info.openstack_domains | length >= 1
|
||||
- name: Assert returned value
|
||||
assert:
|
||||
that: item.enabled == true
|
||||
loop: "{{ domain_info.openstack_domains }}"
|
||||
|
||||
|
||||
74
ci/roles/identity_group_info/tasks/main.yml
Normal file
74
ci/roles/identity_group_info/tasks/main.yml
Normal file
@@ -0,0 +1,74 @@
|
||||
---
|
||||
- name: List group by domain_id
|
||||
openstack.cloud.identity_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
domain: default
|
||||
register: group_domain
|
||||
|
||||
- name: Assert groups were returned
|
||||
assert:
|
||||
that:
|
||||
- group_domain.openstack_groups | length > 0
|
||||
- group_domain.openstack_groups[0].domain_id == 'default'
|
||||
- group_domain.openstack_groups[0].id is defined
|
||||
- group_domain.openstack_groups[0].description is defined
|
||||
- group_domain.openstack_groups[0].name is defined
|
||||
|
||||
- name: List group by domain_id and group
|
||||
openstack.cloud.identity_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
domain: default
|
||||
name: admins
|
||||
register: groups_info
|
||||
|
||||
- name: Assert groups by domain_id and grouph returned
|
||||
assert:
|
||||
that:
|
||||
- groups_info.openstack_groups | length > 0
|
||||
- groups_info.openstack_groups[0].domain_id == 'default'
|
||||
- groups_info.openstack_groups[0].id is defined
|
||||
- groups_info.openstack_groups[0].description is defined
|
||||
- groups_info.openstack_groups[0].name is defined
|
||||
|
||||
- name: List group by filter
|
||||
openstack.cloud.identity_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
domain: default
|
||||
filters:
|
||||
name: admins
|
||||
register: groups_filter
|
||||
|
||||
- name: Assert group by filter returned
|
||||
assert:
|
||||
that:
|
||||
- groups_filter.openstack_groups | length > 0
|
||||
- groups_filter.openstack_groups[0].domain_id == 'default'
|
||||
- groups_filter.openstack_groups[0].id is defined
|
||||
- groups_filter.openstack_groups[0].description is defined
|
||||
- groups_filter.openstack_groups[0].name is defined
|
||||
|
||||
- name: Verify returned values of group info
|
||||
assert:
|
||||
that:
|
||||
- item in groups_info.openstack_groups[0]
|
||||
loop:
|
||||
- description
|
||||
- domain_id
|
||||
- id
|
||||
- name
|
||||
|
||||
- name: List group by group name
|
||||
openstack.cloud.identity_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: admins
|
||||
register: groups_name
|
||||
|
||||
- name: Assert group by name returned
|
||||
assert:
|
||||
that:
|
||||
- groups_name.openstack_groups | length > 0
|
||||
- groups_name.openstack_groups[0].domain_id == 'default'
|
||||
- groups_name.openstack_groups[0].id is defined
|
||||
- groups_name.openstack_groups[0].description is defined
|
||||
- groups_name.openstack_groups[0].name is defined
|
||||
- groups_name.openstack_groups[0].name == 'admins'
|
||||
5
ci/roles/identity_role/defaults/main.yml
Normal file
5
ci/roles/identity_role/defaults/main.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
role_name: ansible_keystone_role
|
||||
expected_fields:
|
||||
- domain_id
|
||||
- id
|
||||
- name
|
||||
83
ci/roles/identity_role/tasks/main.yml
Normal file
83
ci/roles/identity_role/tasks/main.yml
Normal file
@@ -0,0 +1,83 @@
|
||||
---
|
||||
- name: Cleanup before tests
|
||||
block:
|
||||
- openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ role_name }}"
|
||||
|
||||
- block:
|
||||
- name: Delete unexistent role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ role_name }}"
|
||||
register: role
|
||||
- name: Assert role didn't change
|
||||
assert:
|
||||
that: role is not changed
|
||||
|
||||
- block:
|
||||
- name: Create keystone role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ role_name }}"
|
||||
register: role
|
||||
- name: Try to get role
|
||||
openstack.cloud.identity_role_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ role_name }}"
|
||||
register: roles
|
||||
- name: Assert role found
|
||||
assert:
|
||||
that:
|
||||
- roles.openstack_roles | length == 1
|
||||
- name: Assert role changed
|
||||
assert:
|
||||
that: role is changed
|
||||
- name: Assert return fields
|
||||
assert:
|
||||
that: item in role['role']
|
||||
loop: "{{ expected_fields }}"
|
||||
- name: Assert return value
|
||||
assert:
|
||||
that: role['role']['name'] == role_name
|
||||
- name: Assert retrieved values
|
||||
assert:
|
||||
that: roles.openstack_roles[0].name == role_name
|
||||
|
||||
- block:
|
||||
- name: Create existing keystone role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ role_name }}"
|
||||
register: role
|
||||
- name: Assert role not changed
|
||||
assert:
|
||||
that: role is not changed
|
||||
- name: Assert return fields
|
||||
assert:
|
||||
that: item in role['role']
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- block:
|
||||
- name: Delete keystone role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ role_name }}"
|
||||
register: role
|
||||
- name: Assert role changed
|
||||
assert:
|
||||
that: role is changed
|
||||
- name: Try to get role
|
||||
openstack.cloud.identity_role_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ role_name }}"
|
||||
register: roles
|
||||
- name: Assert no role found
|
||||
assert:
|
||||
that:
|
||||
- roles.openstack_roles | length == 0
|
||||
62
ci/roles/identity_role_info/tasks/main.yml
Normal file
62
ci/roles/identity_role_info/tasks/main.yml
Normal file
@@ -0,0 +1,62 @@
|
||||
- name: Ensure role does not exist before tests
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: test_role
|
||||
|
||||
- name: Get unexistent role
|
||||
openstack.cloud.identity_role_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: test_role
|
||||
register: roleinfo
|
||||
|
||||
- debug:
|
||||
var: roleinfo
|
||||
|
||||
- name: Assert that no results were returned
|
||||
assert:
|
||||
that: not roleinfo.openstack_roles
|
||||
|
||||
- name: Create keystone role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: test_role
|
||||
|
||||
- name: Create second role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: test_role2
|
||||
|
||||
- name: Get role by name
|
||||
openstack.cloud.identity_role_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: test_role
|
||||
register: roleinfo
|
||||
|
||||
- debug:
|
||||
var: roleinfo
|
||||
|
||||
- name: Assert that only one result was returned
|
||||
assert:
|
||||
that: roleinfo.openstack_roles | length == 1
|
||||
|
||||
- name: Assert that roleinfo has fields
|
||||
assert:
|
||||
that: item in roleinfo.openstack_roles[0]
|
||||
loop:
|
||||
- domain_id
|
||||
- id
|
||||
- name
|
||||
|
||||
- name: Post-test cleanup
|
||||
block:
|
||||
- name: Clean up roles
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ item }}"
|
||||
loop:
|
||||
- test_role
|
||||
- test_role2
|
||||
9
ci/roles/identity_user/defaults/main.yml
Normal file
9
ci/roles/identity_user/defaults/main.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
os_identity_user_fields:
|
||||
- default_project_id
|
||||
- description
|
||||
- domain_id
|
||||
- email
|
||||
- enabled
|
||||
- id
|
||||
- name
|
||||
- username
|
||||
197
ci/roles/identity_user/tasks/main.yml
Normal file
197
ci/roles/identity_user/tasks/main.yml
Normal file
@@ -0,0 +1,197 @@
|
||||
---
|
||||
- name: setup
|
||||
block:
|
||||
- name: Delete user before running tests
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ item }}"
|
||||
loop:
|
||||
- ansible_user
|
||||
- ansible_user2
|
||||
register: user
|
||||
|
||||
- block:
|
||||
- name: Delete unexistent user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_user
|
||||
register: user
|
||||
|
||||
- name: Ensure user was not changed
|
||||
assert:
|
||||
that: user is not changed
|
||||
|
||||
- block:
|
||||
- name: Create a user without a password
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
email: ansible.user@nowhere.net
|
||||
domain: default
|
||||
default_project: demo
|
||||
register: user
|
||||
|
||||
- name: Ensure user was changed
|
||||
assert:
|
||||
that: user is changed
|
||||
|
||||
- name: Ensure user has fields
|
||||
assert:
|
||||
that: item in user['user']
|
||||
loop: "{{ os_identity_user_fields }}"
|
||||
|
||||
- name: Fail when update_password is always but no password specified
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
update_password: always
|
||||
email: ansible.user@nowhere.net
|
||||
domain: default
|
||||
default_project: demo
|
||||
register: user
|
||||
ignore_errors: yes
|
||||
|
||||
- assert:
|
||||
that: user.msg == "update_password is always but a password value is missing"
|
||||
|
||||
- name: Delete user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_user
|
||||
|
||||
- block:
|
||||
- name: Create user with a password
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
password: secret
|
||||
email: ansible.user@nowhere.net
|
||||
update_password: on_create
|
||||
domain: default
|
||||
default_project: demo
|
||||
register: user
|
||||
|
||||
- name: Assert user has fields
|
||||
assert:
|
||||
that: item in user['user']
|
||||
loop: "{{ os_identity_user_fields }}"
|
||||
|
||||
- block:
|
||||
- name: Create identical user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
password: secret
|
||||
email: ansible.user@nowhere.net
|
||||
update_password: on_create
|
||||
domain: default
|
||||
default_project: demo
|
||||
register: user
|
||||
|
||||
- name: Assert user was not changed
|
||||
assert:
|
||||
that: user is not changed
|
||||
|
||||
- name: Assert user has fields
|
||||
assert:
|
||||
that: item in user['user']
|
||||
loop: "{{ os_identity_user_fields }}"
|
||||
|
||||
- block:
|
||||
- name: Update user with password
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
password: secret2
|
||||
email: updated.ansible.user@nowhere.net
|
||||
register: user
|
||||
|
||||
- name: Ensure user was changed
|
||||
assert:
|
||||
that: user is changed
|
||||
|
||||
- name: Ensure user has fields
|
||||
assert:
|
||||
that: item in user['user']
|
||||
loop: "{{ os_identity_user_fields }}"
|
||||
|
||||
- name: Update user without password and update_password set to always
|
||||
block:
|
||||
- openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
update_password: always
|
||||
email: updated.ansible.user@nowhere.net
|
||||
register: user
|
||||
ignore_errors: yes
|
||||
|
||||
- assert:
|
||||
that: user.msg == "update_password is always but a password value is missing"
|
||||
|
||||
- block:
|
||||
- name: Ensure user with update_password set to on_create
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
update_password: on_create
|
||||
password: secret3
|
||||
email: updated.ansible.user@nowhere.net
|
||||
register: user
|
||||
|
||||
- name: Ensure user was not changed
|
||||
assert:
|
||||
that: user is not changed
|
||||
|
||||
- block:
|
||||
- name: Ensure user with update_password set to always
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
update_password: always
|
||||
password: secret3
|
||||
email: updated.ansible.user@nowhere.net
|
||||
register: user
|
||||
|
||||
- name: Ensure user was changed
|
||||
assert:
|
||||
that: user is changed
|
||||
|
||||
- block:
|
||||
- name: Create user without a password
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user2
|
||||
password: secret
|
||||
email: ansible.user2@nowhere.net
|
||||
update_password: on_create
|
||||
domain: default
|
||||
default_project: demo
|
||||
register: user
|
||||
|
||||
- name: Assert user has fields
|
||||
assert:
|
||||
that: item in user['user']
|
||||
loop: "{{ os_identity_user_fields }}"
|
||||
|
||||
- block:
|
||||
- name: Delete user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_user
|
||||
|
||||
- name: Ensure user was changed
|
||||
assert:
|
||||
that: user is changed
|
||||
9
ci/roles/identity_user_info/defaults/main.yml
Normal file
9
ci/roles/identity_user_info/defaults/main.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
os_expected_user_info_fields:
|
||||
- default_project_id
|
||||
- description
|
||||
- domain_id
|
||||
- email
|
||||
- enabled
|
||||
- id
|
||||
- name
|
||||
- username
|
||||
69
ci/roles/identity_user_info/tasks/main.yml
Normal file
69
ci/roles/identity_user_info/tasks/main.yml
Normal file
@@ -0,0 +1,69 @@
|
||||
- name: Ensure user does not exist before tests
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_user
|
||||
|
||||
- block:
|
||||
- name: Get unexistent user
|
||||
openstack.cloud.identity_user_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_user
|
||||
register: userinfo
|
||||
- name: Ensure nothing was returned
|
||||
assert:
|
||||
that: not userinfo.openstack_users
|
||||
|
||||
- block:
|
||||
- name: Create user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
password: secret
|
||||
email: ansible.user@nowhere.net
|
||||
domain: default
|
||||
default_project: demo
|
||||
register: user
|
||||
- name: Create second user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user2
|
||||
password: secret
|
||||
email: ansible.user2@nowhere.net
|
||||
domain: default
|
||||
default_project: demo
|
||||
register: user
|
||||
- name: Get first user info
|
||||
openstack.cloud.identity_user_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_user
|
||||
register: userinfo
|
||||
- name: Assert only one result exists
|
||||
assert:
|
||||
that: "{{ userinfo.openstack_users | length }} == 1"
|
||||
- name: Assert userinfo has fields
|
||||
assert:
|
||||
that: item in userinfo.openstack_users[0]
|
||||
loop: "{{ os_expected_user_info_fields }}"
|
||||
|
||||
- block:
|
||||
- name: Get all users
|
||||
openstack.cloud.identity_user_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: userinfo
|
||||
- name: Assert results were returned
|
||||
assert:
|
||||
that: "{{ userinfo.openstack_users | length }} > 0"
|
||||
|
||||
- name: Post-test cleanup
|
||||
block:
|
||||
- name: Ensure users do not exist
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ item }}"
|
||||
loop:
|
||||
- ansible_user
|
||||
- ansible_user2
|
||||
@@ -1 +1,4 @@
|
||||
image_name: ansible_image
|
||||
image_tags:
|
||||
- test
|
||||
- ansible
|
||||
|
||||
@@ -13,9 +13,20 @@
|
||||
name: "{{ image_name }}"
|
||||
filename: "{{ tmp_file.stdout }}"
|
||||
disk_format: raw
|
||||
tags: "{{ image_tags }}"
|
||||
register: image
|
||||
|
||||
- debug: var=image
|
||||
- name: Get details of created image
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: "{{ image_name }}"
|
||||
register: image_info_result
|
||||
|
||||
- name: Verify image info
|
||||
assert:
|
||||
that:
|
||||
- "image_info_result.openstack_images[0].name == image_name"
|
||||
- "image_info_result.openstack_images[0].tags | sort == image_tags | sort"
|
||||
|
||||
- name: Delete raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
@@ -40,14 +51,97 @@
|
||||
distro: ubuntu
|
||||
register: image
|
||||
|
||||
- debug: var=image
|
||||
|
||||
- name: Delete raw image (complex)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ image_name }}"
|
||||
|
||||
- name: Try to get details of deleted image
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: "{{ image_name }}"
|
||||
register: deleted_image_info_result
|
||||
|
||||
- name: Verify image is deleted
|
||||
assert:
|
||||
that:
|
||||
- not deleted_image_info_result.openstack_images
|
||||
|
||||
- name: Create owner project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: image_owner_project
|
||||
description: Project owning test image
|
||||
domain_id: default
|
||||
enabled: True
|
||||
register: owner_project
|
||||
|
||||
- name: Create raw image (owner by project name)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ image_name }}"
|
||||
filename: "{{ tmp_file.stdout }}"
|
||||
disk_format: raw
|
||||
tags: "{{ image_tags }}"
|
||||
project: image_owner_project
|
||||
register: image
|
||||
|
||||
- name: Get details of created image (owner by project name)
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: "{{ image_name }}"
|
||||
register: image_info_result
|
||||
|
||||
- name: Verify image owner (owner by project name)
|
||||
assert:
|
||||
that:
|
||||
- image_info_result.openstack_images[0].owner == owner_project.project.id
|
||||
|
||||
- name: Delete raw image (owner by project name)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ image_name }}"
|
||||
|
||||
- name: Create raw image (owner by project name and domain name)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ image_name }}"
|
||||
filename: "{{ tmp_file.stdout }}"
|
||||
disk_format: raw
|
||||
tags: "{{ image_tags }}"
|
||||
project: image_owner_project
|
||||
project_domain: default
|
||||
register: image
|
||||
|
||||
- name: Get details of created image (owner by project name and domain name)
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: "{{ image_name }}"
|
||||
register: image_info_result
|
||||
|
||||
- name: Verify image owner (owner by project name and domain name)
|
||||
assert:
|
||||
that:
|
||||
- image_info_result.openstack_images[0].owner == owner_project.project.id
|
||||
|
||||
- name: Delete raw image (owner by project name and domain name)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ image_name }}"
|
||||
|
||||
- name: Delete owner project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: image_owner_project
|
||||
domain_id: default
|
||||
|
||||
- name: Delete test image file
|
||||
file:
|
||||
name: "{{ tmp_file.stdout }}"
|
||||
|
||||
23
ci/roles/image_info/defaults/main.yml
Normal file
23
ci/roles/image_info/defaults/main.yml
Normal file
@@ -0,0 +1,23 @@
|
||||
expected_fields:
|
||||
- checksum
|
||||
- container_format
|
||||
- created_at
|
||||
- direct_url
|
||||
- disk_format
|
||||
- file
|
||||
- id
|
||||
- locations
|
||||
- metadata
|
||||
- min_disk
|
||||
- min_ram
|
||||
- name
|
||||
- os_hidden
|
||||
- owner
|
||||
- properties
|
||||
- schema
|
||||
- size
|
||||
- status
|
||||
- tags
|
||||
- updated_at
|
||||
- virtual_size
|
||||
- visibility
|
||||
11
ci/roles/image_info/tasks/main.yml
Normal file
11
ci/roles/image_info/tasks/main.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
- name: List all images # This will list at least the default cirros image of devstack
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: image_list_result
|
||||
|
||||
- name: Assert fields
|
||||
assert:
|
||||
that:
|
||||
- item in image_list_result.openstack_images.0.keys()
|
||||
loop: "{{ expected_fields }}"
|
||||
@@ -1 +1,11 @@
|
||||
keypair_name: shade_keypair
|
||||
expected_fields:
|
||||
- created_at
|
||||
- fingerprint
|
||||
- id
|
||||
- is_deleted
|
||||
- name
|
||||
- private_key
|
||||
- public_key
|
||||
- type
|
||||
- user_id
|
||||
|
||||
@@ -1,62 +1,156 @@
|
||||
---
|
||||
- name: Create keypair (non-existing)
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
state: present
|
||||
register:
|
||||
keypair
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
state: present
|
||||
register: keypair
|
||||
|
||||
- name: Get list of all keypairs
|
||||
openstack.cloud.keypair_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: keypairs_all
|
||||
|
||||
- name: Get list of keypairs with filter
|
||||
openstack.cloud.keypair_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
register: keypairs
|
||||
|
||||
- name: Ensure that list of keypairs contains single element
|
||||
assert:
|
||||
that:
|
||||
- keypairs['openstack_keypairs']|length == 1
|
||||
|
||||
- name: Assert fields
|
||||
assert:
|
||||
that:
|
||||
- item in keypairs.openstack_keypairs.0.keys()
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
# This assert verifies that Ansible is capable serializing data returned by SDK
|
||||
- name: Ensure private key is returned
|
||||
- name: Ensure public key is returned
|
||||
assert:
|
||||
that:
|
||||
- keypair.key.public_key is defined and keypair.key.public_key
|
||||
|
||||
- name: Create another keypair
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}-2"
|
||||
state: present
|
||||
|
||||
- name: Delete keypair (non-existing)
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
state: absent
|
||||
cloud: "{{ cloud }}"
|
||||
name: "non-existing"
|
||||
state: absent
|
||||
|
||||
- name: Delete keypair
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
state: absent
|
||||
|
||||
- name: Get list of keypairs
|
||||
openstack.cloud.keypair_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
register: keypairs
|
||||
|
||||
- name: Ensure that list of keypairs is empty
|
||||
assert:
|
||||
that:
|
||||
- keypairs['openstack_keypairs']|length == 0
|
||||
|
||||
- name: Delete another keypair
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}-2"
|
||||
state: absent
|
||||
|
||||
- name: Generate test key file
|
||||
user:
|
||||
name: "{{ ansible_env.USER }}"
|
||||
generate_ssh_key: yes
|
||||
ssh_key_file: .ssh/shade_id_rsa
|
||||
name: "{{ ansible_env.USER }}"
|
||||
generate_ssh_key: yes
|
||||
ssh_key_file: .ssh/shade_id_rsa
|
||||
|
||||
- name: Create keypair (file)
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
state: present
|
||||
public_key_file: "{{ ansible_env.HOME }}/.ssh/shade_id_rsa.pub"
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
state: present
|
||||
public_key_file: "{{ ansible_env.HOME }}/.ssh/shade_id_rsa.pub"
|
||||
|
||||
- name: Get list of keypairs
|
||||
openstack.cloud.keypair_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
register: keypairs
|
||||
|
||||
- name: Ensure that list of keypairs contains single element
|
||||
assert:
|
||||
that:
|
||||
- keypairs['openstack_keypairs']|length == 1
|
||||
|
||||
- name: Delete keypair (file)
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
state: absent
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
state: absent
|
||||
|
||||
- name: Get list of keypairs
|
||||
openstack.cloud.keypair_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
register: keypairs
|
||||
|
||||
- name: Ensure that list of keypairs is empty
|
||||
assert:
|
||||
that:
|
||||
- keypairs['openstack_keypairs']|length == 0
|
||||
|
||||
- name: Create keypair (key)
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
state: present
|
||||
public_key: "{{ lookup('file', '~/.ssh/shade_id_rsa.pub') }}"
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
state: present
|
||||
public_key: "{{ lookup('file', '~/.ssh/shade_id_rsa.pub') }}"
|
||||
|
||||
- name: Get list of keypairs
|
||||
openstack.cloud.keypair_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
register: keypairs
|
||||
|
||||
- name: Ensure that list of keypairs contains single element
|
||||
assert:
|
||||
that:
|
||||
- keypairs['openstack_keypairs']|length == 1
|
||||
|
||||
- name: Delete keypair (key)
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
state: absent
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
state: absent
|
||||
|
||||
- name: Get list of keypairs
|
||||
openstack.cloud.keypair_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
register: keypairs
|
||||
|
||||
- name: Ensure that list of keypairs is empty
|
||||
assert:
|
||||
that:
|
||||
- keypairs['openstack_keypairs']|length == 0
|
||||
|
||||
- name: Delete test key pub file
|
||||
file:
|
||||
name: "{{ ansible_env.HOME }}/.ssh/shade_id_rsa.pub"
|
||||
state: absent
|
||||
name: "{{ ansible_env.HOME }}/.ssh/shade_id_rsa.pub"
|
||||
state: absent
|
||||
|
||||
- name: Delete test key pvt file
|
||||
file:
|
||||
name: "{{ ansible_env.HOME }}/.ssh/shade_id_rsa"
|
||||
state: absent
|
||||
name: "{{ ansible_env.HOME }}/.ssh/shade_id_rsa"
|
||||
state: absent
|
||||
|
||||
@@ -1,19 +1,36 @@
|
||||
---
|
||||
- name: Create keystone domain
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ domain_name }}"
|
||||
description: "test description"
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ domain_name }}"
|
||||
description: "test description"
|
||||
register: os_domain
|
||||
|
||||
- name: Test output
|
||||
assert:
|
||||
that:
|
||||
- "'domain' in os_domain"
|
||||
- os_domain.domain.name == "{{ domain_name }}"
|
||||
- >-
|
||||
('enabled' in os_domain.domain.keys() and os_domain.domain['enabled']|bool) or
|
||||
('is_enabled' in os_domain.domain and os_domain.domain['is_enabled']|bool)
|
||||
- os_domain.domain.description == "test description"
|
||||
|
||||
- name: Update keystone domain
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ domain_name }}"
|
||||
description: "updated description"
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ domain_name }}"
|
||||
description: "updated description"
|
||||
register: os_domain_updated
|
||||
|
||||
- name: Test output
|
||||
assert:
|
||||
that:
|
||||
- os_domain_updated.domain.description == "updated description"
|
||||
|
||||
- name: Delete keystone domain
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ domain_name }}"
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ domain_name }}"
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
role_name: ansible_keystone_role
|
||||
@@ -1,12 +0,0 @@
|
||||
---
|
||||
- name: Create keystone role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ role_name }}"
|
||||
|
||||
- name: Delete keystone role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ role_name }}"
|
||||
3
ci/roles/loadbalancer/defaults/main.yml
Normal file
3
ci/roles/loadbalancer/defaults/main.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
network_name: network_lb
|
||||
subnet_name: subnet_lb
|
||||
lb_name: test_lb
|
||||
50
ci/roles/loadbalancer/tasks/main.yml
Normal file
50
ci/roles/loadbalancer/tasks/main.yml
Normal file
@@ -0,0 +1,50 @@
|
||||
|
||||
---
|
||||
- name: Create network {{ network_name }} for LB
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name }}"
|
||||
state: present
|
||||
|
||||
- name: Create subnet {{ subnet_name }} on network {{ network_name }} for LB
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
network_name: "{{ network_name }}"
|
||||
name: "{{ subnet_name }}"
|
||||
state: present
|
||||
enable_dhcp: true
|
||||
dns_nameservers:
|
||||
- 8.8.8.7
|
||||
- 8.8.8.8
|
||||
cidr: 192.168.0.0/24
|
||||
gateway_ip: 192.168.0.1
|
||||
allocation_pool_start: 192.168.0.2
|
||||
allocation_pool_end: 192.168.0.254
|
||||
|
||||
- name: Create loadbalancer - generic
|
||||
openstack.cloud.loadbalancer:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ lb_name }}"
|
||||
vip_subnet: "{{ subnet_name }}"
|
||||
timeout: 450
|
||||
|
||||
- name: Delete loadbalancer
|
||||
openstack.cloud.loadbalancer:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ lb_name }}"
|
||||
timeout: 150
|
||||
|
||||
- name: Delete subnet {{ subnet_name }} on network {{ network_name }}
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
network_name: "{{ network_name }}"
|
||||
name: "{{ subnet_name }}"
|
||||
state: absent
|
||||
|
||||
- name: Delete network {{ network_name }} of LB
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name }}"
|
||||
state: absent
|
||||
1
ci/roles/logging/defaults/main.yaml
Normal file
1
ci/roles/logging/defaults/main.yaml
Normal file
@@ -0,0 +1 @@
|
||||
sdk_log_file_path: "{{ playbook_dir }}/sdk.log"
|
||||
20
ci/roles/logging/tasks/main.yaml
Normal file
20
ci/roles/logging/tasks/main.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
- name: Trigger flavor listing
|
||||
openstack.cloud.compute_flavor_info:
|
||||
cloud: "{{ cloud }}"
|
||||
sdk_log_path: "{{ sdk_log_file_path }}"
|
||||
sdk_log_level: "DEBUG"
|
||||
|
||||
- name: Check log file presence
|
||||
ansible.builtin.stat:
|
||||
path: "{{ sdk_log_file_path }}"
|
||||
register: sdk_log_file
|
||||
|
||||
- name: Assert
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- "sdk_log_file.stat.exists"
|
||||
|
||||
- name: Debug log file content
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ lookup('ansible.builtin.file', sdk_log_file_path) }}"
|
||||
@@ -1,3 +1,7 @@
|
||||
network_name: shade_network
|
||||
network_name_newparams: newparams_network
|
||||
network_shared: false
|
||||
network_external: false
|
||||
dns_domain: example.opendev.org
|
||||
mtu: 1250
|
||||
port_security_enabled: false
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
- name: Create network
|
||||
- name: Create network - generic
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name }}"
|
||||
@@ -7,8 +7,71 @@
|
||||
shared: "{{ network_shared }}"
|
||||
external: "{{ network_external }}"
|
||||
|
||||
- name: Delete network
|
||||
openstack.cloud.network:
|
||||
- name: Gather networks info - generic
|
||||
openstack.cloud.networks_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name }}"
|
||||
filters:
|
||||
shared: "{{ network_shared|string|capitalize }}"
|
||||
register: result
|
||||
|
||||
- name: Verify networks info - generic
|
||||
assert:
|
||||
that:
|
||||
- result.openstack_networks.0.name == network_name
|
||||
- (result.openstack_networks.0.shared|lower) == (network_shared|lower)
|
||||
- result.openstack_networks[0]['router:external'] == {{ network_external }}
|
||||
|
||||
- name: Create network - with new SDK params
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name_newparams }}"
|
||||
state: present
|
||||
shared: "{{ network_shared }}"
|
||||
external: "{{ network_external }}"
|
||||
mtu: "{{ mtu }}"
|
||||
port_security_enabled: "{{ port_security_enabled }}"
|
||||
register: result_create_nw_with_new_params
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Check errors below min sdk version - with new SDK params
|
||||
assert:
|
||||
that:
|
||||
- result_create_nw_with_new_params.failed
|
||||
- '"the installed version of the openstacksdk library MUST be >=0.18.0." in result_create_nw_with_new_params.msg'
|
||||
when: sdk_version is version('0.18', '<')
|
||||
|
||||
- name: Gather networks info - with new SDK params
|
||||
openstack.cloud.networks_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name_newparams }}"
|
||||
register: result_newparams
|
||||
when: sdk_version is version('0.18', '>=')
|
||||
|
||||
- name: Verify networks info - with new SDK params
|
||||
assert:
|
||||
that:
|
||||
- result_newparams.openstack_networks.0.name == network_name_newparams
|
||||
- result_newparams.openstack_networks.0.mtu == mtu
|
||||
- result_newparams.openstack_networks.0.port_security_enabled == port_security_enabled
|
||||
when: sdk_version is version('0.18', '>=')
|
||||
|
||||
- name: Delete network - generic and with new SDK params
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
with_items:
|
||||
- "{{ network_name }}"
|
||||
- "{{ network_name_newparams }}"
|
||||
|
||||
- name: Gather networks info - deleted
|
||||
openstack.cloud.networks_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name }}"
|
||||
register: result_nonet
|
||||
|
||||
- name: Verify networks info - deleted
|
||||
assert:
|
||||
that:
|
||||
- result_nonet.openstack_networks == []
|
||||
|
||||
85
ci/roles/neutron_rbac/tasks/main.yml
Normal file
85
ci/roles/neutron_rbac/tasks/main.yml
Normal file
@@ -0,0 +1,85 @@
|
||||
---
|
||||
# General run of tests
|
||||
# - Prepare projects/network objects
|
||||
# - Create rbac object
|
||||
# - Get rbac object info
|
||||
# - Verify RBAC object match
|
||||
# - Delete rbac object
|
||||
# - Get rbac object info
|
||||
# - Verify RBAC object deleted
|
||||
|
||||
- name: Create source project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: source_project
|
||||
description: Source project for network RBAC test
|
||||
domain_id: default
|
||||
enabled: True
|
||||
register: source_project
|
||||
|
||||
- name: Create network - generic
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name }}"
|
||||
state: present
|
||||
project: "{{ source_project.project.id }}"
|
||||
shared: false
|
||||
external: "{{ network_external }}"
|
||||
register: network
|
||||
|
||||
- name: Create target project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: Target project for network RBAC test
|
||||
domain_id: default
|
||||
enabled: True
|
||||
register: target_project
|
||||
|
||||
- name: Create a new network RBAC policy
|
||||
openstack.cloud.neutron_rbac_policy:
|
||||
cloud: "{{ cloud }}"
|
||||
object_id: "{{ network.network.id }}"
|
||||
object_type: 'network'
|
||||
action: 'access_as_shared'
|
||||
target_project_id: "{{ target_project.project.id }}"
|
||||
project_id: "{{ source_project.project.id }}"
|
||||
register: rbac_policy
|
||||
|
||||
- name: Get all rbac policies for {{ source_project.project.name }} - after creation
|
||||
openstack.cloud.neutron_rbac_policies_info:
|
||||
cloud: "{{ cloud }}"
|
||||
project_id: "{{ source_project.project.id }}"
|
||||
register: rbac_policies
|
||||
|
||||
- name: Capture all existing policy IDs
|
||||
set_fact:
|
||||
rbac_policy_ids: "{{ rbac_policies.policies | map(attribute='id') | list }}"
|
||||
|
||||
- name: Verify policy exists - after creation
|
||||
assert:
|
||||
that:
|
||||
- rbac_policy.policy.id in rbac_policy_ids
|
||||
|
||||
- name: Delete RBAC policy
|
||||
openstack.cloud.neutron_rbac_policy:
|
||||
cloud: "{{ cloud }}"
|
||||
policy_id: "{{ rbac_policy.policy.id }}"
|
||||
state: absent
|
||||
|
||||
- name: Get all rbac policies for {{ source_project.project.name }} - after deletion
|
||||
openstack.cloud.neutron_rbac_policies_info:
|
||||
cloud: "{{ cloud }}"
|
||||
project_id: "{{ source_project.project.id }}"
|
||||
register: rbac_policies_remaining
|
||||
|
||||
- name: Capture all remaining policy IDs
|
||||
set_fact:
|
||||
remaining_rbac_policy_ids: "{{ rbac_policies_remaining.policies | map(attribute='id') | list }}"
|
||||
|
||||
- name: Verify policy does not exist - after deletion
|
||||
assert:
|
||||
that:
|
||||
- not rbac_policy.policy.id in remaining_rbac_policy_ids
|
||||
33
ci/roles/nova_services/tasks/main.yml
Normal file
33
ci/roles/nova_services/tasks/main.yml
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
|
||||
- name: Get nova compute services info
|
||||
openstack.cloud.compute_service_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: result
|
||||
failed_when: "result.openstack_compute_services | length <= 0"
|
||||
|
||||
- name: Assert fields on OpenStack SDK before 0.53
|
||||
when: sdk_version is version(0.53, '<')
|
||||
assert:
|
||||
that:
|
||||
- '["availability_zone", "binary", "disables_reason",
|
||||
"host", "name", "state", "status", "id"] |
|
||||
difference(result.openstack_compute_services.0.keys()) | length == 0'
|
||||
|
||||
- name: Assert fields on OpenStack SDK 0.53 and later
|
||||
when: sdk_version is version(0.53, '>=')
|
||||
assert:
|
||||
that:
|
||||
- '["availability_zone", "binary", "disabled_reason", "is_forced_down",
|
||||
"host", "name", "state", "status", "updated_at", "id"] |
|
||||
difference(result.openstack_compute_services.0.keys()) | length == 0'
|
||||
|
||||
- name: Filter compute services. Supported since OpenStack SDK 0.53.0 (Wallaby).
|
||||
when: sdk_version is version(0.53, '>=')
|
||||
block:
|
||||
- name: Get nova compute services info
|
||||
openstack.cloud.compute_service_info:
|
||||
cloud: "{{ cloud }}"
|
||||
binary: "nova-compute"
|
||||
register: result
|
||||
failed_when: "result.openstack_compute_services | length <= 0"
|
||||
1
ci/roles/object_container/defaults/main.yml
Normal file
1
ci/roles/object_container/defaults/main.yml
Normal file
@@ -0,0 +1 @@
|
||||
container_name: "test-container"
|
||||
60
ci/roles/object_container/tasks/main.yml
Normal file
60
ci/roles/object_container/tasks/main.yml
Normal file
@@ -0,0 +1,60 @@
|
||||
---
|
||||
- module_defaults:
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
block:
|
||||
- name: Create an empty container
|
||||
openstack.cloud.object_container:
|
||||
container: "{{ container_name }}"
|
||||
register: container
|
||||
|
||||
- name: Verify container was created
|
||||
assert:
|
||||
that:
|
||||
- container is success
|
||||
- container is changed
|
||||
- container.container.name == container_name
|
||||
|
||||
- name: Set metadata for a container
|
||||
openstack.cloud.object_container:
|
||||
container: "{{ container_name }}"
|
||||
metadata: "Cache-Control='no-cache'"
|
||||
register: set_meta
|
||||
|
||||
- name: Verify container metadata was set
|
||||
assert:
|
||||
that:
|
||||
- set_meta is success
|
||||
- set_meta is changed
|
||||
|
||||
- name: Delete some keys from container metadata
|
||||
openstack.cloud.object_container:
|
||||
container: "{{ container_name }}"
|
||||
keys:
|
||||
- Cache-Control
|
||||
register: delete_meta
|
||||
|
||||
- name: Verify some keys from container metadata was deleted
|
||||
assert:
|
||||
that:
|
||||
- delete_meta is success
|
||||
- delete_meta is changed
|
||||
|
||||
- name: Delete container
|
||||
openstack.cloud.object_container:
|
||||
container: "{{ container_name }}"
|
||||
state: absent
|
||||
register: deleted
|
||||
|
||||
- name: Verify container was deleted
|
||||
assert:
|
||||
that:
|
||||
- deleted is success
|
||||
- deleted is changed
|
||||
|
||||
always:
|
||||
- name: Delete container
|
||||
openstack.cloud.object_container:
|
||||
container: "{{ container_name }}"
|
||||
state: absent
|
||||
ignore_errors: yes
|
||||
2
ci/roles/orchestration/defaults/main.yaml
Normal file
2
ci/roles/orchestration/defaults/main.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
---
|
||||
stack_name: "test-stack"
|
||||
11
ci/roles/orchestration/files/hello-world.yaml
Normal file
11
ci/roles/orchestration/files/hello-world.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
#
|
||||
# Minimal HOT template defining a single compute server.
|
||||
#
|
||||
heat_template_version: 2013-05-23
|
||||
|
||||
description: >
|
||||
Minimal HOT template for stack
|
||||
|
||||
parameters:
|
||||
resources:
|
||||
outputs:
|
||||
44
ci/roles/orchestration/tasks/main.yaml
Normal file
44
ci/roles/orchestration/tasks/main.yaml
Normal file
@@ -0,0 +1,44 @@
|
||||
---
|
||||
- name: Create minimal stack
|
||||
openstack.cloud.stack:
|
||||
cloud: "{{ cloud }}"
|
||||
# template is searched related to playbook location or as absolute path
|
||||
template: "roles/orchestration/files/hello-world.yaml"
|
||||
name: "{{ stack_name }}"
|
||||
|
||||
- name: List stacks
|
||||
openstack.cloud.stack_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: stacks
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- stacks['stacks']|length > 0
|
||||
|
||||
- name: Get Single stack
|
||||
openstack.cloud.stack_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ stack_name }}"
|
||||
register: test_stack
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- test_stack is defined
|
||||
- test_stack['stacks'][0]['name'] == stack_name
|
||||
|
||||
- name: Delete stack
|
||||
openstack.cloud.stack:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ stack_name }}"
|
||||
state: absent
|
||||
|
||||
- name: Get Single stack
|
||||
openstack.cloud.stack_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ stack_name }}"
|
||||
register: stacks
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- stacks is defined
|
||||
- (stacks['stacks']|length == 0) or (stacks['stacks'][0]['status'] == 'DELETE_COMPLETE')
|
||||
@@ -4,3 +4,6 @@ subnet_name: ansible_port_subnet
|
||||
port_name: ansible_port
|
||||
secgroup_name: ansible_port_secgroup
|
||||
no_security_groups: True
|
||||
binding_profile:
|
||||
"pci_slot": "0000:03:11.1"
|
||||
"physical_network": "provider"
|
||||
|
||||
@@ -60,6 +60,26 @@
|
||||
state: absent
|
||||
name: "{{ port_name }}"
|
||||
|
||||
- name: Create port (with dns_name, dns_domain)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
fixed_ips:
|
||||
- ip_address: 10.5.5.69
|
||||
dns_name: "dns-port-name"
|
||||
dns_domain: "example.com."
|
||||
register: port
|
||||
|
||||
- debug: var=port
|
||||
|
||||
- name: Delete port (with dns name,domain)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ port_name }}"
|
||||
|
||||
- name: Create port (with allowed_address_pairs and extra_dhcp_opts)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
@@ -88,6 +108,30 @@
|
||||
state: absent
|
||||
name: "{{ secgroup_name }}"
|
||||
|
||||
- name: Test port binding config (runs from train release sdk > 0.28)
|
||||
block:
|
||||
- name: Create port (with binding profile)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
binding_profile: "{{ binding_profile }}"
|
||||
register: port
|
||||
|
||||
- name: Assert binding:profile exists in created port
|
||||
assert:
|
||||
that: "port.port['binding_profile']"
|
||||
|
||||
- debug: var=port
|
||||
|
||||
- name: Delete port (with binding profile)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ port_name }}"
|
||||
when: sdk_version is version(0.28, '>')
|
||||
|
||||
- name: Delete subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
dummy_value: 'test-value'
|
||||
dummy_value_updated: 'test-value-updated'
|
||||
@@ -1,142 +0,0 @@
|
||||
---
|
||||
- name: 'Create project with properties - CHECK_MODE'
|
||||
check_mode: yes
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: dummy description
|
||||
domain_id: default
|
||||
enabled: True
|
||||
properties:
|
||||
dummy_key: '{{ dummy_value }}'
|
||||
register: create_project_cm
|
||||
- assert:
|
||||
that:
|
||||
- create_project_cm is successful
|
||||
- create_project_cm is changed
|
||||
|
||||
- name: 'Create project with properties'
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: dummy description
|
||||
domain_id: default
|
||||
enabled: True
|
||||
properties:
|
||||
dummy_key: '{{ dummy_value }}'
|
||||
register: create_project
|
||||
- assert:
|
||||
that:
|
||||
- create_project is successful
|
||||
- create_project is changed
|
||||
- '"project" in create_project'
|
||||
- '"dummy_key" in create_project["project"]'
|
||||
- create_project["project"].dummy_key == dummy_value
|
||||
|
||||
- name: 'Create project with properties (retry - no change) - CHECK_MODE'
|
||||
check_mode: yes
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: dummy description
|
||||
domain_id: default
|
||||
enabled: True
|
||||
properties:
|
||||
dummy_key: '{{ dummy_value }}'
|
||||
register: create_project_retry_cm
|
||||
- assert:
|
||||
that:
|
||||
- create_project_retry_cm is successful
|
||||
- create_project_retry_cm is not changed
|
||||
|
||||
- name: 'Create project with properties (retry - no change)'
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: dummy description
|
||||
domain_id: default
|
||||
enabled: True
|
||||
properties:
|
||||
dummy_key: '{{ dummy_value }}'
|
||||
register: create_project_retry
|
||||
- assert:
|
||||
that:
|
||||
- create_project_retry is successful
|
||||
- create_project_retry is not changed
|
||||
- '"project" in create_project_retry'
|
||||
- '"dummy_key" in create_project_retry["project"]'
|
||||
- create_project_retry["project"].dummy_key == dummy_value
|
||||
|
||||
- name: 'Update project with properties - CHECK_MODE'
|
||||
check_mode: yes
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: new description
|
||||
properties:
|
||||
dummy_key: '{{ dummy_value_updated }}'
|
||||
register: updated_project_cm
|
||||
- assert:
|
||||
that:
|
||||
- updated_project_cm is successful
|
||||
- updated_project_cm is changed
|
||||
|
||||
- name: 'Update project with properties'
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: new description
|
||||
properties:
|
||||
dummy_key: '{{ dummy_value_updated }}'
|
||||
register: updated_project
|
||||
- assert:
|
||||
that:
|
||||
- updated_project is successful
|
||||
- updated_project is changed
|
||||
- '"project" in updated_project'
|
||||
- '"dummy_key" in updated_project["project"]'
|
||||
- updated_project["project"].dummy_key == dummy_value_updated
|
||||
|
||||
- name: 'Update project with properties (retry - no change) - CHECK_MODE'
|
||||
check_mode: yes
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: new description
|
||||
properties:
|
||||
dummy_key: '{{ dummy_value_updated }}'
|
||||
register: updated_project_retry_cm
|
||||
- assert:
|
||||
that:
|
||||
- updated_project_retry_cm is successful
|
||||
- updated_project_retry_cm is not changed
|
||||
|
||||
- name: 'Update project with properties (retry - no change)'
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: new description
|
||||
properties:
|
||||
dummy_key: '{{ dummy_value_updated }}'
|
||||
register: updated_project_retry
|
||||
- assert:
|
||||
that:
|
||||
- updated_project_retry is successful
|
||||
- updated_project_retry is not changed
|
||||
- '"project" in updated_project_retry'
|
||||
- '"dummy_key" in updated_project_retry["project"]'
|
||||
- updated_project_retry["project"].dummy_key == dummy_value_updated
|
||||
|
||||
- name: Delete project with properties
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_project
|
||||
19
ci/roles/recordset/defaults/main.yml
Normal file
19
ci/roles/recordset/defaults/main.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
dns_zone_name: test.dns.zone.
|
||||
recordset_name: testrecordset.test.dns.zone.
|
||||
records: ['10.0.0.0']
|
||||
updated_records: ['10.1.1.1']
|
||||
|
||||
recordset_fields:
|
||||
- action
|
||||
- created_at
|
||||
- description
|
||||
- id
|
||||
- links
|
||||
- name
|
||||
- project_id
|
||||
- records
|
||||
- status
|
||||
- ttl
|
||||
- type
|
||||
- zone_id
|
||||
- zone_name
|
||||
112
ci/roles/recordset/tasks/main.yml
Normal file
112
ci/roles/recordset/tasks/main.yml
Normal file
@@ -0,0 +1,112 @@
|
||||
- name: Ensure DNS zone not present before tests
|
||||
openstack.cloud.dns_zone:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ dns_zone_name }}"
|
||||
zone_type: "primary"
|
||||
email: test@example.net
|
||||
state: absent
|
||||
|
||||
- name: Ensure dns zone
|
||||
openstack.cloud.dns_zone:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ dns_zone_name }}"
|
||||
zone_type: "primary"
|
||||
email: test@example.net
|
||||
register: dns_zone
|
||||
|
||||
- name: Create a recordset
|
||||
openstack.cloud.recordset:
|
||||
cloud: "{{ cloud }}"
|
||||
zone: "{{ dns_zone.zone.name }}"
|
||||
name: "{{ recordset_name }}"
|
||||
recordset_type: "a"
|
||||
records: "{{ records }}"
|
||||
register: recordset
|
||||
|
||||
- name: Verify recordset info
|
||||
assert:
|
||||
that:
|
||||
- recordset is changed
|
||||
- recordset["recordset"].name == recordset_name
|
||||
- recordset["recordset"].zone_name == dns_zone.zone.name
|
||||
- recordset["recordset"].records == records
|
||||
|
||||
- name: Assert recordset fields
|
||||
assert:
|
||||
that: item in recordset.recordset
|
||||
loop: "{{ recordset_fields }}"
|
||||
|
||||
- name: Create identical recordset
|
||||
openstack.cloud.recordset:
|
||||
cloud: "{{ cloud }}"
|
||||
zone: "{{ dns_zone.zone.name }}"
|
||||
name: "{{ recordset_name }}"
|
||||
recordset_type: "a"
|
||||
records: "{{ records }}"
|
||||
register: recordset
|
||||
|
||||
- name: Assert recordset not changed
|
||||
assert:
|
||||
that:
|
||||
- recordset is not changed
|
||||
|
||||
- name: Assert recordset fields
|
||||
assert:
|
||||
that: item in recordset.recordset
|
||||
loop: "{{ recordset_fields }}"
|
||||
|
||||
- name: Update a recordset
|
||||
openstack.cloud.recordset:
|
||||
cloud: "{{ cloud }}"
|
||||
zone: "{{ dns_zone.zone.name }}"
|
||||
name: "{{ recordset_name }}"
|
||||
recordset_type: "a"
|
||||
records: "{{ updated_records }}"
|
||||
description: "new test recordset"
|
||||
register: recordset
|
||||
|
||||
- name: Verify recordset info
|
||||
assert:
|
||||
that:
|
||||
- recordset is changed
|
||||
- recordset["recordset"].zone_name == dns_zone.zone.name
|
||||
- recordset["recordset"].name == recordset_name
|
||||
- recordset["recordset"].records == updated_records
|
||||
|
||||
- name: Assert recordset fields
|
||||
assert:
|
||||
that: item in recordset.recordset
|
||||
loop: "{{ recordset_fields }}"
|
||||
|
||||
- name: Delete recordset
|
||||
openstack.cloud.recordset:
|
||||
cloud: "{{ cloud }}"
|
||||
zone: "{{ dns_zone.zone.name }}"
|
||||
name: "{{ recordset.recordset.name }}"
|
||||
state: absent
|
||||
register: deleted_recordset
|
||||
|
||||
- name: Verify recordset deletion
|
||||
assert:
|
||||
that:
|
||||
- deleted_recordset is successful
|
||||
- deleted_recordset is changed
|
||||
|
||||
- name: Delete unexistent recordset
|
||||
openstack.cloud.recordset:
|
||||
cloud: "{{ cloud }}"
|
||||
zone: "{{ dns_zone.zone.name }}"
|
||||
name: "{{ recordset.recordset.name }}"
|
||||
state: absent
|
||||
register: deleted_recordset
|
||||
|
||||
- name: Verify recordset deletion
|
||||
assert:
|
||||
that:
|
||||
- deleted_recordset is not changed
|
||||
|
||||
- name: Delete dns zone
|
||||
openstack.cloud.dns_zone:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ dns_zone.zone.name }}"
|
||||
state: absent
|
||||
47
ci/roles/role_assignment/tasks/main.yml
Normal file
47
ci/roles/role_assignment/tasks/main.yml
Normal file
@@ -0,0 +1,47 @@
|
||||
---
|
||||
- name: Create project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: dummy description
|
||||
domain_id: default
|
||||
enabled: True
|
||||
register: project
|
||||
|
||||
- name: Grant an admin role on the user admin in the project ansible_project
|
||||
openstack.cloud.role_assignment:
|
||||
cloud: "{{ cloud }}"
|
||||
domain: default
|
||||
project: ansible_project
|
||||
role: admin
|
||||
user: admin
|
||||
|
||||
- name: Grant an admin role on the user admin in the project ansible_project again
|
||||
openstack.cloud.role_assignment:
|
||||
cloud: "{{ cloud }}"
|
||||
domain: default
|
||||
project: ansible_project
|
||||
role: admin
|
||||
user: admin
|
||||
register: grant_again
|
||||
|
||||
- name: Ensure grant again doesn't change anything
|
||||
assert:
|
||||
that:
|
||||
- not grant_again.changed
|
||||
|
||||
- name: Revoke the admin role on the user admin in the project ansible_project
|
||||
openstack.cloud.role_assignment:
|
||||
cloud: "{{ cloud }}"
|
||||
domain: default
|
||||
project: ansible_project
|
||||
role: admin
|
||||
state: absent
|
||||
user: admin
|
||||
|
||||
- name: Delete project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_project
|
||||
@@ -15,6 +15,30 @@
|
||||
name: shade_subnet1
|
||||
cidr: 10.7.7.0/24
|
||||
|
||||
- name: Create subnet2
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
network_name: "{{ network_name }}"
|
||||
name: shade_subnet2
|
||||
cidr: 10.8.8.0/24
|
||||
|
||||
- name: Create subnet3
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
network_name: "{{ network_name }}"
|
||||
name: shade_subnet3
|
||||
cidr: 10.9.9.0/24
|
||||
|
||||
- name: Create subnet4
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
network_name: "{{ network_name }}"
|
||||
name: shade_subnet4
|
||||
cidr: 10.10.10.0/24
|
||||
|
||||
- name: Create router
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
@@ -29,6 +53,19 @@
|
||||
interfaces:
|
||||
- shade_subnet1
|
||||
|
||||
- name: Update router (add interface) again
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ router_name }}"
|
||||
interfaces:
|
||||
- shade_subnet1
|
||||
register: result
|
||||
|
||||
- name: Assert idempotent module
|
||||
assert:
|
||||
that: result is not changed
|
||||
|
||||
- name: Gather routers info
|
||||
openstack.cloud.routers_info:
|
||||
cloud: "{{ cloud }}"
|
||||
@@ -43,6 +80,93 @@
|
||||
- "result.openstack_routers.0.name == router_name"
|
||||
- (result.openstack_routers.0.interfaces_info|length) == 1
|
||||
|
||||
- name: Update router (change interfaces)
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ router_name }}"
|
||||
interfaces:
|
||||
- net: '{{ network_name }}'
|
||||
subnet: shade_subnet2
|
||||
portip: 10.8.8.1
|
||||
- net: '{{ network_name }}'
|
||||
subnet: shade_subnet3
|
||||
- shade_subnet4
|
||||
|
||||
- name: Update router (change interfaces) again
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ router_name }}"
|
||||
interfaces:
|
||||
- net: '{{ network_name }}'
|
||||
subnet: shade_subnet2
|
||||
portip: 10.8.8.1
|
||||
- net: '{{ network_name }}'
|
||||
subnet: shade_subnet3
|
||||
- shade_subnet4
|
||||
register: result
|
||||
|
||||
- name: Assert idempotent module
|
||||
assert:
|
||||
that: result is not changed
|
||||
|
||||
- name: Gather routers info
|
||||
openstack.cloud.routers_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ router_name }}"
|
||||
filters:
|
||||
admin_state_up: true
|
||||
register: result
|
||||
|
||||
- name: Verify routers info
|
||||
assert:
|
||||
that:
|
||||
- "result.openstack_routers.0.name == router_name"
|
||||
- (result.openstack_routers.0.interfaces_info|length) == 3
|
||||
- result.openstack_routers.0.interfaces_info|map(attribute='ip_address')|sort|list ==
|
||||
['10.10.10.1', '10.8.8.1', '10.9.9.1']
|
||||
|
||||
- name: Update router (remove interface)
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ router_name }}"
|
||||
interfaces:
|
||||
- net: '{{ network_name }}'
|
||||
subnet: shade_subnet1
|
||||
portip: 10.7.7.1
|
||||
|
||||
- name: Update router (remove interface) again
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ router_name }}"
|
||||
interfaces:
|
||||
- net: '{{ network_name }}'
|
||||
subnet: shade_subnet1
|
||||
portip: 10.7.7.1
|
||||
register: result
|
||||
|
||||
- name: Assert idempotent module
|
||||
assert:
|
||||
that: result is not changed
|
||||
|
||||
- name: Gather routers info
|
||||
openstack.cloud.routers_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ router_name }}"
|
||||
filters:
|
||||
admin_state_up: true
|
||||
register: result
|
||||
|
||||
- name: Verify routers info
|
||||
assert:
|
||||
that:
|
||||
- "result.openstack_routers.0.name == router_name"
|
||||
- (result.openstack_routers.0.interfaces_info|length) == 1
|
||||
- result.openstack_routers.0.interfaces_info.0.ip_address == '10.7.7.1'
|
||||
|
||||
# Admin operation
|
||||
- name: Create external network
|
||||
openstack.cloud.network:
|
||||
@@ -53,12 +177,12 @@
|
||||
when:
|
||||
- network_external
|
||||
|
||||
- name: Create subnet2
|
||||
- name: Create subnet5
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
network_name: "{{ external_network_name }}"
|
||||
name: shade_subnet2
|
||||
name: shade_subnet5
|
||||
cidr: 10.6.6.0/24
|
||||
when:
|
||||
- network_external
|
||||
@@ -88,6 +212,142 @@
|
||||
- "result.openstack_routers.0.name == router_name"
|
||||
- (result.openstack_routers.0.interfaces_info|length) == 1
|
||||
|
||||
- name: Update router (change external fixed ips)
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ router_name }}"
|
||||
interfaces:
|
||||
- shade_subnet1
|
||||
network: "{{ external_network_name }}"
|
||||
external_fixed_ips:
|
||||
- subnet: shade_subnet5
|
||||
ip: 10.6.6.100
|
||||
when:
|
||||
- network_external
|
||||
|
||||
- name: Gather routers info
|
||||
openstack.cloud.routers_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ router_name }}"
|
||||
filters:
|
||||
admin_state_up: true
|
||||
register: result
|
||||
|
||||
- name: Verify routers info
|
||||
assert:
|
||||
that:
|
||||
- "result.openstack_routers.0.name == router_name"
|
||||
- (result.openstack_routers.0.external_gateway_info.external_fixed_ips|length) == 1
|
||||
- result.openstack_routers.0.external_gateway_info.external_fixed_ips.0.ip_address == "10.6.6.100"
|
||||
when:
|
||||
- network_external
|
||||
|
||||
- name: Update router (add external fixed ips)
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ router_name }}"
|
||||
interfaces:
|
||||
- shade_subnet1
|
||||
network: "{{ external_network_name }}"
|
||||
external_fixed_ips:
|
||||
- subnet: shade_subnet5
|
||||
ip: 10.6.6.100
|
||||
- subnet: shade_subnet5
|
||||
ip: 10.6.6.101
|
||||
when:
|
||||
- network_external
|
||||
|
||||
- name: Update router (add external fixed ips) again
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ router_name }}"
|
||||
interfaces:
|
||||
- shade_subnet1
|
||||
network: "{{ external_network_name }}"
|
||||
external_fixed_ips:
|
||||
- subnet: shade_subnet5
|
||||
ip: 10.6.6.100
|
||||
- subnet: shade_subnet5
|
||||
ip: 10.6.6.101
|
||||
when:
|
||||
- network_external
|
||||
register: result
|
||||
|
||||
- name: Assert idempotent module
|
||||
assert:
|
||||
that: result is not changed
|
||||
|
||||
- name: Gather routers info
|
||||
openstack.cloud.routers_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ router_name }}"
|
||||
filters:
|
||||
admin_state_up: true
|
||||
register: result
|
||||
|
||||
- name: Verify routers info
|
||||
assert:
|
||||
that:
|
||||
- "result.openstack_routers.0.name == router_name"
|
||||
- (result.openstack_routers.0.external_gateway_info.external_fixed_ips|length) == 2
|
||||
- result.openstack_routers.0.external_gateway_info.external_fixed_ips|map(attribute='ip_address')|sort|list ==
|
||||
["10.6.6.100", "10.6.6.101"]
|
||||
when:
|
||||
- network_external
|
||||
|
||||
- name: Update router (remove external fixed ips)
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ router_name }}"
|
||||
interfaces:
|
||||
- shade_subnet1
|
||||
network: "{{ external_network_name }}"
|
||||
external_fixed_ips:
|
||||
- subnet: shade_subnet5
|
||||
ip: 10.6.6.101
|
||||
when:
|
||||
- network_external
|
||||
|
||||
- name: Update router (remove external fixed ips) again
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ router_name }}"
|
||||
interfaces:
|
||||
- shade_subnet1
|
||||
network: "{{ external_network_name }}"
|
||||
external_fixed_ips:
|
||||
- subnet: shade_subnet5
|
||||
ip: 10.6.6.101
|
||||
when:
|
||||
- network_external
|
||||
register: result
|
||||
|
||||
- name: Assert idempotent module
|
||||
assert:
|
||||
that: result is not changed
|
||||
|
||||
- name: Gather routers info
|
||||
openstack.cloud.routers_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ router_name }}"
|
||||
filters:
|
||||
admin_state_up: true
|
||||
register: result
|
||||
|
||||
- name: Verify routers info
|
||||
assert:
|
||||
that:
|
||||
- "result.openstack_routers.0.name == router_name"
|
||||
- (result.openstack_routers.0.external_gateway_info.external_fixed_ips|length) == 1
|
||||
- result.openstack_routers.0.external_gateway_info.external_fixed_ips.0.ip_address == "10.6.6.101"
|
||||
when:
|
||||
- network_external
|
||||
|
||||
- name: Delete router
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
@@ -105,6 +365,24 @@
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: shade_subnet2
|
||||
|
||||
- name: Delete subnet3
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: shade_subnet3
|
||||
|
||||
- name: Delete subnet4
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: shade_subnet4
|
||||
|
||||
- name: Delete subnet5
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: shade_subnet5
|
||||
when:
|
||||
- network_external
|
||||
|
||||
|
||||
@@ -32,6 +32,26 @@
|
||||
protocol: tcp
|
||||
remote_ip_prefix: 0.0.0.0/0
|
||||
|
||||
- name: Create TCP rule again with port range (1, 65535)
|
||||
openstack.cloud.security_group_rule:
|
||||
cloud: "{{ cloud }}"
|
||||
security_group: "{{ secgroup_name }}"
|
||||
state: present
|
||||
protocol: tcp
|
||||
port_range_min: 1
|
||||
port_range_max: 65535
|
||||
remote_ip_prefix: 0.0.0.0/0
|
||||
|
||||
- name: Create TCP rule again with port range (-1, -1)
|
||||
openstack.cloud.security_group_rule:
|
||||
cloud: "{{ cloud }}"
|
||||
security_group: "{{ secgroup_name }}"
|
||||
state: present
|
||||
protocol: tcp
|
||||
port_range_min: -1
|
||||
port_range_max: -1
|
||||
remote_ip_prefix: 0.0.0.0/0
|
||||
|
||||
- name: Create empty UDP rule
|
||||
openstack.cloud.security_group_rule:
|
||||
cloud: "{{ cloud }}"
|
||||
@@ -40,6 +60,26 @@
|
||||
protocol: udp
|
||||
remote_ip_prefix: 0.0.0.0/0
|
||||
|
||||
- name: Create UDP rule again with port range (1, 65535)
|
||||
openstack.cloud.security_group_rule:
|
||||
cloud: "{{ cloud }}"
|
||||
security_group: "{{ secgroup_name }}"
|
||||
state: present
|
||||
protocol: udp
|
||||
port_range_min: 1
|
||||
port_range_max: 65535
|
||||
remote_ip_prefix: 0.0.0.0/0
|
||||
|
||||
- name: Create UDP rule again with port range (-1, -1)
|
||||
openstack.cloud.security_group_rule:
|
||||
cloud: "{{ cloud }}"
|
||||
security_group: "{{ secgroup_name }}"
|
||||
state: present
|
||||
protocol: udp
|
||||
port_range_min: -1
|
||||
port_range_max: -1
|
||||
remote_ip_prefix: 0.0.0.0/0
|
||||
|
||||
- name: Create HTTP rule
|
||||
openstack.cloud.security_group_rule:
|
||||
cloud: "{{ cloud }}"
|
||||
@@ -61,6 +101,71 @@
|
||||
remote_ip_prefix: 0.0.0.0/0
|
||||
direction: egress
|
||||
|
||||
- name: List all available rules of all security groups in a project
|
||||
openstack.cloud.security_group_rule_info:
|
||||
cloud: "{{ cloud }}"
|
||||
when: sdk_version is version("0.32", '>=')
|
||||
register: test_sec_rules
|
||||
|
||||
- name: Check - List all available rules of all security groups in a project
|
||||
assert:
|
||||
that:
|
||||
- test_sec_rules.security_group_rules | length > 0
|
||||
when: sdk_version is version("0.32", '>=')
|
||||
|
||||
- name: List all available rules of a specific security group
|
||||
openstack.cloud.security_group_rule_info:
|
||||
cloud: "{{ cloud }}"
|
||||
security_group: "{{ secgroup_name }}"
|
||||
register: test_sec_rule1
|
||||
|
||||
- name: Check - List all available rules of a specific security group
|
||||
assert:
|
||||
that:
|
||||
- test_sec_rule1.security_group_rules | length > 0
|
||||
|
||||
- name: List all available rules with filters
|
||||
openstack.cloud.security_group_rule_info:
|
||||
cloud: "{{ cloud }}"
|
||||
security_group: "{{ secgroup_name }}"
|
||||
protocol: tcp
|
||||
port_range_min: 80
|
||||
port_range_max: 80
|
||||
remote_ip_prefix: 0.0.0.0/0
|
||||
when: sdk_version is version("0.32", '>=')
|
||||
register: test_sec_rule
|
||||
|
||||
- name: Check - List all available rules with filters
|
||||
assert:
|
||||
that:
|
||||
- test_sec_rule.security_group_rules | length == 1
|
||||
when: sdk_version is version("0.32", '>=')
|
||||
|
||||
- name: List all security groups of a project
|
||||
openstack.cloud.security_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: test_sec_groups
|
||||
|
||||
- name: Check - List all security groups of a project
|
||||
assert:
|
||||
that:
|
||||
- test_sec_groups.security_groups | length > 0
|
||||
|
||||
- name: Filter security group by name
|
||||
openstack.cloud.security_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ secgroup_name }}"
|
||||
register: test_sec_group
|
||||
|
||||
- name: Check - List all security groups of a project
|
||||
assert:
|
||||
that:
|
||||
- test_sec_group.security_groups | length == 1
|
||||
- test_sec_group.security_groups[0]['name'] == secgroup_name
|
||||
# This fails on Stein only
|
||||
when: sdk_version is version("0.36.5", '>=')
|
||||
|
||||
|
||||
- name: Delete empty ICMP rule
|
||||
openstack.cloud.security_group_rule:
|
||||
cloud: "{{ cloud }}"
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
server_network: private
|
||||
server_name: ansible_server
|
||||
server_alt_network: private_alt
|
||||
server_alt_subnet: subnet_alt
|
||||
server_alt_name: ansible_server_alt
|
||||
flavor: m1.tiny
|
||||
floating_ip_pool_name: public
|
||||
boot_volume_size: 5
|
||||
|
||||
@@ -14,6 +14,16 @@
|
||||
|
||||
- debug: var=server
|
||||
|
||||
- name: Get info about all servers
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: info
|
||||
|
||||
- name: Check info about servers
|
||||
assert:
|
||||
that:
|
||||
info.openstack_servers|length > 0
|
||||
|
||||
- name: Delete server with meta as CSV
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud }}"
|
||||
@@ -21,6 +31,16 @@
|
||||
name: "{{ server_name }}"
|
||||
wait: true
|
||||
|
||||
- name: Get info about all servers
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: info
|
||||
|
||||
- name: Check info about no servers
|
||||
assert:
|
||||
that:
|
||||
info.openstack_servers|length == 0
|
||||
|
||||
- name: Create server with meta as dict
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud }}"
|
||||
@@ -38,6 +58,17 @@
|
||||
|
||||
- debug: var=server
|
||||
|
||||
- name: Get info about one server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info
|
||||
|
||||
- name: Check info about server name
|
||||
assert:
|
||||
that:
|
||||
info.openstack_servers[0].name == "{{ server_name }}"
|
||||
|
||||
- name: Delete server with meta as dict
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud }}"
|
||||
@@ -60,6 +91,18 @@
|
||||
|
||||
- debug: var=server
|
||||
|
||||
- name: Get detailed info about one server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
detailed: true
|
||||
register: info
|
||||
|
||||
- name: Check info about server image name
|
||||
assert:
|
||||
that:
|
||||
info.openstack_servers[0].image.name == "{{ image }}"
|
||||
|
||||
- name: Delete server (FIP from pool/network)
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud }}"
|
||||
@@ -90,3 +133,48 @@
|
||||
state: absent
|
||||
name: "{{ server_name }}"
|
||||
wait: true
|
||||
- name: Create a minimal server
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ server_name }}"
|
||||
image: "{{ image }}"
|
||||
flavor: "{{ flavor }}"
|
||||
network: "{{ server_network }}"
|
||||
auto_floating_ip: false
|
||||
wait: true
|
||||
register: server
|
||||
|
||||
- debug: var=server
|
||||
|
||||
- name: Get info about servers in all projects
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
all_projects: true
|
||||
register: info
|
||||
|
||||
- name: Check info about servers in all projects
|
||||
assert:
|
||||
that:
|
||||
info.openstack_servers|length > 0
|
||||
|
||||
- name: Get info about one server in all projects
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
all_projects: true
|
||||
register: info
|
||||
|
||||
- name: Check info about one server in all projects
|
||||
assert:
|
||||
that:
|
||||
info.openstack_servers|length > 0
|
||||
|
||||
- name: Delete minimal server
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ server_name }}"
|
||||
wait: true
|
||||
|
||||
- include_tasks: server_actions.yml
|
||||
|
||||
612
ci/roles/server/tasks/server_actions.yml
Normal file
612
ci/roles/server/tasks/server_actions.yml
Normal file
@@ -0,0 +1,612 @@
|
||||
- name: Create server
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ server_name }}"
|
||||
image: "{{ image }}"
|
||||
flavor: "{{ flavor }}"
|
||||
network: "{{ server_network }}"
|
||||
auto_floating_ip: false
|
||||
wait: true
|
||||
register: server
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info1
|
||||
|
||||
- name: Ensure status for server is ACTIVE
|
||||
assert:
|
||||
that:
|
||||
- info1.openstack_servers.0.status == 'ACTIVE'
|
||||
|
||||
- name: Stop server
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
action: stop
|
||||
wait: true
|
||||
register: server
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info2
|
||||
|
||||
- name: Ensure status for server is SHUTOFF
|
||||
assert:
|
||||
that:
|
||||
- info2.openstack_servers.0.status == 'SHUTOFF'
|
||||
- server is changed
|
||||
|
||||
- name: Stop server again
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
action: stop
|
||||
wait: true
|
||||
register: server
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info3
|
||||
|
||||
- name: Ensure status for server is SHUTOFF
|
||||
assert:
|
||||
that:
|
||||
- info3.openstack_servers.0.status == 'SHUTOFF'
|
||||
- server is not changed
|
||||
|
||||
- name: Start server
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
action: start
|
||||
wait: true
|
||||
register: server
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info4
|
||||
|
||||
- name: Ensure status for server is ACTIVE
|
||||
assert:
|
||||
that:
|
||||
- info4.openstack_servers.0.status == 'ACTIVE'
|
||||
- server is changed
|
||||
|
||||
- name: Start server again
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
action: start
|
||||
wait: true
|
||||
register: server
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info5
|
||||
|
||||
- name: Ensure status for server is ACTIVE
|
||||
assert:
|
||||
that:
|
||||
- info5.openstack_servers.0.status == 'ACTIVE'
|
||||
- server is not changed
|
||||
|
||||
- name: Pause server
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
action: pause
|
||||
wait: true
|
||||
register: server
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info6
|
||||
|
||||
- name: Ensure status for server is PAUSED
|
||||
assert:
|
||||
that:
|
||||
- info6.openstack_servers.0.status == 'PAUSED'
|
||||
- server is changed
|
||||
|
||||
- name: Pause server again
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
action: pause
|
||||
wait: true
|
||||
register: server
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info7
|
||||
|
||||
- name: Ensure status for server is PAUSED
|
||||
assert:
|
||||
that:
|
||||
- info7.openstack_servers.0.status == 'PAUSED'
|
||||
- server is not changed
|
||||
|
||||
- name: Unpause server
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
action: unpause
|
||||
wait: true
|
||||
register: server
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info8
|
||||
|
||||
- name: Ensure status for server is ACTIVE
|
||||
assert:
|
||||
that:
|
||||
- info8.openstack_servers.0.status == 'ACTIVE'
|
||||
- server is changed
|
||||
|
||||
- name: Unpause server again
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
action: unpause
|
||||
wait: true
|
||||
register: server
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info9
|
||||
|
||||
- name: Ensure status for server is ACTIVE
|
||||
assert:
|
||||
that:
|
||||
- info9.openstack_servers.0.status == 'ACTIVE'
|
||||
- server is not changed
|
||||
|
||||
- name: Lock server
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
action: lock
|
||||
wait: true
|
||||
register: server
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info10
|
||||
|
||||
- name: Ensure status for server is ACTIVE
|
||||
assert:
|
||||
that:
|
||||
- info10.openstack_servers.0.status == 'ACTIVE'
|
||||
# not in all versions 'locked' is supported
|
||||
- >-
|
||||
(info10.openstack_server[0]['locked'] is defined and
|
||||
info10.openstack_server[0]['locked']|bool) or
|
||||
(info10.openstack_server[0]['locked'] is not defined)
|
||||
- server is changed
|
||||
|
||||
- name: Lock server again
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
action: lock
|
||||
wait: true
|
||||
register: server
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info11
|
||||
|
||||
- name: Ensure status for server is ACTIVE
|
||||
assert:
|
||||
that:
|
||||
- info11.openstack_servers.0.status == 'ACTIVE'
|
||||
# not in all versions 'locked' is supported
|
||||
- >-
|
||||
(info11.openstack_server[0]['locked'] is defined and
|
||||
info11.openstack_server[0]['locked']|bool) or
|
||||
(info11.openstack_server[0]['locked'] is not defined)
|
||||
- server is changed # no support for lock idempotency
|
||||
|
||||
- name: Unock server
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
action: unlock
|
||||
wait: true
|
||||
register: server
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info12
|
||||
|
||||
- name: Ensure status for server is ACTIVE
|
||||
assert:
|
||||
that:
|
||||
- info12.openstack_servers.0.status == 'ACTIVE'
|
||||
# not in all versions 'locked' is supported
|
||||
- >-
|
||||
(info12.openstack_server[0]['locked'] is defined and
|
||||
not info12.openstack_server[0]['locked']|bool) or
|
||||
(info12.openstack_server[0]['locked'] is not defined)
|
||||
- server is changed
|
||||
|
||||
- name: Unlock server again
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
action: unlock
|
||||
wait: true
|
||||
register: server
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info13
|
||||
|
||||
- name: Ensure status for server is ACTIVE
|
||||
assert:
|
||||
that:
|
||||
- info13.openstack_servers.0.status == 'ACTIVE'
|
||||
- server is changed # no support for unlock idempotency
|
||||
# not in all versions 'locked' is supported
|
||||
- >-
|
||||
(info13.openstack_server[0]['locked'] is defined and
|
||||
not info13.openstack_server[0]['locked']|bool) or
|
||||
(info13.openstack_server[0]['locked'] is not defined)
|
||||
|
||||
- name: Suspend server
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
action: suspend
|
||||
wait: true
|
||||
register: server
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info14
|
||||
|
||||
- name: Ensure status for server is SUSPENDED
|
||||
assert:
|
||||
that:
|
||||
- info14.openstack_servers.0.status == 'SUSPENDED'
|
||||
- server is changed
|
||||
|
||||
- name: Suspend server again
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
action: suspend
|
||||
wait: true
|
||||
register: server
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info15
|
||||
|
||||
- name: Ensure status for server is SUSPENDED
|
||||
assert:
|
||||
that:
|
||||
- info15.openstack_servers.0.status == 'SUSPENDED'
|
||||
- server is not changed
|
||||
|
||||
- name: Resume server
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
action: resume
|
||||
wait: true
|
||||
register: server
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info16
|
||||
|
||||
- name: Ensure status for server is ACTIVE
|
||||
assert:
|
||||
that:
|
||||
- info16.openstack_servers.0.status == 'ACTIVE'
|
||||
- server is changed
|
||||
|
||||
- name: Resume server again
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
action: resume
|
||||
wait: true
|
||||
register: server
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info17
|
||||
|
||||
- name: Ensure status for server is ACTIVE
|
||||
assert:
|
||||
that:
|
||||
- info17.openstack_servers.0.status == 'ACTIVE'
|
||||
- server is not changed
|
||||
|
||||
- name: Rebuild server - error
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
action: rebuild
|
||||
wait: true
|
||||
register: server
|
||||
ignore_errors: true
|
||||
|
||||
- name: Ensure server rebuild failed
|
||||
assert:
|
||||
that:
|
||||
- server is failed
|
||||
- "'missing: image' in server.msg "
|
||||
|
||||
- name: Rebuild server
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
image: "{{ image }}"
|
||||
action: rebuild
|
||||
wait: true
|
||||
register: server
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info18
|
||||
|
||||
- name: Ensure status for server is ACTIVE
|
||||
assert:
|
||||
that:
|
||||
- info18.openstack_servers.0.status in ('ACTIVE', 'REBUILD')
|
||||
- server is changed
|
||||
|
||||
- name: Rebuild server with admin password
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
image: "{{ image }}"
|
||||
action: rebuild
|
||||
wait: true
|
||||
admin_password: random
|
||||
register: server
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info19
|
||||
|
||||
- name: Ensure status for server is ACTIVE
|
||||
assert:
|
||||
that:
|
||||
- info19.openstack_servers.0.status in ('ACTIVE', 'REBUILD')
|
||||
- server is changed
|
||||
|
||||
- name: Shelve server
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
action: shelve
|
||||
wait: true
|
||||
register: server
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info20
|
||||
|
||||
- name: Ensure status for server is SHELVED or SHELVED_OFFLOADED
|
||||
assert:
|
||||
that:
|
||||
- info20.openstack_servers.0.status in ['SHELVED', 'SHELVED_OFFLOADED']
|
||||
- server is changed
|
||||
|
||||
- name: Shelve offload server
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
action: shelve_offload
|
||||
wait: true
|
||||
register: server
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info21
|
||||
|
||||
- name: Ensure status for server is SHELVED_OFFLOADED
|
||||
# no change if server has been offloaded automatically after first shelve command
|
||||
assert:
|
||||
that:
|
||||
- info21.openstack_servers.0.status == 'SHELVED_OFFLOADED'
|
||||
|
||||
- name: Shelve offload server again
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
action: shelve_offload
|
||||
wait: true
|
||||
register: server
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info22
|
||||
|
||||
- name: Ensure status for server is SHELVED_OFFLOADED
|
||||
assert:
|
||||
that:
|
||||
- info22.openstack_servers.0.status == 'SHELVED_OFFLOADED'
|
||||
- server is not changed
|
||||
|
||||
- name: Unshelve server
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
action: unshelve
|
||||
wait: true
|
||||
register: server
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info23
|
||||
|
||||
- name: Ensure status for server is ACTIVE
|
||||
assert:
|
||||
that:
|
||||
- info23.openstack_servers.0.status == 'ACTIVE'
|
||||
- server is changed
|
||||
|
||||
- name: Unshelve server again
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
action: unshelve
|
||||
wait: true
|
||||
register: server
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
register: info24
|
||||
|
||||
- name: Ensure status for server is ACTIVE
|
||||
assert:
|
||||
that:
|
||||
- info24.openstack_servers.0.status == 'ACTIVE'
|
||||
- server is not changed
|
||||
|
||||
- name: Create network for alternate server
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud_alt }}"
|
||||
name: "{{ server_alt_network }}"
|
||||
state: present
|
||||
|
||||
- name: Create subnet for alternate server
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud_alt }}"
|
||||
network_name: "{{ server_alt_network }}"
|
||||
name: "{{ server_alt_subnet }}"
|
||||
state: present
|
||||
cidr: 192.168.0.0/24
|
||||
|
||||
- name: Create server in alternate project
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud_alt }}"
|
||||
state: present
|
||||
name: "{{ server_alt_name }}"
|
||||
image: "{{ image }}"
|
||||
flavor: "{{ flavor }}"
|
||||
network: "{{ server_alt_network }}"
|
||||
auto_floating_ip: false
|
||||
wait: true
|
||||
register: server_alt
|
||||
|
||||
- name: Get info about server in alternate project
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud_alt }}"
|
||||
server: "{{ server_alt_name }}"
|
||||
register: info25
|
||||
|
||||
- name: Ensure status for server in alternate project is ACTIVE
|
||||
assert:
|
||||
that:
|
||||
- info25.openstack_servers.0.status == 'ACTIVE'
|
||||
|
||||
- name: Try to stop server in alternate project
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_alt_name }}"
|
||||
action: stop
|
||||
wait: true
|
||||
ignore_errors: true
|
||||
register: server_alt
|
||||
|
||||
- name: Ensure server was not stopped
|
||||
assert:
|
||||
that:
|
||||
- server_alt is failed
|
||||
- server_alt.msg == "Could not find server {{ server_alt_name }}"
|
||||
|
||||
- name: Stop server in alternate project with all_projects=true
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_alt_name }}"
|
||||
action: stop
|
||||
wait: true
|
||||
all_projects: True
|
||||
register: server_alt
|
||||
|
||||
- name: Get info about server in alternate project
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud_alt }}"
|
||||
server: "{{ server_alt_name }}"
|
||||
register: info26
|
||||
|
||||
- name: Ensure status for server is SHUTOFF
|
||||
assert:
|
||||
that:
|
||||
- info26.openstack_servers.0.status == 'SHUTOFF'
|
||||
- server_alt is changed
|
||||
|
||||
- name: Delete server in alternate project
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud_alt }}"
|
||||
state: absent
|
||||
name: "{{ server_alt_name }}"
|
||||
wait: true
|
||||
|
||||
- name: Delete subnet for alternate server
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud_alt }}"
|
||||
name: "{{ server_alt_subnet }}"
|
||||
state: absent
|
||||
|
||||
- name: Delete network for alternate server
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud_alt }}"
|
||||
name: "{{ server_alt_network }}"
|
||||
state: absent
|
||||
@@ -17,6 +17,19 @@
|
||||
allocation_pool_start: 192.168.0.2
|
||||
allocation_pool_end: 192.168.0.4
|
||||
|
||||
- name: Create subnet {{ subnet_name }} on network {{ network_name }} again
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
network_name: "{{ network_name }}"
|
||||
enable_dhcp: "{{ enable_subnet_dhcp }}"
|
||||
name: "{{ subnet_name }}"
|
||||
state: present
|
||||
cidr: 192.168.0.0/24
|
||||
gateway_ip: 192.168.0.1
|
||||
allocation_pool_start: 192.168.0.2
|
||||
allocation_pool_end: 192.168.0.4
|
||||
register: idem1
|
||||
|
||||
- name: Update subnet {{ subnet_name }} allocation pools
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
@@ -24,7 +37,8 @@
|
||||
name: "{{ subnet_name }}"
|
||||
state: present
|
||||
cidr: 192.168.0.0/24
|
||||
allocation_pool_start: 192.168.0.5
|
||||
gateway_ip: 192.168.0.1
|
||||
allocation_pool_start: 192.168.0.2
|
||||
allocation_pool_end: 192.168.0.8
|
||||
|
||||
- name: Get Subnet Info
|
||||
@@ -36,19 +50,17 @@
|
||||
- name: Verify Subnet Allocation Pools Exist
|
||||
assert:
|
||||
that:
|
||||
- idem1 is not changed
|
||||
- subnet_result.openstack_subnets is defined
|
||||
- subnet_result.openstack_subnets | length == 1
|
||||
- subnet_result.openstack_subnets[0].allocation_pools is defined
|
||||
- subnet_result.openstack_subnets[0].allocation_pools | length == 2
|
||||
- subnet_result.openstack_subnets[0].allocation_pools | length == 1
|
||||
|
||||
- name: Verify Subnet Allocation Pools
|
||||
assert:
|
||||
that:
|
||||
- subnet_result.openstack_subnets[0].allocation_pools | selectattr('start','equalto',item.start) | list | count > 0
|
||||
- subnet_result.openstack_subnets[0].allocation_pools | selectattr('end','equalto',item.end) | list | count > 0
|
||||
loop:
|
||||
- {start: '192.168.0.2', end: '192.168.0.4'}
|
||||
- {start: '192.168.0.5', end: '192.168.0.8'}
|
||||
- subnet_result.openstack_subnets[0].allocation_pools.0.start == '192.168.0.2'
|
||||
- subnet_result.openstack_subnets[0].allocation_pools.0.end == '192.168.0.8'
|
||||
|
||||
- name: Delete subnet {{ subnet_name }}
|
||||
openstack.cloud.subnet:
|
||||
|
||||
5
ci/roles/subnet_pool/defaults/main.yml
Normal file
5
ci/roles/subnet_pool/defaults/main.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
subnet_pool_name: "subnet_pool"
|
||||
address_scope_name: "address_scope"
|
||||
default_prefix_length: 24
|
||||
minimum_prefix_length: 10
|
||||
maximum_prefix_length: 30
|
||||
73
ci/roles/subnet_pool/tasks/main.yaml
Normal file
73
ci/roles/subnet_pool/tasks/main.yaml
Normal file
@@ -0,0 +1,73 @@
|
||||
---
|
||||
- name: Create address_scope
|
||||
openstack.cloud.address_scope:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ address_scope_name }}"
|
||||
shared: False
|
||||
ip_version: "4"
|
||||
register: create_address_scope
|
||||
|
||||
- name: Create subnet pool
|
||||
openstack.cloud.subnet_pool:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ subnet_pool_name }}"
|
||||
shared: False
|
||||
address_scope: "{{ address_scope_name }}"
|
||||
prefixes:
|
||||
- 192.168.0.0/24
|
||||
register: create_subnet_pool
|
||||
|
||||
- name: Verify subnet pool
|
||||
assert:
|
||||
that:
|
||||
- create_subnet_pool is successful
|
||||
- create_subnet_pool is changed
|
||||
- create_subnet_pool.subnet_pool.name == subnet_pool_name
|
||||
- create_subnet_pool.subnet_pool.is_shared == False
|
||||
- create_subnet_pool.subnet_pool.is_default == False
|
||||
- create_subnet_pool.subnet_pool.address_scope_id == create_address_scope.address_scope.id
|
||||
- create_subnet_pool.subnet_pool.prefixes == ['192.168.0.0/24']
|
||||
|
||||
|
||||
- name: Update subnet pool
|
||||
openstack.cloud.subnet_pool:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ subnet_pool_name }}"
|
||||
address_scope: "{{ address_scope_name }}"
|
||||
shared: False
|
||||
default_prefix_length: "{{ default_prefix_length }}"
|
||||
minimum_prefix_length: "{{ minimum_prefix_length }}"
|
||||
maximum_prefix_length: "{{ maximum_prefix_length }}"
|
||||
description: "test"
|
||||
prefixes:
|
||||
- 192.168.0.0/24
|
||||
- 192.168.1.0/24
|
||||
register: update_subnet_pool
|
||||
|
||||
- name: Verify updated subnet pool
|
||||
assert:
|
||||
that:
|
||||
- update_subnet_pool is successful
|
||||
- update_subnet_pool is changed
|
||||
- update_subnet_pool.subnet_pool.name == subnet_pool_name
|
||||
- update_subnet_pool.subnet_pool.is_shared == False
|
||||
- update_subnet_pool.subnet_pool.is_default == False
|
||||
- update_subnet_pool.subnet_pool.address_scope_id == create_address_scope.address_scope.id
|
||||
- update_subnet_pool.subnet_pool.prefixes == ['192.168.0.0/23']
|
||||
- update_subnet_pool.subnet_pool.description == 'test'
|
||||
- update_subnet_pool.subnet_pool.default_prefix_length == default_prefix_length
|
||||
- update_subnet_pool.subnet_pool.minimum_prefix_length == minimum_prefix_length
|
||||
- update_subnet_pool.subnet_pool.maximum_prefix_length == maximum_prefix_length
|
||||
|
||||
- name: Delete created subnet pool
|
||||
openstack.cloud.subnet_pool:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ subnet_pool_name }}"
|
||||
state: absent
|
||||
|
||||
|
||||
- name: Delete created address scope
|
||||
openstack.cloud.address_scope:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ address_scope_name }}"
|
||||
state: absent
|
||||
@@ -1,30 +0,0 @@
|
||||
---
|
||||
- name: Create user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
password: secret
|
||||
email: ansible.user@nowhere.net
|
||||
domain: default
|
||||
default_project: demo
|
||||
register: user
|
||||
|
||||
- debug: var=user
|
||||
|
||||
- name: Update user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
password: secret
|
||||
email: updated.ansible.user@nowhere.net
|
||||
register: updateduser
|
||||
|
||||
- debug: var=updateduser
|
||||
|
||||
- name: Delete user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_user
|
||||
@@ -8,10 +8,63 @@
|
||||
display_description: Test volume
|
||||
register: vol
|
||||
|
||||
- name: Create volume snapshot
|
||||
openstack.cloud.volume_snapshot:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
display_name: ansible_volume_snapshot
|
||||
volume: ansible_volume
|
||||
register: vol_snap
|
||||
|
||||
- name: Get snapshot info
|
||||
openstack.cloud.volume_snapshot_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_volume_snapshot
|
||||
register: snap_info
|
||||
ignore_errors: sdk_version is version('0.49', '<')
|
||||
|
||||
- name: Create volume backup
|
||||
openstack.cloud.volume_backup:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
display_name: ansible_volume_backup
|
||||
volume: ansible_volume
|
||||
register: vol_backup
|
||||
ignore_errors: sdk_version is version('0.49', '<')
|
||||
|
||||
- name: Get backup info
|
||||
openstack.cloud.volume_backup_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_volume_backup
|
||||
register: backup_info
|
||||
ignore_errors: sdk_version is version('0.49', '<')
|
||||
|
||||
- debug: var=vol
|
||||
|
||||
- debug: var=vol_backup
|
||||
|
||||
- debug: var=backup_info
|
||||
|
||||
- debug: var=snap_info
|
||||
|
||||
- name: Delete volume backup
|
||||
openstack.cloud.volume_backup:
|
||||
cloud: "{{ cloud }}"
|
||||
display_name: ansible_volume_backup
|
||||
state: absent
|
||||
ignore_errors: sdk_version is version(0.49, '<')
|
||||
|
||||
- name: Delete volume snapshot
|
||||
openstack.cloud.volume_snapshot:
|
||||
cloud: "{{ cloud }}"
|
||||
display_name: ansible_volume_snapshot
|
||||
volume: ansible_volume
|
||||
state: absent
|
||||
|
||||
- name: Delete volume
|
||||
openstack.cloud.volume:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
display_name: ansible_volume
|
||||
|
||||
- include_tasks: volume_info.yml
|
||||
|
||||
155
ci/roles/volume/tasks/volume_info.yml
Normal file
155
ci/roles/volume/tasks/volume_info.yml
Normal file
@@ -0,0 +1,155 @@
|
||||
- name: Get info about volumes and all projects for all SDK
|
||||
openstack.cloud.volume_info:
|
||||
cloud: "{{ cloud }}"
|
||||
details: true
|
||||
all_projects: true
|
||||
register: all_sdk
|
||||
ignore_errors: true
|
||||
|
||||
- name: Check info for all projects
|
||||
assert:
|
||||
that:
|
||||
# Rocky SDK doesn't have all_projects attribute
|
||||
- >-
|
||||
(all_sdk is failed and sdk_version is version(0.19, '<')) or
|
||||
all_sdk is success
|
||||
|
||||
- name: Get info about volumes for all SDK
|
||||
openstack.cloud.volume_info:
|
||||
cloud: "{{ cloud }}"
|
||||
details: true
|
||||
register: all_sdk1
|
||||
ignore_errors: true
|
||||
|
||||
- name: Check info for all SDK
|
||||
assert:
|
||||
that:
|
||||
- all_sdk1 is success
|
||||
- all_sdk1.volumes is defined
|
||||
|
||||
- name: Run tests for SDK > 0.28 (from train)
|
||||
when: sdk_version is version(0.28, '>')
|
||||
block:
|
||||
|
||||
- name: Get info about volumes
|
||||
openstack.cloud.volume_info:
|
||||
cloud: "{{ cloud }}"
|
||||
all_projects: true
|
||||
register: delete
|
||||
|
||||
- name: Clean up volumes before the test
|
||||
openstack.cloud.volume:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
display_name: "{{ vol.name }}"
|
||||
loop: "{{ delete.volumes }}"
|
||||
loop_control:
|
||||
loop_var: vol
|
||||
|
||||
- name: Create volume
|
||||
openstack.cloud.volume:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
size: 1
|
||||
display_name: ansible_test
|
||||
display_description: testci
|
||||
register: vol
|
||||
|
||||
- name: Get info about volumes
|
||||
openstack.cloud.volume_info:
|
||||
cloud: "{{ cloud }}"
|
||||
details: true
|
||||
all_projects: true
|
||||
register: info
|
||||
|
||||
- name: Check info
|
||||
assert:
|
||||
that:
|
||||
- info.volumes | selectattr("description", "equalto", "testci") | list | length == 1
|
||||
- info.volumes.0.name == 'ansible_test'
|
||||
- info.volumes.0.status == 'available'
|
||||
|
||||
- name: Get not detailed info about volumes
|
||||
openstack.cloud.volume_info:
|
||||
cloud: "{{ cloud }}"
|
||||
details: false
|
||||
all_projects: true
|
||||
register: info1
|
||||
|
||||
- name: Check info
|
||||
assert:
|
||||
that:
|
||||
- info1.volumes | selectattr("id", "equalto", "{{ info.volumes.0.id }}") | list | length == 1
|
||||
- info1.volumes.0.name == 'ansible_test'
|
||||
- info1.volumes.0.status == None
|
||||
|
||||
- name: Get info about volumes with name
|
||||
openstack.cloud.volume_info:
|
||||
cloud: "{{ cloud }}"
|
||||
details: false
|
||||
name: ansible_test
|
||||
all_projects: true
|
||||
register: info2
|
||||
|
||||
- name: Check info
|
||||
assert:
|
||||
that:
|
||||
- info2.volumes | length == 1
|
||||
- info2.volumes.0.name == 'ansible_test'
|
||||
|
||||
- name: Get info about volumes with non-existent name
|
||||
openstack.cloud.volume_info:
|
||||
cloud: "{{ cloud }}"
|
||||
details: false
|
||||
name: nothing_here
|
||||
all_projects: true
|
||||
register: info3
|
||||
|
||||
- name: Check info
|
||||
assert:
|
||||
that:
|
||||
- info3.volumes | length == 0
|
||||
|
||||
- name: Get info about volumes
|
||||
openstack.cloud.volume_info:
|
||||
cloud: "{{ cloud }}"
|
||||
details: false
|
||||
name: ansible_test
|
||||
all_projects: true
|
||||
register: info4
|
||||
|
||||
- name: Check info
|
||||
assert:
|
||||
that:
|
||||
- info4.volumes | length == 1
|
||||
- info4.volumes.0.name == 'ansible_test'
|
||||
|
||||
- name: Get info about volumes not from all projects
|
||||
openstack.cloud.volume_info:
|
||||
cloud: "{{ cloud }}"
|
||||
details: false
|
||||
name: ansible_test
|
||||
register: info4a
|
||||
|
||||
- name: Check info
|
||||
assert:
|
||||
that:
|
||||
- info4a.volumes | length == 1
|
||||
- info4a.volumes.0.name == 'ansible_test'
|
||||
|
||||
- name: Delete volume
|
||||
openstack.cloud.volume:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
display_name: ansible_test
|
||||
|
||||
- name: Get info when no volumes
|
||||
openstack.cloud.volume_info:
|
||||
cloud: "{{ cloud }}"
|
||||
all_projects: true
|
||||
register: info5
|
||||
|
||||
- name: Check info
|
||||
assert:
|
||||
that:
|
||||
- info5.volumes | selectattr("name", "equalto", "ansible_test") | list | length == 0
|
||||
@@ -6,20 +6,22 @@
|
||||
#
|
||||
# tox -e ansible [TAG ...]
|
||||
# or
|
||||
# tox -e ansible -- -c cloudX [TAG ...]
|
||||
# tox -e ansible -- -c cloudX -u cloudY [TAG ...]
|
||||
# or to use the development version of Ansible:
|
||||
# tox -e ansible -- -d -c cloudX [TAG ...]
|
||||
# tox -e ansible -- -d -c cloudX -u cloudY [TAG ...]
|
||||
#
|
||||
# USAGE:
|
||||
# run-ansible-tests.sh -e ENVDIR [-d] [-c CLOUD] [TAG ...]
|
||||
# run-ansible-tests.sh -e ENVDIR [-d] [-c CLOUD] [-u CLOUD_ALT] [TAG ...]
|
||||
#
|
||||
# PARAMETERS:
|
||||
# -d Use Ansible source repo development branch.
|
||||
# -e ENVDIR Directory of the tox environment to use for testing.
|
||||
# -c CLOUD Name of the cloud to use for testing.
|
||||
# Defaults to "devstack-admin".
|
||||
# [TAG ...] Optional list of space-separated tags to control which
|
||||
# modules are tested.
|
||||
# -d Use Ansible source repo development branch.
|
||||
# -e ENVDIR Directory of the tox environment to use for testing.
|
||||
# -c CLOUD Name of the cloud to use for testing.
|
||||
# Defaults to "devstack-admin".
|
||||
# -u CLOUD_ALT Name of another cloud to use for testing.
|
||||
# Defaults to "devstack-alt".
|
||||
# [TAG ...] Optional list of space-separated tags to control which
|
||||
# modules are tested.
|
||||
#
|
||||
# EXAMPLES:
|
||||
# # Run all Ansible tests
|
||||
@@ -31,14 +33,16 @@
|
||||
set -ex
|
||||
|
||||
CLOUD="devstack-admin"
|
||||
CLOUD_ALT="devstack-alt"
|
||||
ENVDIR=
|
||||
USE_DEV=0
|
||||
|
||||
while getopts "c:de:" opt
|
||||
while getopts "c:de:u:" opt
|
||||
do
|
||||
case $opt in
|
||||
d) USE_DEV=1 ;;
|
||||
c) CLOUD=${OPTARG} ;;
|
||||
u) CLOUD_ALT=${OPTARG} ;;
|
||||
e) ENVDIR=${OPTARG} ;;
|
||||
?) echo "Invalid option: -${OPTARG}"
|
||||
exit 1;;
|
||||
@@ -54,6 +58,16 @@ fi
|
||||
shift $((OPTIND-1))
|
||||
TAGS=$( echo "$*" | tr ' ' , )
|
||||
|
||||
# Install collections before dealing with Ansible virtual environments
|
||||
if [[ -z "$PIP_INSTALL" ]]; then
|
||||
tox -ebuild
|
||||
ansible-galaxy collection install $(ls build_artifact/openstack-cloud-*) --force
|
||||
TEST_COLLECTIONS_PATHS=${HOME}/.ansible/collections:$ANSIBLE_COLLECTIONS_PATHS
|
||||
else
|
||||
pip freeze | grep ansible-collections-openstack
|
||||
TEST_COLLECTIONS_PATHS=$VIRTUAL_ENV/share/ansible/collections:$ANSIBLE_COLLECTIONS_PATHS
|
||||
fi
|
||||
|
||||
# We need to source the current tox environment so that Ansible will
|
||||
# be setup for the correct python environment.
|
||||
source $ENVDIR/bin/activate
|
||||
@@ -96,16 +110,34 @@ then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# install collections
|
||||
tox -ebuild
|
||||
ansible-galaxy collection build --force . --output-path ./build_artifact
|
||||
ansible-galaxy collection install $(ls build_artifact/openstack-cloud-*) --force
|
||||
# In case of Octavia enabled:
|
||||
_octavia_image_path="/tmp/test-only-amphora-x64-haproxy-ubuntu-bionic.qcow2"
|
||||
if systemctl list-units --full -all | grep -Fq "devstack@o-api.service" && \
|
||||
test -f "$_octavia_image_path"
|
||||
then
|
||||
# Upload apmhora image for Octavia to test load balancers
|
||||
OCTAVIA_AMP_IMAGE_FILE=${OCTAVIA_AMP_IMAGE_FILE:-"$_octavia_image_path"}
|
||||
OCTAVIA_AMP_IMAGE_NAME=${OCTAVIA_AMP_IMAGE_NAME:-"test-only-amphora-x64-haproxy-ubuntu-bionic"}
|
||||
OCTAVIA_AMP_IMAGE_SIZE=${OCTAVIA_AMP_IMAGE_SIZE:-3}
|
||||
openstack --os-cloud=${CLOUD} image create \
|
||||
--container-format bare \
|
||||
--disk-format qcow2 \
|
||||
--private \
|
||||
--file $OCTAVIA_AMP_IMAGE_FILE \
|
||||
--project service $OCTAVIA_AMP_IMAGE_NAME
|
||||
openstack --os-cloud=${CLOUD} image set --tag amphora $OCTAVIA_AMP_IMAGE_NAME
|
||||
# End of Octavia preparement
|
||||
else
|
||||
tag_opt="$tag_opt --skip-tags loadbalancer"
|
||||
fi
|
||||
|
||||
# Discover openstackSDK version
|
||||
SDK_VER=$(python -c "import openstack; print(openstack.version.__version__)")
|
||||
pushd ci/
|
||||
# run tests
|
||||
ANSIBLE_COLLECTIONS_PATHS=${HOME}/.ansible/collections ansible-playbook \
|
||||
set -o pipefail
|
||||
ANSIBLE_COLLECTIONS_PATHS=$TEST_COLLECTIONS_PATHS ansible-playbook \
|
||||
-vvv ./run-collection.yml \
|
||||
-e "sdk_version=${SDK_VER} cloud=${CLOUD} image=${IMAGE} ${ANSIBLE_VARS}" \
|
||||
${tag_opt}
|
||||
-e "sdk_version=${SDK_VER} cloud=${CLOUD} cloud_alt=${CLOUD_ALT} image=${IMAGE} ${ANSIBLE_VARS}" \
|
||||
${tag_opt} 2>&1 | sudo tee /opt/stack/logs/test_output.log
|
||||
popd
|
||||
|
||||
@@ -4,12 +4,29 @@
|
||||
gather_facts: true
|
||||
|
||||
roles:
|
||||
- { role: address_scope, tags: address_scope }
|
||||
- { role: auth, tags: auth }
|
||||
- { role: catalog_service, tags: catalog_service }
|
||||
- { role: client_config, tags: client_config }
|
||||
- { role: dns_zone_info, tags: dns_zone_info }
|
||||
- role: object_container
|
||||
tags: object_container
|
||||
when: sdk_version is version(0.18, '>=')
|
||||
- { role: group, tags: group }
|
||||
# TODO(mordred) Reenable this once the fixed openstack.cloud.image winds up in an
|
||||
# upstream ansible release.
|
||||
# - { role: image, tags: image }
|
||||
- role: dns
|
||||
tags: dns
|
||||
when: sdk_version is version(0.28, '>=')
|
||||
- { role: endpoint, tags: endpoint }
|
||||
- { role: floating_ip_info, tags: floating_ip_info }
|
||||
- { role: host_aggregate, tags: host_aggregate }
|
||||
- { role: identity_domain_info, tags: identity_domain_info }
|
||||
- { role: identity_group_info, tags: identity_group_info }
|
||||
- { role: identity_user, tags: identity_user }
|
||||
- { role: identity_user_info, tags: identity_user_info }
|
||||
- { role: identity_role, tags: identity_role }
|
||||
- { role: identity_role_info, tags: identity_role_info }
|
||||
- { role: image, tags: image }
|
||||
- { role: image_info, tags: image_info }
|
||||
- { role: keypair, tags: keypair }
|
||||
- { role: keystone_domain, tags: keystone_domain }
|
||||
- role: keystone_mapping
|
||||
@@ -21,20 +38,34 @@
|
||||
- role: keystone_federation_protocol
|
||||
tags: keystone_federation_protocol
|
||||
when: sdk_version is version(0.44, '>=')
|
||||
- { role: keystone_role, tags: keystone_role }
|
||||
- { role: logging, tags: logging }
|
||||
- { role: network, tags: network }
|
||||
- role: neutron_rbac
|
||||
tags:
|
||||
- rbac
|
||||
- neutron_rbac
|
||||
- { role: nova_flavor, tags: nova_flavor }
|
||||
- role: compute_flavor_info
|
||||
tags: nova_flavor
|
||||
- role: nova_services
|
||||
tags: nova_services
|
||||
when: sdk_version is version(0.44, '>=')
|
||||
- { role: object, tags: object }
|
||||
- { role: port, tags: port }
|
||||
- { role: project, tags: project }
|
||||
- role: project_properties
|
||||
tags: project_properties
|
||||
when: sdk_version is version("0.45.01", '>')
|
||||
- { role: recordset, tags: recordset }
|
||||
- { role: role_assignment, tags: role_assignment }
|
||||
- { role: router, tags: router }
|
||||
- { role: security_group, tags: security_group }
|
||||
- { role: server, tags: server }
|
||||
- { role: subnet, tags: subnet }
|
||||
- { role: user, tags: user }
|
||||
- { role: subnet_pool, tags: subnet_pool }
|
||||
- { role: user_group, tags: user_group }
|
||||
- { role: user_role, tags: user_role }
|
||||
- { role: volume, tags: volume }
|
||||
- role: orchestration
|
||||
tags: orchestrate
|
||||
when: sdk_version is version("0.53.0", '>=')
|
||||
- role: loadbalancer
|
||||
tags: loadbalancer
|
||||
- { role: floating_ip, tags: floating_ip }
|
||||
|
||||
5
contrib/generate_module.sh
Executable file
5
contrib/generate_module.sh
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
# For resource changing module
|
||||
ansible localhost -c local -m template -a "src=module_template.py.j2 dest=my_module.py" -e @module_template_vars.yaml
|
||||
# For resource info collection module
|
||||
ansible localhost -c local -m template -a "src=module_info_template.py.j2 dest=my_module_info.py" -e @module_template_vars.yaml
|
||||
110
contrib/module_info_template.py.j2
Normal file
110
contrib/module_info_template.py.j2
Normal file
@@ -0,0 +1,110 @@
|
||||
#!/usr/bin/python
|
||||
# coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2020, {{ author_name }} <{{ author_mail }}>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: {{ module_name }}
|
||||
short_description: {{ module_short_description }}
|
||||
author: OpenStack Ansible SIG
|
||||
description:
|
||||
- {{ module_long_description }}
|
||||
options:
|
||||
{{ options|to_nice_yaml(indent=2,sort_keys=false)|indent(width=2)|trim }}
|
||||
|
||||
requirements:
|
||||
- "python >= 3.6"
|
||||
- "openstacksdk"
|
||||
|
||||
extends_documentation_fragment:
|
||||
- openstack.cloud.openstack
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
{{ module_returns_example|to_nice_yaml(indent=2,sort_keys=false) }}
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# What modules does for example
|
||||
- {{ module_name }}:
|
||||
name:
|
||||
- name1
|
||||
- name2
|
||||
timeout: 200
|
||||
'''
|
||||
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
class {{ module_name.split("_")|map("capitalize")|list|join("") }}Module(OpenStackModule):
|
||||
|
||||
argument_spec = dict(
|
||||
{% for k, v in options.items() %}
|
||||
{{ k | indent( width=8, indentfirst=True) }}=dict(type='{{ v.type }}'
|
||||
{%- if 'required' in v %}, required={{ v.required }}{% endif %}
|
||||
{%- if 'elements' in v %}, elements={{ v.elements }}{% endif %}
|
||||
{%- if 'default' in v %}, default={% if v.type == 'str' %}"{{ v.default }}"{% else %}{{ v.default }}{% endif %}{% endif %}
|
||||
{%- if 'aliases' in v %}, aliases={{ v.aliases }}{% endif %}
|
||||
{%- if 'choices' in v %}, choices={{ v.choices }}{% endif %}),
|
||||
{% endfor %}
|
||||
),
|
||||
|
||||
# Optional arguments requirements
|
||||
module_kwargs = dict(
|
||||
required_if=[
|
||||
['action', 'rebuild', ['image']], # if need to rebuild image (only), the 'image' is required
|
||||
["state", "present", ["username", "user_roles"]], # for creating user 'user_roles' is required
|
||||
["state", "absent", ["username"]], # for state 'absent' only username is required
|
||||
],
|
||||
required_by=dict( # for weather and population 'city' is required to set
|
||||
weather=('city'),
|
||||
population=('city'),
|
||||
),
|
||||
mutually_exclusive=[
|
||||
['use_cloud1', 'use_cloud2'] # can't run on both, choose only one to set
|
||||
],
|
||||
required_together=[
|
||||
['remove_image', 'image_name'] # if need to remove image, must to specify which one
|
||||
],
|
||||
required_one_of_args=[["password", "password_hash"]], # one of these args must be set
|
||||
supports_check_mode={{ check_mode_support }}, # good practice is to support check_mode
|
||||
)
|
||||
|
||||
# you main funciton is here
|
||||
def run(self):
|
||||
# do any arguments check if needed
|
||||
data = self.preliminary_checks()
|
||||
# check if we need to prepare various filters for results
|
||||
filters = self.prepare_filters()
|
||||
# run SDK call to get information about requested resource
|
||||
result = self.conn.compute.resource_list(
|
||||
filters=filters,
|
||||
detailed=self.params['detailed'],
|
||||
# any other parameters
|
||||
)
|
||||
# process results if they require a change
|
||||
result = self.normalize_result()
|
||||
self.results.update({'resource_name': result})
|
||||
|
||||
def preliminary_checks(self):
|
||||
# you checks before running like arguments and options checks, etc
|
||||
return data
|
||||
|
||||
def prepare_filters(self):
|
||||
# process filters if they require additional checks
|
||||
return filters
|
||||
|
||||
def normalize_result(self):
|
||||
# process filters if they require additional checks
|
||||
return result
|
||||
|
||||
|
||||
def main():
|
||||
module = {{ module_name.split("_")|map("capitalize")|list|join("") }}Module()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
149
contrib/module_template.py.j2
Normal file
149
contrib/module_template.py.j2
Normal file
@@ -0,0 +1,149 @@
|
||||
#!/usr/bin/python
|
||||
# coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2020, {{ author_name }} <{{ author_mail }}>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: {{ module_name }}
|
||||
short_description: {{ module_short_description }}
|
||||
author: OpenStack Ansible SIG
|
||||
description:
|
||||
- {{ module_long_description }}
|
||||
options:
|
||||
{{ options|to_nice_yaml(indent=2,sort_keys=false)|indent(width=2)|trim }}
|
||||
|
||||
requirements:
|
||||
- "python >= 3.6"
|
||||
- "openstacksdk"
|
||||
|
||||
extends_documentation_fragment:
|
||||
- openstack.cloud.openstack
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
{{ module_returns_example|to_nice_yaml(indent=2,sort_keys=false) }}
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# What modules does for example
|
||||
- {{ module_name }}:
|
||||
action: pause
|
||||
auth:
|
||||
auth_url: https://identity.example.com
|
||||
username: admin
|
||||
password: admin
|
||||
project_name: admin
|
||||
server: vm1
|
||||
timeout: 200
|
||||
'''
|
||||
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
class {{ module_name.split("_")|map("capitalize")|list|join("") }}Module(OpenStackModule):
|
||||
|
||||
argument_spec = dict(
|
||||
{% for k, v in options.items() %}
|
||||
{{ k | indent( width=8, indentfirst=True) }}=dict(type='{{ v.type }}'
|
||||
{%- if 'required' in v %}, required={{ v.required }}{% endif %}
|
||||
{%- if 'elements' in v %}, elements={{ v.elements }}{% endif %}
|
||||
{%- if 'default' in v %}, default={% if v.type == 'str' %}"{{ v.default }}"{% else %}{{ v.default }}{% endif %}{% endif %}
|
||||
{%- if 'aliases' in v %}, aliases={{ v.aliases }}{% endif %}
|
||||
{%- if 'choices' in v %}, choices={{ v.choices }}{% endif %}),
|
||||
{% endfor %}
|
||||
),
|
||||
|
||||
# Optional arguments requirements
|
||||
module_kwargs = dict(
|
||||
required_if=[
|
||||
['action', 'rebuild', ['image']], # if need to rebuild image (only), the 'image' is required
|
||||
["state", "present", ["username", "user_roles"]], # for creating user 'user_roles' is required
|
||||
["state", "absent", ["username"]], # for state 'absent' only username is required
|
||||
],
|
||||
required_by=dict( # for weather and population 'city' is required to set
|
||||
weather=('city'),
|
||||
population=('city'),
|
||||
),
|
||||
mutually_exclusive=[
|
||||
['use_cloud1', 'use_cloud2'] # can't run on both, choose only one to set
|
||||
],
|
||||
required_together=[
|
||||
['remove_image', 'image_name'] # if need to remove image, must to specify which one
|
||||
],
|
||||
required_one_of_args=[["password", "password_hash"]], # one of these args must be set
|
||||
supports_check_mode={{ check_mode_support }}, # good practice is to support check_mode
|
||||
)
|
||||
|
||||
# you main funciton is here
|
||||
def run(self):
|
||||
# do any arguments check if needed
|
||||
data = self.preliminary_checks()
|
||||
# check if we need to run or the resource is in desired state already
|
||||
must_run = self.check_mode_test()
|
||||
# if the resource is good
|
||||
if not must_run:
|
||||
# updated returned results if need
|
||||
self.results.update({"returning_data": some_data})
|
||||
# returning {changed: False, ...} because we didn't change resource
|
||||
self.exit_json(self.results)
|
||||
# do something if must to run the module
|
||||
self.execute()
|
||||
|
||||
def preliminary_checks(self):
|
||||
# you checks before running like arguments and options checks, etc
|
||||
return data
|
||||
|
||||
def check_mode_test(self):
|
||||
# check the idempotency - does module should do anything or
|
||||
# it's already in the desired state?
|
||||
return must_run
|
||||
|
||||
def execute(self):
|
||||
# doing here what should be done, using OpenstackSDK
|
||||
# for example actions for resource:
|
||||
# self.params['action'] = "rebuild"
|
||||
action_name = self.params['action'] + "_resource" # action_name='rebuild_resource'
|
||||
try:
|
||||
# find a method "rebuild_resource" in openstack SDK compute:
|
||||
func_name = getattr(self.conn.compute, action_name)
|
||||
# found self.conn.compute.rebuild_resource
|
||||
except AttributeError:
|
||||
self.fail_json(
|
||||
msg="Method %s wasn't found in OpenstackSDK compute" % action_name)
|
||||
summary = func_name(data) # summary = self.conn.compute.rebuild_resource(data)
|
||||
self.results.update({"returning_data": summary})
|
||||
# that's it, exiting, results will be returned from module automatically
|
||||
|
||||
# another option for states
|
||||
def execute_with_action_map(self):
|
||||
actions_map = {
|
||||
'start': self._start_resource,
|
||||
'stop': self._stop_resource,
|
||||
'restart': self._restart_resource,
|
||||
'absent': self._absent_resource,
|
||||
}
|
||||
summary = actions_map(self.params['action'])() # summary = self.start_resource()
|
||||
self.results.update({"changed": True, "data2return": summary})
|
||||
|
||||
def _start_resource(self, some_other_data):
|
||||
pass
|
||||
|
||||
def _stop_resource(self, some_other_data):
|
||||
pass
|
||||
|
||||
def _restart_resource(self, some_other_data):
|
||||
pass
|
||||
|
||||
def _absent_resource(self, some_other_data):
|
||||
pass
|
||||
|
||||
|
||||
def main():
|
||||
module = {{ module_name.split("_")|map("capitalize")|list|join("") }}Module()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
81
contrib/module_template_vars.yaml
Normal file
81
contrib/module_template_vars.yaml
Normal file
@@ -0,0 +1,81 @@
|
||||
##### PLEASE READ BEFORE #####
|
||||
|
||||
# Module format and documentation
|
||||
# https://docs.ansible.com/ansible/latest/dev_guide/developing_modules_documenting.html#module-format-and-documentation
|
||||
|
||||
|
||||
module_name: server_manage
|
||||
author_name: 'Happy Ansible User'
|
||||
author_mail: dontwriteme@example.com
|
||||
module_short_description: "Doing something very useful"
|
||||
module_long_description: "Here is the place to release your inner writer"
|
||||
check_mode_support: True # good practice to support check_mode:
|
||||
# https://docs.ansible.com/ansible/latest/user_guide/playbooks_checkmode.html#check-mode-dry-run
|
||||
|
||||
module_returns_example:
|
||||
image:
|
||||
description: Image inspection results for the image that was pulled, pushed, or built.
|
||||
returned: always # or 'success' in case of success only
|
||||
type: dict
|
||||
sample:
|
||||
Image Name: Sample Image
|
||||
Image ID: e6471d00796a13de8142c15d7ad3a44f
|
||||
Nested:
|
||||
images list:
|
||||
- data 1
|
||||
- image 1234
|
||||
boolean_1: True
|
||||
|
||||
options:
|
||||
optional_string:
|
||||
description:
|
||||
- This variable is set for having string argument, for example 'action'
|
||||
type: str
|
||||
required: true
|
||||
default: "my_lovely_action"
|
||||
choices:
|
||||
- allowed_option1
|
||||
- allowed_option1
|
||||
optional_boolean:
|
||||
description:
|
||||
- This variable is set for having a boolean argument, for example whether
|
||||
to wait for resource creation or not
|
||||
type: bool
|
||||
required: false # may be omitted if false
|
||||
# and no default because not required
|
||||
optional_integer:
|
||||
description:
|
||||
- This variable is set for having a integer argument, for example how many
|
||||
seconds to wait for the resource to come alive
|
||||
required: true
|
||||
default: 60
|
||||
type: int
|
||||
aliases: # sometimes we allow to pass the same option with different name
|
||||
- old_optional_integer_name
|
||||
- different_option_name
|
||||
optional_list:
|
||||
description:
|
||||
- This variable is set for having a list argument, for example files need
|
||||
to create with the resource
|
||||
type: list
|
||||
elements: str # type of elements of the list, can be dict, str, int, list
|
||||
optional_dictionary:
|
||||
description:
|
||||
- This variable is set for having a dictionary argument, for example to
|
||||
set environment variables or to pass more complex data to SDK
|
||||
required: true
|
||||
default: {}
|
||||
type: dict
|
||||
suboptions:
|
||||
suboption_1:
|
||||
description:
|
||||
- suboption_1 description, what it does
|
||||
type: str
|
||||
aliases:
|
||||
- suboption_1_another_name
|
||||
suboption_2:
|
||||
description:
|
||||
- suboption_2 description, what it does
|
||||
type: list
|
||||
elements: str
|
||||
default: []
|
||||
@@ -13,7 +13,7 @@ Naming
|
||||
------
|
||||
|
||||
* This is a collection named ``openstack.cloud``. There is no need for further namespace prefixing.
|
||||
* Name any module that a cloud consumer would expect to use after the logical resource it manages:
|
||||
* Name any module that a cloud consumer would expect to use after the logical resource it manages:
|
||||
``server`` not ``nova``. This naming convention acknowledges that the end user does not care
|
||||
which service manages the resource - that is a deployment detail. For example cloud consumers may
|
||||
not know whether their floating IPs are managed by Nova or Neutron.
|
||||
@@ -24,6 +24,7 @@ Interface
|
||||
* If the resource being managed has an id, it should be returned.
|
||||
* If the resource being managed has an associated object more complex than
|
||||
an id, it should also be returned.
|
||||
* Return format shall be a dictionary or list
|
||||
|
||||
Interoperability
|
||||
----------------
|
||||
@@ -53,15 +54,15 @@ Libraries
|
||||
* All complex cloud interaction or interoperability code should be housed in
|
||||
the `openstacksdk <https://opendev.org/openstack/openstacksdk>`_
|
||||
library.
|
||||
* All OpenStack API interactions should happen via the openstacksdk and not via
|
||||
* All OpenStack API interactions should happen via the openstackSDK and not via
|
||||
OpenStack Client libraries. The OpenStack Client libraries do no have end
|
||||
users as a primary audience, they are for intra-server communication.
|
||||
* All modules should be registered in ``meta/action_groups.yml`` for enabling the
|
||||
variables to be set in `group level
|
||||
<https://docs.ansible.com/ansible/latest/user_guide/playbooks_module_defaults.html>`.
|
||||
<https://docs.ansible.com/ansible/latest/user_guide/playbooks_module_defaults.html>`_.
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
* Integration testing is currently done in `OpenStack's CI system
|
||||
<https://opendev.org/openstack/ansible-collections-openstack/src/branch/master/zuul.yaml>`
|
||||
<https://opendev.org/openstack/ansible-collections-openstack/src/branch/master/.zuul.yaml>`_
|
||||
|
||||
36
galaxy.yml
Normal file
36
galaxy.yml
Normal file
@@ -0,0 +1,36 @@
|
||||
namespace: openstack
|
||||
name: cloud
|
||||
readme: README.md
|
||||
authors: Openstack
|
||||
description: Openstack Ansible modules
|
||||
license: GPL-3.0-or-later
|
||||
tags:
|
||||
- cloud
|
||||
- openstack
|
||||
dependencies: {}
|
||||
repository: https://opendev.org/openstack/ansible-collections-openstack
|
||||
documentation: https://docs.ansible.com/ansible/latest/collections/openstack/cloud/index.html
|
||||
homepage: https://opendev.org/openstack/ansible-collections-openstack
|
||||
issues: https://storyboard.openstack.org/#!/project/openstack/ansible-collections-openstack
|
||||
build_ignore:
|
||||
- "*.tar.gz"
|
||||
- build_artifact
|
||||
- ci
|
||||
- galaxy.yml.in
|
||||
- setup.cfg
|
||||
- test-requirements*
|
||||
- tests
|
||||
- tools
|
||||
- tox.ini
|
||||
- .gitignore
|
||||
- .gitreview
|
||||
- .zuul.yaml
|
||||
- .pytest_cache
|
||||
- importer_result.json
|
||||
- .tox
|
||||
- .env
|
||||
- .vscode
|
||||
- ansible_collections_openstack.egg-info
|
||||
- contrib
|
||||
- changelogs
|
||||
version: 1.10.0
|
||||
@@ -8,17 +8,17 @@ tags:
|
||||
- cloud
|
||||
- openstack
|
||||
dependencies: {}
|
||||
repository: https://opendev.org/openstack/ansible-collections-openstack.git
|
||||
documentation: https://docs.openstack.org/ansible-collections-openstack
|
||||
homepage: https://opendev.org
|
||||
issues: https://review.opendev.org/q/project:openstack/ansible-collections-openstack
|
||||
repository: https://opendev.org/openstack/ansible-collections-openstack
|
||||
documentation: https://docs.ansible.com/ansible/latest/collections/openstack/cloud/index.html
|
||||
homepage: https://opendev.org/openstack/ansible-collections-openstack
|
||||
issues: https://storyboard.openstack.org/#!/project/openstack/ansible-collections-openstack
|
||||
build_ignore:
|
||||
- "*.tar.gz"
|
||||
- build_artifact
|
||||
- ci
|
||||
- galaxy.yml.in
|
||||
- setup.cfg
|
||||
- test-requirements.txt
|
||||
- test-requirements*
|
||||
- tests
|
||||
- tools
|
||||
- tox.ini
|
||||
@@ -27,3 +27,9 @@ build_ignore:
|
||||
- .zuul.yaml
|
||||
- .pytest_cache
|
||||
- importer_result.json
|
||||
- .tox
|
||||
- .env
|
||||
- .vscode
|
||||
- ansible_collections_openstack.egg-info
|
||||
- contrib
|
||||
- changelogs
|
||||
|
||||
@@ -1,269 +0,0 @@
|
||||
openstack:
|
||||
- auth
|
||||
- baremetal_inspect
|
||||
- baremetal_inspect
|
||||
- baremetal_node
|
||||
- baremetal_node
|
||||
- baremetal_node_action
|
||||
- baremetal_node_action
|
||||
- catalog_endpoint
|
||||
- catalog_service
|
||||
- catalog_service
|
||||
- coe_cluster
|
||||
- coe_cluster_template
|
||||
- compute_flavor
|
||||
- compute_flavor
|
||||
- compute_flavor
|
||||
- compute_flavor_info
|
||||
- compute_flavor_info
|
||||
- config
|
||||
- config
|
||||
- dns_zone
|
||||
- dns_zone
|
||||
- endpoint
|
||||
- endpoint
|
||||
- federation_idp
|
||||
- federation_idp
|
||||
- federation_idp_info
|
||||
- federation_idp_info
|
||||
- federation_mapping
|
||||
- federation_mapping
|
||||
- federation_mapping_info
|
||||
- federation_mapping_info
|
||||
- floating_ip
|
||||
- group_assignment
|
||||
- group_assignment
|
||||
- host_aggregate
|
||||
- host_aggregate
|
||||
- identity_domain
|
||||
- identity_domain
|
||||
- identity_domain_info
|
||||
- identity_domain_info
|
||||
- identity_group
|
||||
- identity_group
|
||||
- identity_group_info
|
||||
- identity_group_info
|
||||
- identity_role
|
||||
- identity_role
|
||||
- identity_user
|
||||
- identity_user
|
||||
- identity_user_info
|
||||
- identity_user_info
|
||||
- image
|
||||
- image_info
|
||||
- keypair
|
||||
- keystone_federation_protocol
|
||||
- keystone_federation_protocol_info
|
||||
- lb_listener
|
||||
- lb_listener
|
||||
- lb_member
|
||||
- lb_member
|
||||
- lb_pool
|
||||
- lb_pool
|
||||
- loadbalancer
|
||||
- network
|
||||
- networks_info
|
||||
- object
|
||||
- port
|
||||
- port_info
|
||||
- project
|
||||
- project_access
|
||||
- project_info
|
||||
- quota
|
||||
- recordset
|
||||
- role_assignment
|
||||
- role_assignment
|
||||
- router
|
||||
- routers_info
|
||||
- security_group
|
||||
- security_group_rule
|
||||
- server
|
||||
- server_action
|
||||
- server_group
|
||||
- server_info
|
||||
- server_metadata
|
||||
- server_volume
|
||||
- stack
|
||||
- subnet
|
||||
- subnets_info
|
||||
- volume
|
||||
- volume_snapshot
|
||||
os:
|
||||
- auth
|
||||
- baremetal_inspect
|
||||
- baremetal_inspect
|
||||
- baremetal_node
|
||||
- baremetal_node
|
||||
- baremetal_node_action
|
||||
- baremetal_node_action
|
||||
- catalog_endpoint
|
||||
- catalog_service
|
||||
- catalog_service
|
||||
- coe_cluster
|
||||
- coe_cluster_template
|
||||
- compute_flavor
|
||||
- compute_flavor
|
||||
- compute_flavor
|
||||
- compute_flavor_info
|
||||
- compute_flavor_info
|
||||
- config
|
||||
- config
|
||||
- dns_zone
|
||||
- dns_zone
|
||||
- endpoint
|
||||
- endpoint
|
||||
- federation_idp
|
||||
- federation_idp
|
||||
- federation_idp_info
|
||||
- federation_idp_info
|
||||
- federation_mapping
|
||||
- federation_mapping
|
||||
- federation_mapping_info
|
||||
- federation_mapping_info
|
||||
- floating_ip
|
||||
- group_assignment
|
||||
- group_assignment
|
||||
- host_aggregate
|
||||
- host_aggregate
|
||||
- identity_domain
|
||||
- identity_domain
|
||||
- identity_domain_info
|
||||
- identity_domain_info
|
||||
- identity_group
|
||||
- identity_group
|
||||
- identity_group_info
|
||||
- identity_group_info
|
||||
- identity_role
|
||||
- identity_role
|
||||
- identity_user
|
||||
- identity_user
|
||||
- identity_user_info
|
||||
- identity_user_info
|
||||
- image
|
||||
- image_info
|
||||
- keypair
|
||||
- keystone_federation_protocol
|
||||
- keystone_federation_protocol_info
|
||||
- lb_listener
|
||||
- lb_listener
|
||||
- lb_member
|
||||
- lb_member
|
||||
- lb_pool
|
||||
- lb_pool
|
||||
- loadbalancer
|
||||
- network
|
||||
- networks_info
|
||||
- object
|
||||
- port
|
||||
- port_info
|
||||
- project
|
||||
- project_access
|
||||
- project_info
|
||||
- quota
|
||||
- recordset
|
||||
- role_assignment
|
||||
- role_assignment
|
||||
- router
|
||||
- routers_info
|
||||
- security_group
|
||||
- security_group_rule
|
||||
- server
|
||||
- server_action
|
||||
- server_group
|
||||
- server_info
|
||||
- server_metadata
|
||||
- server_volume
|
||||
- stack
|
||||
- subnet
|
||||
- subnets_info
|
||||
- volume
|
||||
- volume_snapshot
|
||||
- os_auth
|
||||
- os_client_config
|
||||
- os_client_config
|
||||
- os_coe_cluster
|
||||
- os_coe_cluster_template
|
||||
- os_endpoint
|
||||
- os_flavor
|
||||
- os_flavor_info
|
||||
- os_flavor_info
|
||||
- os_floating_ip
|
||||
- os_group
|
||||
- os_group
|
||||
- os_group_info
|
||||
- os_group_info
|
||||
- os_image
|
||||
- os_image_info
|
||||
- os_ironic
|
||||
- os_ironic
|
||||
- os_ironic_inspect
|
||||
- os_ironic_inspect
|
||||
- os_ironic_node
|
||||
- os_ironic_node
|
||||
- os_keypair
|
||||
- os_keystone_domain
|
||||
- os_keystone_domain
|
||||
- os_keystone_domain_info
|
||||
- os_keystone_domain_info
|
||||
- os_keystone_endpoint
|
||||
- os_keystone_endpoint
|
||||
- os_keystone_federation_protocol
|
||||
- os_keystone_federation_protocol_info
|
||||
- os_keystone_identity_provider
|
||||
- os_keystone_identity_provider
|
||||
- os_keystone_identity_provider_info
|
||||
- os_keystone_identity_provider_info
|
||||
- os_keystone_mapping
|
||||
- os_keystone_mapping
|
||||
- os_keystone_mapping_info
|
||||
- os_keystone_mapping_info
|
||||
- os_keystone_role
|
||||
- os_keystone_role
|
||||
- os_keystone_service
|
||||
- os_keystone_service
|
||||
- os_listener
|
||||
- os_listener
|
||||
- os_loadbalancer
|
||||
- os_member
|
||||
- os_member
|
||||
- os_network
|
||||
- os_networks_info
|
||||
- os_nova_flavor
|
||||
- os_nova_flavor
|
||||
- os_nova_host_aggregate
|
||||
- os_nova_host_aggregate
|
||||
- os_object
|
||||
- os_pool
|
||||
- os_pool
|
||||
- os_port
|
||||
- os_port_info
|
||||
- os_project
|
||||
- os_project_access
|
||||
- os_project_info
|
||||
- os_quota
|
||||
- os_recordset
|
||||
- os_router
|
||||
- os_routers_info
|
||||
- os_security_group
|
||||
- os_security_group_rule
|
||||
- os_server
|
||||
- os_server_action
|
||||
- os_server_group
|
||||
- os_server_info
|
||||
- os_server_metadata
|
||||
- os_server_volume
|
||||
- os_stack
|
||||
- os_subnet
|
||||
- os_subnets_info
|
||||
- os_user
|
||||
- os_user
|
||||
- os_user_group
|
||||
- os_user_group
|
||||
- os_user_info
|
||||
- os_user_info
|
||||
- os_user_role
|
||||
- os_user_role
|
||||
- os_volume
|
||||
- os_volume_snapshot
|
||||
- os_zone
|
||||
- os_zone
|
||||
422
meta/runtime.yml
422
meta/runtime.yml
@@ -1,317 +1,613 @@
|
||||
requires_ansible: ">=2.8"
|
||||
action_groups:
|
||||
openstack:
|
||||
- address_scope
|
||||
- auth
|
||||
- baremetal_inspect
|
||||
- baremetal_inspect
|
||||
- baremetal_node
|
||||
- baremetal_node
|
||||
- baremetal_node_action
|
||||
- baremetal_node_action
|
||||
- baremetal_node_info
|
||||
- baremetal_port_info
|
||||
- baremetal_port
|
||||
- catalog_endpoint
|
||||
- catalog_service
|
||||
- catalog_service
|
||||
- coe_cluster
|
||||
- coe_cluster_template
|
||||
- compute_flavor
|
||||
- compute_flavor
|
||||
- compute_flavor
|
||||
- compute_flavor_info
|
||||
- compute_flavor_info
|
||||
- compute_service_info
|
||||
- compute_service_info
|
||||
- config
|
||||
- config
|
||||
- dns_zone
|
||||
- dns_zone_info
|
||||
- endpoint
|
||||
- endpoint
|
||||
- federation_idp
|
||||
- federation_idp
|
||||
- federation_idp_info
|
||||
- federation_idp_info
|
||||
- federation_mapping
|
||||
- federation_mapping
|
||||
- federation_mapping_info
|
||||
- federation_mapping_info
|
||||
- floating_ip
|
||||
- floating_ip_info
|
||||
- group_assignment
|
||||
- group_assignment
|
||||
- host_aggregate
|
||||
- host_aggregate
|
||||
- identity_domain
|
||||
- identity_domain
|
||||
- identity_domain_info
|
||||
- identity_domain_info
|
||||
- identity_group
|
||||
- identity_group
|
||||
- identity_group_info
|
||||
- identity_group_info
|
||||
- identity_role
|
||||
- identity_role
|
||||
- identity_user
|
||||
- identity_user
|
||||
- identity_user_info
|
||||
- identity_user_info
|
||||
- image
|
||||
- image_info
|
||||
- keypair
|
||||
- keypair_info
|
||||
- keystone_federation_protocol
|
||||
- keystone_federation_protocol_info
|
||||
- lb_listener
|
||||
- lb_listener
|
||||
- lb_member
|
||||
- lb_member
|
||||
- lb_pool
|
||||
- lb_pool
|
||||
- loadbalancer
|
||||
- network
|
||||
- networks_info
|
||||
- object
|
||||
- object_container
|
||||
- port
|
||||
- port_info
|
||||
- project
|
||||
- project_access
|
||||
- project_info
|
||||
- quota
|
||||
- recordset
|
||||
- role_assignment
|
||||
- role_assignment
|
||||
- router
|
||||
- routers_info
|
||||
- security_group
|
||||
- security_group_info
|
||||
- security_group_rule
|
||||
- security_group_rule_info
|
||||
- server
|
||||
- server_action
|
||||
- server_group
|
||||
- server_info
|
||||
- server_metadata
|
||||
- server_volume
|
||||
- stack
|
||||
- subnet
|
||||
- subnets_info
|
||||
- subnet_pool
|
||||
- volume
|
||||
- volume_backup
|
||||
- volume_backup_info
|
||||
- volume_info
|
||||
- volume_snapshot
|
||||
- volume_snapshot_info
|
||||
os:
|
||||
- auth
|
||||
- baremetal_inspect
|
||||
- baremetal_inspect
|
||||
- baremetal_node
|
||||
- baremetal_node
|
||||
- baremetal_node_action
|
||||
- baremetal_node_action
|
||||
- catalog_endpoint
|
||||
- catalog_service
|
||||
- catalog_service
|
||||
- coe_cluster
|
||||
- coe_cluster_template
|
||||
- compute_flavor
|
||||
- compute_flavor
|
||||
- compute_flavor
|
||||
- compute_flavor_info
|
||||
- compute_flavor_info
|
||||
- config
|
||||
- config
|
||||
- dns_zone
|
||||
- dns_zone
|
||||
- endpoint
|
||||
- endpoint
|
||||
- federation_idp
|
||||
- federation_idp
|
||||
- federation_idp_info
|
||||
- federation_idp_info
|
||||
- federation_mapping
|
||||
- federation_mapping
|
||||
- federation_mapping_info
|
||||
- federation_mapping_info
|
||||
- floating_ip
|
||||
- group_assignment
|
||||
- group_assignment
|
||||
- host_aggregate
|
||||
- host_aggregate
|
||||
- identity_domain
|
||||
- identity_domain
|
||||
- identity_domain_info
|
||||
- identity_domain_info
|
||||
- identity_group
|
||||
- identity_group
|
||||
- identity_group_info
|
||||
- identity_group_info
|
||||
- identity_role
|
||||
- identity_role
|
||||
- identity_user
|
||||
- identity_user
|
||||
- identity_user_info
|
||||
- identity_user_info
|
||||
- image
|
||||
- image_info
|
||||
- keypair
|
||||
- keypair_info
|
||||
- keystone_federation_protocol
|
||||
- keystone_federation_protocol_info
|
||||
- lb_listener
|
||||
- lb_listener
|
||||
- lb_member
|
||||
- lb_member
|
||||
- lb_pool
|
||||
- lb_pool
|
||||
- loadbalancer
|
||||
- network
|
||||
- networks_info
|
||||
- object
|
||||
- object_container
|
||||
- port
|
||||
- port_info
|
||||
- project
|
||||
- project_access
|
||||
- project_info
|
||||
- quota
|
||||
- recordset
|
||||
- role_assignment
|
||||
- role_assignment
|
||||
- router
|
||||
- routers_info
|
||||
- security_group
|
||||
- security_group_info
|
||||
- security_group_rule
|
||||
- security_group_rule_info
|
||||
- server
|
||||
- server_action
|
||||
- server_group
|
||||
- server_info
|
||||
- server_metadata
|
||||
- server_volume
|
||||
- stack
|
||||
- subnet
|
||||
- subnets_info
|
||||
- volume
|
||||
- volume_backup
|
||||
- volume_backup_info
|
||||
- volume_info
|
||||
- volume_snapshot
|
||||
- volume_snapshot_info
|
||||
- os_auth
|
||||
- os_client_config
|
||||
- os_client_config
|
||||
- os_coe_cluster
|
||||
- os_coe_cluster_template
|
||||
- os_endpoint
|
||||
- os_flavor
|
||||
- os_flavor_info
|
||||
- os_flavor_info
|
||||
- os_floating_ip
|
||||
- os_group
|
||||
- os_group
|
||||
- os_group_info
|
||||
- os_group_info
|
||||
- os_image
|
||||
- os_image_info
|
||||
- os_ironic
|
||||
- os_ironic
|
||||
- os_ironic_inspect
|
||||
- os_ironic_inspect
|
||||
- os_ironic_node
|
||||
- os_ironic_node
|
||||
- os_keypair
|
||||
- os_keystone_domain
|
||||
- os_keystone_domain
|
||||
- os_keystone_domain_info
|
||||
- os_keystone_domain_info
|
||||
- os_keystone_endpoint
|
||||
- os_keystone_endpoint
|
||||
- os_keystone_federation_protocol
|
||||
- os_keystone_federation_protocol_info
|
||||
- os_keystone_identity_provider
|
||||
- os_keystone_identity_provider
|
||||
- os_keystone_identity_provider_info
|
||||
- os_keystone_identity_provider_info
|
||||
- os_keystone_mapping
|
||||
- os_keystone_mapping
|
||||
- os_keystone_mapping_info
|
||||
- os_keystone_mapping_info
|
||||
- os_keystone_role
|
||||
- os_keystone_role
|
||||
- os_keystone_service
|
||||
- os_keystone_service
|
||||
- os_listener
|
||||
- os_listener
|
||||
- os_loadbalancer
|
||||
- os_member
|
||||
- os_member
|
||||
- os_network
|
||||
- os_networks_info
|
||||
- os_nova_flavor
|
||||
- os_nova_flavor
|
||||
- os_nova_host_aggregate
|
||||
- os_nova_host_aggregate
|
||||
- os_object
|
||||
- os_pool
|
||||
- os_pool
|
||||
- os_port
|
||||
- os_port_info
|
||||
- os_project
|
||||
- os_project_access
|
||||
- os_project_info
|
||||
- os_quota
|
||||
- os_recordset
|
||||
- os_router
|
||||
- os_routers_info
|
||||
- os_security_group
|
||||
- os_security_group_rule
|
||||
- os_server
|
||||
- os_server_action
|
||||
- os_server_group
|
||||
- os_server_info
|
||||
- os_server_metadata
|
||||
- os_server_volume
|
||||
- os_stack
|
||||
- os_subnet
|
||||
- os_subnets_info
|
||||
- os_user
|
||||
- os_user
|
||||
- os_user_group
|
||||
- os_user_group
|
||||
- os_user_info
|
||||
- os_user_info
|
||||
- os_user_role
|
||||
- os_user_role
|
||||
- os_volume
|
||||
- os_volume_snapshot
|
||||
- os_zone
|
||||
- os_zone
|
||||
|
||||
plugin_routing:
|
||||
modules:
|
||||
os_auth:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.auth
|
||||
redirect: openstack.cloud.auth
|
||||
os_client_config:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.config
|
||||
redirect: openstack.cloud.config
|
||||
os_coe_cluster:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.coe_cluster
|
||||
redirect: openstack.cloud.coe_cluster
|
||||
os_coe_cluster_template:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.coe_cluster_template
|
||||
redirect: openstack.cloud.coe_cluster_template
|
||||
os_endpoint:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.catalog_endpoint
|
||||
redirect: openstack.cloud.catalog_endpoint
|
||||
os_flavor:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.compute_flavor
|
||||
redirect: openstack.cloud.compute_flavor
|
||||
os_flavor_info:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.compute_flavor_info
|
||||
redirect: openstack.cloud.compute_flavor_info
|
||||
os_floating_ip:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.floating_ip
|
||||
redirect: openstack.cloud.floating_ip
|
||||
os_group:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.identity_group
|
||||
redirect: openstack.cloud.identity_group
|
||||
os_group_info:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.identity_group_info
|
||||
redirect: openstack.cloud.identity_group_info
|
||||
os_image:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.image
|
||||
redirect: openstack.cloud.image
|
||||
os_image_info:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.image_info
|
||||
redirect: openstack.cloud.image_info
|
||||
os_ironic:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.baremetal_node
|
||||
redirect: openstack.cloud.baremetal_node
|
||||
os_ironic_inspect:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.baremetal_inspect
|
||||
redirect: openstack.cloud.baremetal_inspect
|
||||
os_ironic_node:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.baremetal_node_action
|
||||
redirect: openstack.cloud.baremetal_node_action
|
||||
os_keypair:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.keypair
|
||||
redirect: openstack.cloud.keypair
|
||||
os_keystone_domain:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.identity_domain
|
||||
redirect: openstack.cloud.identity_domain
|
||||
os_keystone_domain_info:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.identity_domain_info
|
||||
redirect: openstack.cloud.identity_domain_info
|
||||
os_keystone_endpoint:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.endpoint
|
||||
redirect: openstack.cloud.endpoint
|
||||
os_keystone_federation_protocol:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.keystone_federation_protocol
|
||||
redirect: openstack.cloud.keystone_federation_protocol
|
||||
os_keystone_federation_protocol_info:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.keystone_federation_protocol_info
|
||||
redirect: openstack.cloud.keystone_federation_protocol_info
|
||||
os_keystone_identity_provider:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.federation_idp
|
||||
redirect: openstack.cloud.federation_idp
|
||||
os_keystone_identity_provider_info:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.federation_idp_info
|
||||
redirect: openstack.cloud.federation_idp_info
|
||||
os_keystone_mapping:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.federation_mapping
|
||||
redirect: openstack.cloud.federation_mapping
|
||||
os_keystone_mapping_info:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.federation_mapping_info
|
||||
redirect: openstack.cloud.federation_mapping_info
|
||||
os_keystone_role:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.identity_role
|
||||
redirect: openstack.cloud.identity_role
|
||||
os_keystone_service:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.catalog_service
|
||||
redirect: openstack.cloud.catalog_service
|
||||
os_listener:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.lb_listener
|
||||
redirect: openstack.cloud.lb_listener
|
||||
os_loadbalancer:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.loadbalancer
|
||||
redirect: openstack.cloud.loadbalancer
|
||||
os_member:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.lb_member
|
||||
redirect: openstack.cloud.lb_member
|
||||
os_network:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.network
|
||||
redirect: openstack.cloud.network
|
||||
os_networks_info:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.networks_info
|
||||
redirect: openstack.cloud.networks_info
|
||||
os_nova_flavor:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.compute_flavor
|
||||
redirect: openstack.cloud.compute_flavor
|
||||
os_nova_host_aggregate:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.host_aggregate
|
||||
redirect: openstack.cloud.host_aggregate
|
||||
os_object:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.object
|
||||
redirect: openstack.cloud.object
|
||||
os_pool:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.lb_pool
|
||||
redirect: openstack.cloud.lb_pool
|
||||
os_port:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.port
|
||||
redirect: openstack.cloud.port
|
||||
os_port_info:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.port_info
|
||||
redirect: openstack.cloud.port_info
|
||||
os_project:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.project
|
||||
redirect: openstack.cloud.project
|
||||
os_project_access:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.project_access
|
||||
redirect: openstack.cloud.project_access
|
||||
os_project_info:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.project_info
|
||||
redirect: openstack.cloud.project_info
|
||||
os_quota:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.quota
|
||||
redirect: openstack.cloud.quota
|
||||
os_recordset:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.recordset
|
||||
redirect: openstack.cloud.recordset
|
||||
os_router:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.router
|
||||
redirect: openstack.cloud.router
|
||||
os_routers_info:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.routers_info
|
||||
redirect: openstack.cloud.routers_info
|
||||
os_security_group:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.security_group
|
||||
redirect: openstack.cloud.security_group
|
||||
os_security_group_rule:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.security_group_rule
|
||||
redirect: openstack.cloud.security_group_rule
|
||||
os_server:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.server
|
||||
redirect: openstack.cloud.server
|
||||
os_server_action:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.server_action
|
||||
redirect: openstack.cloud.server_action
|
||||
os_server_group:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.server_group
|
||||
redirect: openstack.cloud.server_group
|
||||
os_server_info:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.server_info
|
||||
redirect: openstack.cloud.server_info
|
||||
os_server_metadata:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.server_metadata
|
||||
redirect: openstack.cloud.server_metadata
|
||||
os_server_volume:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.server_volume
|
||||
redirect: openstack.cloud.server_volume
|
||||
os_stack:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.stack
|
||||
redirect: openstack.cloud.stack
|
||||
os_subnet:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.subnet
|
||||
redirect: openstack.cloud.subnet
|
||||
os_subnets_info:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.subnets_info
|
||||
redirect: openstack.cloud.subnets_info
|
||||
os_user:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.identity_user
|
||||
redirect: openstack.cloud.identity_user
|
||||
os_user_group:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.group_assignment
|
||||
redirect: openstack.cloud.group_assignment
|
||||
os_user_info:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.identity_user_info
|
||||
redirect: openstack.cloud.identity_user_info
|
||||
os_user_role:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.role_assignment
|
||||
redirect: openstack.cloud.role_assignment
|
||||
os_volume:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.volume
|
||||
redirect: openstack.cloud.volume
|
||||
os_volume_snapshot:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.volume_snapshot
|
||||
redirect: openstack.cloud.volume_snapshot
|
||||
os_zone:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
removal_date: 2021-12-12
|
||||
warning_text: os_ prefixed module names are deprecated, use openstack.cloud.dns_zone
|
||||
redirect: openstack.cloud.dns_zone
|
||||
|
||||
@@ -61,7 +61,6 @@ options:
|
||||
- Whether or not SSL API requests should be verified.
|
||||
- Before Ansible 2.3 this defaulted to C(yes).
|
||||
type: bool
|
||||
default: no
|
||||
aliases: [ verify ]
|
||||
ca_cert:
|
||||
description:
|
||||
@@ -90,9 +89,18 @@ options:
|
||||
description:
|
||||
- Ignored. Present for backwards compatibility
|
||||
type: str
|
||||
sdk_log_path:
|
||||
description:
|
||||
- Path to the logfile of the OpenStackSDK. If empty no log is written
|
||||
type: str
|
||||
sdk_log_level:
|
||||
description: Log level of the OpenStackSDK
|
||||
type: str
|
||||
default: INFO
|
||||
choices: [INFO, DEBUG]
|
||||
requirements:
|
||||
- python >= 3.6
|
||||
- openstacksdk >= 0.12.0
|
||||
- openstacksdk >= 0.36, < 0.99.0
|
||||
notes:
|
||||
- The standard OpenStack environment variables, such as C(OS_USERNAME)
|
||||
may be used instead of providing explicit values.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2012, Marco Vito Moscaritolo <marco@agavee.com>
|
||||
# Copyright (c) 2013, Jesse Keating <jesse.keating@rackspace.com>
|
||||
# Copyright (c) 2015, Hewlett-Packard Development Company, L.P.
|
||||
@@ -9,13 +10,8 @@
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
name: openstack
|
||||
plugin_type: inventory
|
||||
author:
|
||||
- "Marco Vito Moscaritolo <marco@agavee.com>"
|
||||
- "Jesse Keating <jesse.keating@rackspace.com>"
|
||||
author: OpenStack Ansible SIG
|
||||
short_description: OpenStack inventory source
|
||||
requirements:
|
||||
- "openstacksdk >= 0.28"
|
||||
description:
|
||||
- Get inventory hosts from OpenStack clouds
|
||||
- Uses openstack.(yml|yaml) YAML configuration file to configure the inventory plugin
|
||||
@@ -24,11 +20,11 @@ options:
|
||||
plugin:
|
||||
description: token that ensures this is a source file for the 'openstack' plugin.
|
||||
required: True
|
||||
choices: ['openstack']
|
||||
choices: ['openstack', 'openstack.cloud.openstack']
|
||||
show_all:
|
||||
description: toggles showing all vms vs only those with a working IP
|
||||
type: bool
|
||||
default: 'no'
|
||||
default: false
|
||||
inventory_hostname:
|
||||
description: |
|
||||
What to register as the inventory hostname.
|
||||
@@ -44,6 +40,13 @@ options:
|
||||
- name
|
||||
- uuid
|
||||
default: "name"
|
||||
use_names:
|
||||
description: |
|
||||
Use the host's 'name' instead of 'interface_ip' for the 'ansible_host' and
|
||||
'ansible_ssh_host' facts. This might be desired when using jump or
|
||||
bastion hosts and the name is the FQDN of the host.
|
||||
type: bool
|
||||
default: false
|
||||
expand_hostvars:
|
||||
description: |
|
||||
Run extra commands on each host to fill in additional
|
||||
@@ -52,7 +55,7 @@ options:
|
||||
(Note, the default value of this is opposite from the default
|
||||
old openstack.py inventory script's option expand_hostvars)
|
||||
type: bool
|
||||
default: 'no'
|
||||
default: false
|
||||
private:
|
||||
description: |
|
||||
Use the private interface of each server, if it has one, as
|
||||
@@ -60,12 +63,13 @@ options:
|
||||
running ansible inside a server in the cloud and would rather
|
||||
communicate to your servers over the private network.
|
||||
type: bool
|
||||
default: 'no'
|
||||
default: false
|
||||
only_clouds:
|
||||
description: |
|
||||
List of clouds from clouds.yaml to use, instead of using
|
||||
the whole list.
|
||||
type: list
|
||||
elements: str
|
||||
default: []
|
||||
fail_on_errors:
|
||||
description: |
|
||||
@@ -76,12 +80,12 @@ options:
|
||||
default value of this is opposite from the old openstack.py
|
||||
inventory script's option fail_on_errors)
|
||||
type: bool
|
||||
default: 'no'
|
||||
default: false
|
||||
all_projects:
|
||||
description: |
|
||||
Lists servers from all projects
|
||||
type: bool
|
||||
default: 'no'
|
||||
default: false
|
||||
clouds_yaml_path:
|
||||
description: |
|
||||
Override path to clouds.yaml file. If this value is given it
|
||||
@@ -90,6 +94,7 @@ options:
|
||||
/etc/ansible/openstack.yml to the regular locations documented
|
||||
at https://docs.openstack.org/os-client-config/latest/user/configuration.html#config-files
|
||||
type: list
|
||||
elements: str
|
||||
env:
|
||||
- name: OS_CLIENT_CONFIG_FILE
|
||||
compose:
|
||||
@@ -100,7 +105,13 @@ options:
|
||||
description: Add hosts to group based on Jinja2 conditionals.
|
||||
type: dictionary
|
||||
default: {}
|
||||
|
||||
legacy_groups:
|
||||
description: Automatically create groups from host variables.
|
||||
type: bool
|
||||
default: true
|
||||
requirements:
|
||||
- "python >= 3.6"
|
||||
- "openstacksdk >= 0.28, < 0.99.0"
|
||||
extends_documentation_fragment:
|
||||
- inventory_cache
|
||||
- constructed
|
||||
@@ -110,7 +121,7 @@ extends_documentation_fragment:
|
||||
EXAMPLES = '''
|
||||
# file must be named openstack.yaml or openstack.yml
|
||||
# Make the plugin behave like the default behavior of the old script
|
||||
plugin: openstack
|
||||
plugin: openstack.cloud.openstack
|
||||
expand_hostvars: yes
|
||||
fail_on_errors: yes
|
||||
all_projects: yes
|
||||
@@ -118,9 +129,17 @@ all_projects: yes
|
||||
|
||||
import collections
|
||||
import sys
|
||||
import logging
|
||||
|
||||
from ansible.errors import AnsibleParserError
|
||||
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable, Cacheable
|
||||
from ansible.utils.display import Display
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (
|
||||
ensure_compatibility
|
||||
)
|
||||
|
||||
display = Display()
|
||||
os_logger = logging.getLogger("openstack")
|
||||
|
||||
try:
|
||||
# Due to the name shadowing we should import other way
|
||||
@@ -128,8 +147,10 @@ try:
|
||||
sdk = importlib.import_module('openstack')
|
||||
sdk_inventory = importlib.import_module('openstack.cloud.inventory')
|
||||
client_config = importlib.import_module('openstack.config.loader')
|
||||
sdk_exceptions = importlib.import_module("openstack.exceptions")
|
||||
HAS_SDK = True
|
||||
except ImportError:
|
||||
display.vvvv("Couldn't import Openstack SDK modules")
|
||||
HAS_SDK = False
|
||||
|
||||
|
||||
@@ -150,19 +171,29 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||
msg = ''
|
||||
if not self._config_data:
|
||||
msg = 'File empty. this is not my config file'
|
||||
elif 'plugin' in self._config_data and self._config_data['plugin'] != self.NAME:
|
||||
elif 'plugin' in self._config_data and self._config_data['plugin'] not in (self.NAME, 'openstack'):
|
||||
msg = 'plugin config file, but not for us: %s' % self._config_data['plugin']
|
||||
elif 'plugin' not in self._config_data and 'clouds' not in self._config_data:
|
||||
msg = "it's not a plugin configuration nor a clouds.yaml file"
|
||||
elif not HAS_SDK:
|
||||
msg = "openstacksdk is required for the OpenStack inventory plugin. OpenStack inventory sources will be skipped."
|
||||
|
||||
if not msg:
|
||||
try:
|
||||
ensure_compatibility(sdk.version.__version__)
|
||||
except ImportError as e:
|
||||
msg = ("Incompatible openstacksdk library found: {error}."
|
||||
.format(error=str(e)))
|
||||
|
||||
if msg:
|
||||
display.vvvv(msg)
|
||||
raise AnsibleParserError(msg)
|
||||
|
||||
# The user has pointed us at a clouds.yaml file. Use defaults for
|
||||
# everything.
|
||||
if 'clouds' in self._config_data:
|
||||
self.display.vvvv(
|
||||
"Found clouds config file instead of plugin config. "
|
||||
"Using default configuration."
|
||||
)
|
||||
self._config_data = {}
|
||||
|
||||
# update cache if the user has caching enabled and the cache is being refreshed
|
||||
@@ -173,13 +204,16 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||
cache = self.get_option('cache')
|
||||
source_data = None
|
||||
if cache:
|
||||
self.display.vvvv("Reading inventory data from cache: %s" % cache_key)
|
||||
try:
|
||||
source_data = self._cache[cache_key]
|
||||
except KeyError:
|
||||
# cache expired or doesn't exist yet
|
||||
display.vvvv("Inventory data cache not found")
|
||||
cache_needs_update = True
|
||||
|
||||
if not source_data:
|
||||
self.display.vvvv("Getting hosts from Openstack clouds")
|
||||
clouds_yaml_path = self._config_data.get('clouds_yaml_path')
|
||||
if clouds_yaml_path:
|
||||
config_files = (
|
||||
@@ -192,11 +226,16 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||
# Redict logging to stderr so it does not mix with output
|
||||
# particular ansible-inventory JSON output
|
||||
# TODO(mordred) Integrate openstack's logging with ansible's logging
|
||||
sdk.enable_logging(stream=sys.stderr)
|
||||
if self.display.verbosity > 3:
|
||||
sdk.enable_logging(debug=True, stream=sys.stderr)
|
||||
else:
|
||||
sdk.enable_logging(stream=sys.stderr)
|
||||
|
||||
cloud_inventory = sdk_inventory.OpenStackInventory(
|
||||
config_files=config_files,
|
||||
private=self._config_data.get('private', False))
|
||||
self.display.vvvv("Found %d cloud(s) in Openstack" %
|
||||
len(cloud_inventory.clouds))
|
||||
only_clouds = self._config_data.get('only_clouds', [])
|
||||
if only_clouds and not isinstance(only_clouds, list):
|
||||
raise ValueError(
|
||||
@@ -205,20 +244,32 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||
if only_clouds:
|
||||
new_clouds = []
|
||||
for cloud in cloud_inventory.clouds:
|
||||
self.display.vvvv("Looking at cloud : %s" % cloud.name)
|
||||
if cloud.name in only_clouds:
|
||||
self.display.vvvv("Selecting cloud : %s" % cloud.name)
|
||||
new_clouds.append(cloud)
|
||||
cloud_inventory.clouds = new_clouds
|
||||
|
||||
self.display.vvvv("Selected %d cloud(s)" %
|
||||
len(cloud_inventory.clouds))
|
||||
|
||||
expand_hostvars = self._config_data.get('expand_hostvars', False)
|
||||
fail_on_errors = self._config_data.get('fail_on_errors', False)
|
||||
all_projects = self._config_data.get('all_projects', False)
|
||||
self.use_names = self._config_data.get('use_names', False)
|
||||
|
||||
source_data = cloud_inventory.list_hosts(
|
||||
expand=expand_hostvars, fail_on_cloud_config=fail_on_errors,
|
||||
all_projects=all_projects)
|
||||
|
||||
if cache_needs_update:
|
||||
self._cache[cache_key] = source_data
|
||||
source_data = []
|
||||
try:
|
||||
source_data = cloud_inventory.list_hosts(
|
||||
expand=expand_hostvars, fail_on_cloud_config=fail_on_errors,
|
||||
all_projects=all_projects)
|
||||
except Exception as e:
|
||||
self.display.warning("Couldn't list Openstack hosts. "
|
||||
"See logs for details")
|
||||
os_logger.error(e.message)
|
||||
finally:
|
||||
if cache_needs_update:
|
||||
self._cache[cache_key] = source_data
|
||||
|
||||
self._populate_from_source(source_data)
|
||||
|
||||
@@ -280,7 +331,11 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||
for group_name, group_hosts in groups.items():
|
||||
gname = self.inventory.add_group(group_name)
|
||||
for host in group_hosts:
|
||||
self.inventory.add_child(gname, host)
|
||||
if gname == host:
|
||||
display.vvvv("Same name for host %s and group %s" % (host, gname))
|
||||
self.inventory.add_host(host, gname)
|
||||
else:
|
||||
self.inventory.add_child(gname, host)
|
||||
|
||||
def _get_groups_from_server(self, server_vars, namegroup=True):
|
||||
groups = []
|
||||
@@ -328,14 +383,25 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||
|
||||
def _append_hostvars(self, hostvars, groups, current_host,
|
||||
server, namegroup=False):
|
||||
hostvars[current_host] = dict(
|
||||
ansible_ssh_host=server['interface_ip'],
|
||||
ansible_host=server['interface_ip'],
|
||||
openstack=server)
|
||||
if not self.use_names:
|
||||
hostvars[current_host] = dict(
|
||||
ansible_ssh_host=server['interface_ip'],
|
||||
ansible_host=server['interface_ip'],
|
||||
openstack=server,
|
||||
)
|
||||
|
||||
if self.use_names:
|
||||
hostvars[current_host] = dict(
|
||||
ansible_ssh_host=server['name'],
|
||||
ansible_host=server['name'],
|
||||
openstack=server,
|
||||
)
|
||||
|
||||
self.inventory.add_host(current_host)
|
||||
|
||||
for group in self._get_groups_from_server(server, namegroup=namegroup):
|
||||
groups[group].append(current_host)
|
||||
if self.get_option('legacy_groups'):
|
||||
for group in self._get_groups_from_server(server, namegroup=namegroup):
|
||||
groups[group].append(current_host)
|
||||
|
||||
def verify_file(self, path):
|
||||
|
||||
@@ -344,5 +410,6 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||
for suffix in ('yaml', 'yml'):
|
||||
maybe = '{fn}.{suffix}'.format(fn=fn, suffix=suffix)
|
||||
if path.endswith(maybe):
|
||||
self.display.vvvv("Valid plugin config file found")
|
||||
return True
|
||||
return False
|
||||
|
||||
68
plugins/module_utils/ironic.py
Normal file
68
plugins/module_utils/ironic.py
Normal file
@@ -0,0 +1,68 @@
|
||||
# This code is part of Ansible, but is an independent component.
|
||||
# This particular file snippet, and this file snippet only, is BSD licensed.
|
||||
# Modules you write using this snippet, which is embedded dynamically by Ansible
|
||||
# still belong to the author of the module, and may assign their own license
|
||||
# to the complete work.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import openstack_full_argument_spec
|
||||
|
||||
|
||||
def ironic_argument_spec(**kwargs):
|
||||
spec = dict(
|
||||
auth_type=dict(required=False),
|
||||
ironic_url=dict(required=False),
|
||||
)
|
||||
spec.update(kwargs)
|
||||
return openstack_full_argument_spec(**spec)
|
||||
|
||||
|
||||
# TODO(dtantsur): inherit the collection's base module
|
||||
class IronicModule(AnsibleModule):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self._update_ironic_auth()
|
||||
|
||||
def _update_ironic_auth(self):
|
||||
"""Validate and update authentication parameters for ironic."""
|
||||
if (
|
||||
self.params['auth_type'] in [None, 'None', 'none']
|
||||
and self.params['ironic_url'] is None
|
||||
and not self.params['cloud']
|
||||
and not (self.params['auth']
|
||||
and self.params['auth'].get('endpoint'))
|
||||
):
|
||||
self.fail_json(msg=("Authentication appears to be disabled, "
|
||||
"Please define either ironic_url, or cloud, "
|
||||
"or auth.endpoint"))
|
||||
|
||||
if (
|
||||
self.params['ironic_url']
|
||||
and self.params['auth_type'] in [None, 'None', 'none']
|
||||
and not (self.params['auth']
|
||||
and self.params['auth'].get('endpoint'))
|
||||
):
|
||||
self.params['auth'] = dict(
|
||||
endpoint=self.params['ironic_url']
|
||||
)
|
||||
@@ -28,13 +28,90 @@
|
||||
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import abc
|
||||
from distutils.version import StrictVersion
|
||||
import copy
|
||||
from ansible.module_utils.six import raise_from
|
||||
try:
|
||||
from ansible.module_utils.compat.version import StrictVersion
|
||||
except ImportError:
|
||||
try:
|
||||
from distutils.version import StrictVersion
|
||||
except ImportError as exc:
|
||||
raise_from(ImportError('To use this plugin or module with ansible-core'
|
||||
' < 2.11, you need to use Python < 3.12 with '
|
||||
'distutils.version present'), exc)
|
||||
import importlib
|
||||
import os
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.six import iteritems
|
||||
|
||||
OVERRIDES = {'os_client_config': 'config',
|
||||
'os_endpoint': 'catalog_endpoint',
|
||||
'os_flavor': 'compute_flavor',
|
||||
'os_flavor_info': 'compute_flavor_info',
|
||||
'os_group': 'identity_group',
|
||||
'os_group_info': 'identity_group_info',
|
||||
'os_ironic': 'baremetal_node',
|
||||
'os_ironic_inspect': 'baremetal_inspect',
|
||||
'os_ironic_node': 'baremetal_node_action',
|
||||
'os_keystone_domain': 'identity_domain',
|
||||
'os_keystone_domain_info': 'identity_domain_info',
|
||||
'os_keystone_endpoint': 'endpoint',
|
||||
'os_keystone_identity_provider': 'federation_idp',
|
||||
'os_keystone_identity_provider_info': 'federation_idp_info',
|
||||
'os_keystone_mapping': 'federation_mapping',
|
||||
'os_keystone_mapping_info': 'federation_mapping_info',
|
||||
'os_keystone_role': 'identity_role',
|
||||
'os_keystone_service': 'catalog_service',
|
||||
'os_listener': 'lb_listener',
|
||||
'os_member': 'lb_member',
|
||||
'os_nova_flavor': 'compute_flavor',
|
||||
'os_nova_host_aggregate': 'host_aggregate',
|
||||
'os_pool': 'lb_pool',
|
||||
'os_user': 'identity_user',
|
||||
'os_user_group': 'group_assignment',
|
||||
'os_user_info': 'identity_user_info',
|
||||
'os_user_role': 'role_assignment',
|
||||
'os_zone': 'dns_zone'}
|
||||
|
||||
CUSTOM_VAR_PARAMS = ['min_ver', 'max_ver']
|
||||
|
||||
MINIMUM_SDK_VERSION = '0.36.0'
|
||||
MAXIMUM_SDK_VERSION = '0.98.999'
|
||||
|
||||
|
||||
def ensure_compatibility(version, min_version=None, max_version=None):
|
||||
""" Raises ImportError if the specified version does not
|
||||
meet the minimum and maximum version requirements"""
|
||||
|
||||
if min_version and MINIMUM_SDK_VERSION:
|
||||
min_version = max(StrictVersion(MINIMUM_SDK_VERSION),
|
||||
StrictVersion(min_version))
|
||||
elif MINIMUM_SDK_VERSION:
|
||||
min_version = StrictVersion(MINIMUM_SDK_VERSION)
|
||||
|
||||
if max_version and MAXIMUM_SDK_VERSION:
|
||||
max_version = min(StrictVersion(MAXIMUM_SDK_VERSION),
|
||||
StrictVersion(max_version))
|
||||
elif MAXIMUM_SDK_VERSION:
|
||||
max_version = StrictVersion(MAXIMUM_SDK_VERSION)
|
||||
|
||||
if min_version and StrictVersion(version) < min_version:
|
||||
raise ImportError(
|
||||
"Version MUST be >={min_version} and <={max_version}, but"
|
||||
" {version} is smaller than minimum version {min_version}"
|
||||
.format(version=version,
|
||||
min_version=min_version,
|
||||
max_version=max_version))
|
||||
|
||||
if max_version and StrictVersion(version) > max_version:
|
||||
raise ImportError(
|
||||
"Version MUST be >={min_version} and <={max_version}, but"
|
||||
" {version} is larger than maximum version {max_version}"
|
||||
.format(version=version,
|
||||
min_version=min_version,
|
||||
max_version=max_version))
|
||||
|
||||
|
||||
def openstack_argument_spec():
|
||||
# DEPRECATED: This argument spec is only used for the deprecated old
|
||||
@@ -96,8 +173,16 @@ def openstack_full_argument_spec(**kwargs):
|
||||
interface=dict(
|
||||
default='public', choices=['public', 'internal', 'admin'],
|
||||
aliases=['endpoint_type']),
|
||||
sdk_log_path=dict(default=None, type='str'),
|
||||
sdk_log_level=dict(
|
||||
default='INFO', type='str', choices=['INFO', 'DEBUG']),
|
||||
)
|
||||
spec.update(kwargs)
|
||||
# Filter out all our custom parameters before passing to AnsibleModule
|
||||
kwargs_copy = copy.deepcopy(kwargs)
|
||||
for v in kwargs_copy.values():
|
||||
for c in CUSTOM_VAR_PARAMS:
|
||||
v.pop(c, None)
|
||||
spec.update(kwargs_copy)
|
||||
return spec
|
||||
|
||||
|
||||
@@ -109,28 +194,24 @@ def openstack_module_kwargs(**kwargs):
|
||||
ret[key].extend(kwargs[key])
|
||||
else:
|
||||
ret[key] = kwargs[key]
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def openstack_cloud_from_module(module, min_version='0.12.0'):
|
||||
# for compatibility with old versions
|
||||
def openstack_cloud_from_module(module, min_version=None, max_version=None):
|
||||
try:
|
||||
# Due to the name shadowing we should import other way
|
||||
sdk = importlib.import_module('openstack')
|
||||
sdk_version = importlib.import_module('openstack.version')
|
||||
except ImportError:
|
||||
module.fail_json(msg='openstacksdk is required for this module')
|
||||
|
||||
if min_version:
|
||||
min_version = max(StrictVersion('0.12.0'), StrictVersion(min_version))
|
||||
else:
|
||||
min_version = StrictVersion('0.12.0')
|
||||
|
||||
if StrictVersion(sdk_version.__version__) < min_version:
|
||||
try:
|
||||
ensure_compatibility(sdk.version.__version__,
|
||||
min_version, max_version)
|
||||
except ImportError as e:
|
||||
module.fail_json(
|
||||
msg="To utilize this module, the installed version of "
|
||||
"the openstacksdk library MUST be >={min_version}.".format(
|
||||
min_version=min_version))
|
||||
msg="Incompatible openstacksdk library found: {error}."
|
||||
.format(error=str(e)))
|
||||
|
||||
cloud_config = module.params.pop('cloud', None)
|
||||
try:
|
||||
@@ -166,25 +247,224 @@ def openstack_cloud_from_module(module, min_version='0.12.0'):
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
|
||||
class OpenStackModule(AnsibleModule):
|
||||
class OpenStackModule:
|
||||
"""Openstack Module is a base class for all Openstack Module classes.
|
||||
|
||||
The class has `run` function that should be overriden in child classes,
|
||||
the provided methods include:
|
||||
|
||||
Methods:
|
||||
params: Dictionary of Ansible module parameters.
|
||||
module_name: Module name (i.e. server_action)
|
||||
sdk_version: Version of used OpenstackSDK.
|
||||
results: Dictionary for return of Ansible module,
|
||||
must include `changed` keyword.
|
||||
exit, exit_json: Exit module and return data inside, must include
|
||||
changed` keyword in a data.
|
||||
fail, fail_json: Exit module with failure, has `msg` keyword to
|
||||
specify a reason of failure.
|
||||
conn: Connection to SDK object.
|
||||
log: Print message to system log.
|
||||
debug: Print debug message to system log, prints if Ansible Debug is
|
||||
enabled or verbosity is more than 2.
|
||||
check_deprecated_names: Function that checks if module was called with
|
||||
a deprecated name and prints the correct name
|
||||
with deprecation warning.
|
||||
check_versioned: helper function to check that all arguments are known
|
||||
in the current SDK version.
|
||||
run: method that executes and shall be overriden in inherited classes.
|
||||
|
||||
Args:
|
||||
deprecated_names: Should specify deprecated modules names for current
|
||||
module.
|
||||
argument_spec: Used for construction of Openstack common arguments.
|
||||
module_kwargs: Additional arguments for Ansible Module.
|
||||
"""
|
||||
|
||||
deprecated_names = ()
|
||||
argument_spec = {}
|
||||
module_kwargs = {}
|
||||
module_min_sdk_version = None
|
||||
module_max_sdk_version = None
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize Openstack base class.
|
||||
|
||||
super(OpenStackModule, self).__init__(
|
||||
Set up variables, connection to SDK and check if there are
|
||||
deprecated names.
|
||||
"""
|
||||
self.ansible = AnsibleModule(
|
||||
openstack_full_argument_spec(**self.argument_spec),
|
||||
**self.module_kwargs)
|
||||
self.params = self.ansible.params
|
||||
self.module_name = self.ansible._name
|
||||
self.check_mode = self.ansible.check_mode
|
||||
self.sdk_version = None
|
||||
self.results = {'changed': False}
|
||||
self.exit = self.exit_json = self.ansible.exit_json
|
||||
self.fail = self.fail_json = self.ansible.fail_json
|
||||
self.warn = self.ansible.warn
|
||||
self.sdk, self.conn = self.openstack_cloud_from_module()
|
||||
self.check_deprecated_names()
|
||||
self.setup_sdk_logging()
|
||||
|
||||
self.sdk, self.conn = openstack_cloud_from_module(self)
|
||||
def log(self, msg):
|
||||
"""Prints log message to system log.
|
||||
|
||||
Arguments:
|
||||
msg {str} -- Log message
|
||||
"""
|
||||
self.ansible.log(msg)
|
||||
|
||||
def debug(self, msg):
|
||||
"""Prints debug message to system log
|
||||
|
||||
Arguments:
|
||||
msg {str} -- Debug message.
|
||||
"""
|
||||
if self.ansible._debug or self.ansible._verbosity > 2:
|
||||
self.ansible.log(
|
||||
" ".join(['[DEBUG]', msg]))
|
||||
|
||||
def setup_sdk_logging(self):
|
||||
log_path = self.params.get('sdk_log_path')
|
||||
if log_path is not None:
|
||||
log_level = self.params.get('sdk_log_level')
|
||||
self.sdk.enable_logging(
|
||||
debug=True if log_level == 'DEBUG' else False,
|
||||
http_debug=True if log_level == 'DEBUG' else False,
|
||||
path=log_path
|
||||
)
|
||||
|
||||
def check_deprecated_names(self):
|
||||
"""Check deprecated module names if `deprecated_names` variable is set.
|
||||
"""
|
||||
new_module_name = OVERRIDES.get(self.module_name)
|
||||
if self.module_name in self.deprecated_names and new_module_name:
|
||||
self.ansible.deprecate(
|
||||
"The '%s' module has been renamed to '%s' in openstack "
|
||||
"collection: openstack.cloud.%s" % (
|
||||
self.module_name, new_module_name, new_module_name),
|
||||
version='2.0.0', collection_name='openstack.cloud')
|
||||
|
||||
def openstack_cloud_from_module(self):
|
||||
"""Sets up connection to cloud using provided options. Checks if all
|
||||
provided variables are supported for the used SDK version.
|
||||
"""
|
||||
try:
|
||||
# Due to the name shadowing we should import other way
|
||||
sdk = importlib.import_module('openstack')
|
||||
self.sdk_version = sdk.version.__version__
|
||||
except ImportError:
|
||||
self.fail_json(msg='openstacksdk is required for this module')
|
||||
|
||||
try:
|
||||
ensure_compatibility(self.sdk_version,
|
||||
self.module_min_sdk_version,
|
||||
self.module_max_sdk_version)
|
||||
except ImportError as e:
|
||||
self.fail_json(
|
||||
msg="Incompatible openstacksdk library found: {error}."
|
||||
.format(error=str(e)))
|
||||
|
||||
# Fail if there are set unsupported for this version parameters
|
||||
# New parameters should NOT use 'default' but rely on SDK defaults
|
||||
for param in self.argument_spec:
|
||||
if (self.params[param] is not None
|
||||
and 'min_ver' in self.argument_spec[param]
|
||||
and StrictVersion(self.sdk_version) < self.argument_spec[param]['min_ver']):
|
||||
self.fail_json(
|
||||
msg="To use parameter '{param}' with module '{module}', the installed version of "
|
||||
"the openstacksdk library MUST be >={min_version}.".format(
|
||||
min_version=self.argument_spec[param]['min_ver'],
|
||||
param=param,
|
||||
module=self.module_name))
|
||||
if (self.params[param] is not None
|
||||
and 'max_ver' in self.argument_spec[param]
|
||||
and StrictVersion(self.sdk_version) > self.argument_spec[param]['max_ver']):
|
||||
self.fail_json(
|
||||
msg="To use parameter '{param}' with module '{module}', the installed version of "
|
||||
"the openstacksdk library MUST be <={max_version}.".format(
|
||||
max_version=self.argument_spec[param]['max_ver'],
|
||||
param=param,
|
||||
module=self.module_name))
|
||||
|
||||
cloud_config = self.params.pop('cloud', None)
|
||||
if isinstance(cloud_config, dict):
|
||||
fail_message = (
|
||||
"A cloud config dict was provided to the cloud parameter"
|
||||
" but also a value was provided for {param}. If a cloud"
|
||||
" config dict is provided, {param} should be"
|
||||
" excluded.")
|
||||
for param in (
|
||||
'auth', 'region_name', 'validate_certs',
|
||||
'ca_cert', 'client_key', 'api_timeout', 'auth_type'):
|
||||
if self.params[param] is not None:
|
||||
self.fail_json(msg=fail_message.format(param=param))
|
||||
# For 'interface' parameter, fail if we receive a non-default value
|
||||
if self.params['interface'] != 'public':
|
||||
self.fail_json(msg=fail_message.format(param='interface'))
|
||||
else:
|
||||
cloud_config = dict(
|
||||
cloud=cloud_config,
|
||||
auth_type=self.params['auth_type'],
|
||||
auth=self.params['auth'],
|
||||
region_name=self.params['region_name'],
|
||||
verify=self.params['validate_certs'],
|
||||
cacert=self.params['ca_cert'],
|
||||
key=self.params['client_key'],
|
||||
api_timeout=self.params['api_timeout'],
|
||||
interface=self.params['interface'],
|
||||
)
|
||||
try:
|
||||
return sdk, sdk.connect(**cloud_config)
|
||||
except sdk.exceptions.SDKException as e:
|
||||
# Probably a cloud configuration/login error
|
||||
self.fail_json(msg=str(e))
|
||||
|
||||
# Filter out all arguments that are not from current SDK version
|
||||
def check_versioned(self, **kwargs):
|
||||
"""Check that provided arguments are supported by current SDK version
|
||||
|
||||
Returns:
|
||||
versioned_result {dict} dictionary of only arguments that are
|
||||
supported by current SDK version. All others
|
||||
are dropped.
|
||||
"""
|
||||
versioned_result = {}
|
||||
for var_name in kwargs:
|
||||
if ('min_ver' in self.argument_spec[var_name]
|
||||
and StrictVersion(self.sdk_version) < self.argument_spec[var_name]['min_ver']):
|
||||
continue
|
||||
if ('max_ver' in self.argument_spec[var_name]
|
||||
and StrictVersion(self.sdk_version) > self.argument_spec[var_name]['max_ver']):
|
||||
continue
|
||||
versioned_result.update({var_name: kwargs[var_name]})
|
||||
return versioned_result
|
||||
|
||||
@abc.abstractmethod
|
||||
def run(self):
|
||||
"""Function for overriding in inhetired classes, it's executed by default.
|
||||
"""
|
||||
pass
|
||||
|
||||
def __call__(self):
|
||||
"""Execute `run` function when calling the class.
|
||||
"""
|
||||
try:
|
||||
self.run()
|
||||
results = self.run()
|
||||
if results and isinstance(results, dict):
|
||||
self.ansible.exit_json(**results)
|
||||
except self.sdk.exceptions.OpenStackCloudException as e:
|
||||
self.fail_json(msg=str(e), extra_data=e.extra_data)
|
||||
params = {
|
||||
'msg': str(e),
|
||||
'extra_data': {
|
||||
'data': getattr(e, 'extra_data', 'None'),
|
||||
'details': getattr(e, 'details', 'None'),
|
||||
'response': getattr(getattr(e, 'response', ''),
|
||||
'text', 'None')
|
||||
}
|
||||
}
|
||||
self.ansible.fail_json(**params)
|
||||
# if we got to this place, modules didn't exit
|
||||
self.ansible.exit_json(**self.results)
|
||||
|
||||
201
plugins/modules/address_scope.py
Normal file
201
plugins/modules/address_scope.py
Normal file
@@ -0,0 +1,201 @@
|
||||
#!/usr/bin/python
|
||||
# coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2021 by Uemit Seren <uemit.seren@gmail.com>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: address_scope
|
||||
short_description: Create or delete address scopes from OpenStack
|
||||
author: OpenStack Ansible SIG
|
||||
description:
|
||||
- Create or Delete address scopes from OpenStack.
|
||||
options:
|
||||
state:
|
||||
description:
|
||||
- Indicate desired state of the resource
|
||||
choices: ['present', 'absent']
|
||||
default: present
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Name to be give to the address scope
|
||||
required: true
|
||||
type: str
|
||||
project:
|
||||
description:
|
||||
- Unique name or ID of the project.
|
||||
type: str
|
||||
ip_version:
|
||||
description:
|
||||
- The IP version of the subnet 4 or 6
|
||||
default: '4'
|
||||
type: str
|
||||
choices: ['4', '6']
|
||||
shared:
|
||||
description:
|
||||
- Whether this address scope is shared or not.
|
||||
type: bool
|
||||
default: 'no'
|
||||
extra_specs:
|
||||
description:
|
||||
- Dictionary with extra key/value pairs passed to the API
|
||||
required: false
|
||||
default: {}
|
||||
type: dict
|
||||
requirements:
|
||||
- "python >= 3.6"
|
||||
- "openstacksdk"
|
||||
|
||||
extends_documentation_fragment:
|
||||
- openstack.cloud.openstack
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# Create an IPv4 address scope.
|
||||
- openstack.cloud.address_scope:
|
||||
cloud: mycloud
|
||||
state: present
|
||||
name: my_adress_scope
|
||||
|
||||
# Create a shared IPv6 address scope for a given project.
|
||||
- openstack.cloud.address_scope:
|
||||
cloud: mycloud
|
||||
state: present
|
||||
ip_version: 6
|
||||
name: ipv6_address_scope
|
||||
project: myproj
|
||||
|
||||
# Delete address scope.
|
||||
- openstack.cloud.address_scope:
|
||||
cloud: mycloud
|
||||
state: absent
|
||||
name: my_adress_scope
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
address_scope:
|
||||
description: Dictionary describing the address scope.
|
||||
returned: On success when I(state) is 'present'
|
||||
type: complex
|
||||
contains:
|
||||
id:
|
||||
description: Address Scope ID.
|
||||
type: str
|
||||
sample: "474acfe5-be34-494c-b339-50f06aa143e4"
|
||||
name:
|
||||
description: Address Scope name.
|
||||
type: str
|
||||
sample: "my_address_scope"
|
||||
tenant_id:
|
||||
description: The tenant ID.
|
||||
type: str
|
||||
sample: "861174b82b43463c9edc5202aadc60ef"
|
||||
ip_version:
|
||||
description: The IP version of the subnet 4 or 6.
|
||||
type: str
|
||||
sample: "4"
|
||||
is_shared:
|
||||
description: Indicates whether this address scope is shared across all tenants.
|
||||
type: bool
|
||||
sample: false
|
||||
|
||||
'''
|
||||
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
class AddressScopeModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
name=dict(required=True),
|
||||
shared=dict(default=False, type='bool'),
|
||||
ip_version=dict(type='str', default='4', choices=['4', '6']),
|
||||
project=dict(default=None),
|
||||
extra_specs=dict(type='dict', default=dict())
|
||||
)
|
||||
|
||||
def _needs_update(self, address_scope, filters=None):
|
||||
"""Decide if the given address_scope needs an update.
|
||||
"""
|
||||
ip_version = int(self.params['ip_version'])
|
||||
if address_scope['is_shared'] != self.params['shared']:
|
||||
return True
|
||||
if ip_version and address_scope['ip_version'] != ip_version:
|
||||
self.fail_json(msg='Cannot update ip_version in existing address scope')
|
||||
return False
|
||||
|
||||
def _system_state_change(self, address_scope, filters=None):
|
||||
"""Check if the system state would be changed."""
|
||||
state = self.params['state']
|
||||
if state == 'absent' and address_scope:
|
||||
return True
|
||||
if state == 'present':
|
||||
if not address_scope:
|
||||
return True
|
||||
return self._needs_update(address_scope, filters)
|
||||
return False
|
||||
|
||||
def run(self):
|
||||
|
||||
state = self.params['state']
|
||||
name = self.params['name']
|
||||
shared = self.params['shared']
|
||||
ip_version = self.params['ip_version']
|
||||
project = self.params['project']
|
||||
extra_specs = self.params['extra_specs']
|
||||
|
||||
if project is not None:
|
||||
proj = self.conn.get_project(project)
|
||||
if proj is None:
|
||||
self.fail(msg='Project %s could not be found' % project)
|
||||
project_id = proj['id']
|
||||
else:
|
||||
project_id = self.conn.current_project_id
|
||||
|
||||
address_scope = self.conn.network.find_address_scope(name_or_id=name)
|
||||
if self.ansible.check_mode:
|
||||
self.exit_json(
|
||||
changed=self._system_state_change(address_scope)
|
||||
)
|
||||
|
||||
if state == 'present':
|
||||
changed = False
|
||||
|
||||
if not address_scope:
|
||||
kwargs = dict(
|
||||
name=name,
|
||||
ip_version=ip_version,
|
||||
is_shared=shared,
|
||||
tenant_id=project_id)
|
||||
dup_args = set(kwargs.keys()) & set(extra_specs.keys())
|
||||
if dup_args:
|
||||
raise ValueError('Duplicate key(s) {0} in extra_specs'
|
||||
.format(list(dup_args)))
|
||||
kwargs = dict(kwargs, **extra_specs)
|
||||
address_scope = self.conn.network.create_address_scope(**kwargs)
|
||||
changed = True
|
||||
else:
|
||||
if self._needs_update(address_scope):
|
||||
address_scope = self.conn.network.update_address_scope(address_scope['id'], is_shared=shared)
|
||||
changed = True
|
||||
else:
|
||||
changed = False
|
||||
self.exit_json(changed=changed, address_scope=address_scope, id=address_scope['id'])
|
||||
|
||||
elif state == 'absent':
|
||||
if not address_scope:
|
||||
self.exit(changed=False)
|
||||
else:
|
||||
self.conn.network.delete_address_scope(address_scope['id'])
|
||||
self.exit_json(changed=True)
|
||||
|
||||
|
||||
def main():
|
||||
module = AddressScopeModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -7,7 +7,7 @@ DOCUMENTATION = '''
|
||||
---
|
||||
module: auth
|
||||
short_description: Retrieve an auth token
|
||||
author: "Monty Taylor (@emonty)"
|
||||
author: OpenStack Ansible SIG
|
||||
description:
|
||||
- Retrieve an auth token from an OpenStack Cloud
|
||||
requirements:
|
||||
@@ -38,29 +38,24 @@ service_catalog:
|
||||
type: dict
|
||||
'''
|
||||
|
||||
import traceback
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
|
||||
class AuthModule(OpenStackModule):
|
||||
argument_spec = dict()
|
||||
module_kwargs = dict()
|
||||
|
||||
def run(self):
|
||||
self.exit_json(
|
||||
changed=False,
|
||||
ansible_facts=dict(
|
||||
auth_token=self.conn.auth_token,
|
||||
service_catalog=self.conn.service_catalog))
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
argument_spec = openstack_full_argument_spec()
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(argument_spec, **module_kwargs)
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
module.exit_json(
|
||||
changed=False,
|
||||
ansible_facts=dict(
|
||||
auth_token=cloud.auth_token,
|
||||
service_catalog=cloud.service_catalog))
|
||||
except Exception as e:
|
||||
module.fail_json(msg=str(e), exception=traceback.format_exc())
|
||||
module = AuthModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -8,7 +8,7 @@ DOCUMENTATION = '''
|
||||
---
|
||||
module: baremetal_inspect
|
||||
short_description: Explicitly triggers baremetal node introspection in ironic.
|
||||
author: "Julia Kreger (@juliakreger)"
|
||||
author: OpenStack Ansible SIG
|
||||
description:
|
||||
- Requests Ironic to set a node into inspect state in order to collect metadata regarding the node.
|
||||
This command may be out of band or in-band depending on the ironic driver configuration.
|
||||
@@ -75,10 +75,14 @@ EXAMPLES = '''
|
||||
name: "testnode1"
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.ironic import (
|
||||
IronicModule,
|
||||
ironic_argument_spec,
|
||||
)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module
|
||||
)
|
||||
|
||||
|
||||
def _choose_id_value(module):
|
||||
@@ -90,31 +94,14 @@ def _choose_id_value(module):
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
auth_type=dict(required=False),
|
||||
argument_spec = ironic_argument_spec(
|
||||
uuid=dict(required=False),
|
||||
name=dict(required=False),
|
||||
mac=dict(required=False),
|
||||
ironic_url=dict(required=False),
|
||||
timeout=dict(default=1200, type='int', required=False),
|
||||
)
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(argument_spec, **module_kwargs)
|
||||
|
||||
if (
|
||||
module.params['auth_type'] in [None, 'None']
|
||||
and module.params['ironic_url'] is None
|
||||
):
|
||||
module.fail_json(msg="Authentication appears to be disabled, "
|
||||
"Please define an ironic_url parameter")
|
||||
|
||||
if (
|
||||
module.params['ironic_url']
|
||||
and module.params['auth_type'] in [None, 'None']
|
||||
):
|
||||
module.params['auth'] = dict(
|
||||
endpoint=module.params['ironic_url']
|
||||
)
|
||||
module = IronicModule(argument_spec, **module_kwargs)
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
|
||||
@@ -8,7 +8,7 @@ DOCUMENTATION = '''
|
||||
---
|
||||
module: baremetal_node
|
||||
short_description: Create/Delete Bare Metal Resources from OpenStack
|
||||
author: "Monty Taylor (@emonty)"
|
||||
author: OpenStack Ansible SIG
|
||||
description:
|
||||
- Create or Remove Ironic nodes from OpenStack.
|
||||
options:
|
||||
@@ -43,29 +43,71 @@ options:
|
||||
endpoint URL for the Ironic API. Use with "auth" and "auth_type"
|
||||
settings set to None.
|
||||
type: str
|
||||
resource_class:
|
||||
description:
|
||||
- The specific resource type to which this node belongs.
|
||||
type: str
|
||||
bios_interface:
|
||||
description:
|
||||
- The bios interface for this node, e.g. "no-bios".
|
||||
type: str
|
||||
boot_interface:
|
||||
description:
|
||||
- The boot interface for this node, e.g. "pxe".
|
||||
type: str
|
||||
console_interface:
|
||||
description:
|
||||
- The console interface for this node, e.g. "no-console".
|
||||
type: str
|
||||
deploy_interface:
|
||||
description:
|
||||
- The deploy interface for this node, e.g. "iscsi".
|
||||
type: str
|
||||
inspect_interface:
|
||||
description:
|
||||
- The interface used for node inspection, e.g. "no-inspect".
|
||||
type: str
|
||||
management_interface:
|
||||
description:
|
||||
- The interface for out-of-band management of this node, e.g.
|
||||
"ipmitool".
|
||||
type: str
|
||||
network_interface:
|
||||
description:
|
||||
- The network interface provider to use when describing
|
||||
connections for this node.
|
||||
type: str
|
||||
power_interface:
|
||||
description:
|
||||
- The interface used to manage power actions on this node, e.g.
|
||||
"ipmitool".
|
||||
type: str
|
||||
raid_interface:
|
||||
description:
|
||||
- Interface used for configuring raid on this node.
|
||||
type: str
|
||||
rescue_interface:
|
||||
description:
|
||||
- Interface used for node rescue, e.g. "no-rescue".
|
||||
type: str
|
||||
storage_interface:
|
||||
description:
|
||||
- Interface used for attaching and detaching volumes on this node, e.g.
|
||||
"cinder".
|
||||
type: str
|
||||
vendor_interface:
|
||||
description:
|
||||
- Interface for all vendor-specific actions on this node, e.g.
|
||||
"no-vendor".
|
||||
type: str
|
||||
driver_info:
|
||||
description:
|
||||
- Information for this server's driver. Will vary based on which
|
||||
driver is in use. Any sub-field which is populated will be validated
|
||||
during creation.
|
||||
during creation. For compatibility reasons sub-fields `power`,
|
||||
`deploy`, `management` and `console` are flattened.
|
||||
required: true
|
||||
type: dict
|
||||
suboptions:
|
||||
power:
|
||||
description:
|
||||
- Information necessary to turn this server on / off.
|
||||
This often includes such things as IPMI username, password, and IP address.
|
||||
required: true
|
||||
deploy:
|
||||
description:
|
||||
- Information necessary to deploy this server directly, without using Nova. THIS IS NOT RECOMMENDED.
|
||||
console:
|
||||
description:
|
||||
- Information necessary to connect to this server's serial console. Not all drivers support this.
|
||||
management:
|
||||
description:
|
||||
- Information necessary to interact with this server's management interface. May be shared by power_info in some cases.
|
||||
required: true
|
||||
nics:
|
||||
description:
|
||||
- 'A list of network interface cards, eg, " - mac: aa:bb:cc:aa:bb:cc"'
|
||||
@@ -118,10 +160,10 @@ options:
|
||||
- As of Kilo, by default, passwords are always masked to API
|
||||
requests, which means the logic as a result always attempts to
|
||||
re-assert the password field.
|
||||
- C(skip_update_of_driver_password) is deprecated alias and will be removed in 2.14.
|
||||
- C(skip_update_of_driver_password) is deprecated alias and will be removed in openstack.cloud 2.0.0.
|
||||
type: bool
|
||||
default: 'no'
|
||||
aliases: [ skip_update_of_driver_password ]
|
||||
aliases:
|
||||
- skip_update_of_driver_password
|
||||
requirements:
|
||||
- "python >= 3.6"
|
||||
- "openstacksdk"
|
||||
@@ -149,10 +191,9 @@ EXAMPLES = '''
|
||||
- mac: "aa:bb:cc:aa:bb:cc"
|
||||
- mac: "dd:ee:ff:dd:ee:ff"
|
||||
driver_info:
|
||||
power:
|
||||
ipmi_address: "1.2.3.4"
|
||||
ipmi_username: "admin"
|
||||
ipmi_password: "adminpass"
|
||||
ipmi_address: "1.2.3.4"
|
||||
ipmi_username: "admin"
|
||||
ipmi_password: "adminpass"
|
||||
chassis_uuid: "00000000-0000-0000-0000-000000000001"
|
||||
|
||||
'''
|
||||
@@ -163,37 +204,46 @@ try:
|
||||
except ImportError:
|
||||
HAS_JSONPATCH = False
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.ironic import (
|
||||
IronicModule,
|
||||
ironic_argument_spec,
|
||||
)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module
|
||||
)
|
||||
|
||||
|
||||
_PROPERTIES = {
|
||||
'cpu_arch': 'cpu_arch',
|
||||
'cpus': 'cpus',
|
||||
'ram': 'memory_mb',
|
||||
'disk_size': 'local_gb',
|
||||
'capabilities': 'capabilities',
|
||||
'root_device': 'root_device',
|
||||
}
|
||||
|
||||
|
||||
def _parse_properties(module):
|
||||
"""Convert ansible properties into native ironic values.
|
||||
|
||||
Also filter out any properties that are not set.
|
||||
"""
|
||||
p = module.params['properties']
|
||||
props = dict(
|
||||
cpu_arch=p.get('cpu_arch') if p.get('cpu_arch') else 'x86_64',
|
||||
cpus=p.get('cpus') if p.get('cpus') else 1,
|
||||
memory_mb=p.get('ram') if p.get('ram') else 1,
|
||||
local_gb=p.get('disk_size') if p.get('disk_size') else 1,
|
||||
capabilities=p.get('capabilities') if p.get('capabilities') else '',
|
||||
root_device=p.get('root_device') if p.get('root_device') else '',
|
||||
)
|
||||
return props
|
||||
return {to_key: p[from_key] for (from_key, to_key) in _PROPERTIES.items()
|
||||
if p.get(from_key) is not None}
|
||||
|
||||
|
||||
def _parse_driver_info(sdk, module):
|
||||
p = module.params['driver_info']
|
||||
info = p.get('power')
|
||||
if not info:
|
||||
raise sdk.exceptions.OpenStackCloudException(
|
||||
"driver_info['power'] is required")
|
||||
if p.get('console'):
|
||||
info.update(p.get('console'))
|
||||
if p.get('management'):
|
||||
info.update(p.get('management'))
|
||||
if p.get('deploy'):
|
||||
info.update(p.get('deploy'))
|
||||
info = module.params['driver_info'].copy()
|
||||
for deprecated in ('power', 'console', 'management', 'deploy'):
|
||||
if deprecated in info:
|
||||
info.update(info.pop(deprecated))
|
||||
module.deprecate("Suboption %s of the driver_info parameter of "
|
||||
"'openstack.cloud.baremetal_node' is deprecated"
|
||||
% deprecated, version='2.0.0',
|
||||
collection_name='openstack.cloud')
|
||||
return info
|
||||
|
||||
|
||||
@@ -224,42 +274,43 @@ def _exit_node_not_updated(module, server):
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
argument_spec = ironic_argument_spec(
|
||||
uuid=dict(required=False),
|
||||
name=dict(required=False),
|
||||
driver=dict(required=False),
|
||||
resource_class=dict(required=False),
|
||||
bios_interface=dict(required=False),
|
||||
boot_interface=dict(required=False),
|
||||
console_interface=dict(required=False),
|
||||
deploy_interface=dict(required=False),
|
||||
inspect_interface=dict(required=False),
|
||||
management_interface=dict(required=False),
|
||||
network_interface=dict(required=False),
|
||||
power_interface=dict(required=False),
|
||||
raid_interface=dict(required=False),
|
||||
rescue_interface=dict(required=False),
|
||||
storage_interface=dict(required=False),
|
||||
vendor_interface=dict(required=False),
|
||||
driver_info=dict(type='dict', required=True),
|
||||
nics=dict(type='list', required=True, elements="dict"),
|
||||
properties=dict(type='dict', default={}),
|
||||
ironic_url=dict(required=False),
|
||||
chassis_uuid=dict(required=False),
|
||||
skip_update_of_masked_password=dict(
|
||||
required=False,
|
||||
type='bool',
|
||||
aliases=['skip_update_of_driver_password'],
|
||||
deprecated_aliases=[dict(name='skip_update_of_driver_password', version='2.14')]
|
||||
deprecated_aliases=[dict(
|
||||
name='skip_update_of_driver_password',
|
||||
version='2.0.0',
|
||||
collection_name='openstack.cloud')]
|
||||
),
|
||||
state=dict(required=False, default='present', choices=['present', 'absent'])
|
||||
)
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(argument_spec, **module_kwargs)
|
||||
module = IronicModule(argument_spec, **module_kwargs)
|
||||
|
||||
if not HAS_JSONPATCH:
|
||||
module.fail_json(msg='jsonpatch is required for this module')
|
||||
if (
|
||||
module.params['auth_type'] in [None, 'None']
|
||||
and module.params['ironic_url'] is None
|
||||
):
|
||||
module.fail_json(msg="Authentication appears to be disabled, "
|
||||
"Please define an ironic_url parameter")
|
||||
|
||||
if (
|
||||
module.params['ironic_url']
|
||||
and module.params['auth_type'] in [None, 'None']
|
||||
):
|
||||
module.params['auth'] = dict(
|
||||
endpoint=module.params['ironic_url']
|
||||
)
|
||||
|
||||
node_id = _choose_id_value(module)
|
||||
|
||||
@@ -279,6 +330,22 @@ def main():
|
||||
driver_info=driver_info,
|
||||
name=module.params['name'],
|
||||
)
|
||||
optional_field_names = ('resource_class',
|
||||
'bios_interface',
|
||||
'boot_interface',
|
||||
'console_interface',
|
||||
'deploy_interface',
|
||||
'inspect_interface',
|
||||
'management_interface',
|
||||
'network_interface',
|
||||
'power_interface',
|
||||
'raid_interface',
|
||||
'rescue_interface',
|
||||
'storage_interface',
|
||||
'vendor_interface')
|
||||
for i in optional_field_names:
|
||||
if module.params[i]:
|
||||
kwargs[i] = module.params[i]
|
||||
|
||||
if module.params['chassis_uuid']:
|
||||
kwargs['chassis_uuid'] = module.params['chassis_uuid']
|
||||
|
||||
@@ -8,7 +8,7 @@ DOCUMENTATION = '''
|
||||
---
|
||||
module: baremetal_node_action
|
||||
short_description: Activate/Deactivate Bare Metal Resources from OpenStack
|
||||
author: "Monty Taylor (@emonty)"
|
||||
author: OpenStack Ansible SIG
|
||||
description:
|
||||
- Deploy to nodes controlled by Ironic.
|
||||
options:
|
||||
@@ -132,10 +132,15 @@ EXAMPLES = '''
|
||||
delegate_to: localhost
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.ironic import (
|
||||
IronicModule,
|
||||
ironic_argument_spec,
|
||||
)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module
|
||||
)
|
||||
|
||||
|
||||
def _choose_id_value(module):
|
||||
@@ -227,12 +232,11 @@ def _check_set_power_state(module, cloud, node):
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
argument_spec = ironic_argument_spec(
|
||||
uuid=dict(required=False),
|
||||
name=dict(required=False),
|
||||
instance_info=dict(type='dict', required=False),
|
||||
config_drive=dict(type='raw', required=False),
|
||||
ironic_url=dict(required=False),
|
||||
state=dict(required=False, default='present'),
|
||||
maintenance=dict(required=False),
|
||||
maintenance_reason=dict(required=False),
|
||||
@@ -242,22 +246,7 @@ def main():
|
||||
timeout=dict(required=False, type='int', default=1800),
|
||||
)
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(argument_spec, **module_kwargs)
|
||||
|
||||
if (
|
||||
module.params['auth_type'] in [None, 'None']
|
||||
and module.params['ironic_url'] is None
|
||||
):
|
||||
module.fail_json(msg="Authentication appears disabled, Please "
|
||||
"define an ironic_url parameter")
|
||||
|
||||
if (
|
||||
module.params['ironic_url']
|
||||
and module.params['auth_type'] in [None, 'None']
|
||||
):
|
||||
module.params['auth'] = dict(
|
||||
endpoint=module.params['ironic_url']
|
||||
)
|
||||
module = IronicModule(argument_spec, **module_kwargs)
|
||||
|
||||
if (
|
||||
module.params['config_drive']
|
||||
|
||||
555
plugins/modules/baremetal_node_info.py
Normal file
555
plugins/modules/baremetal_node_info.py
Normal file
@@ -0,0 +1,555 @@
|
||||
#!/usr/bin/python
|
||||
# coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2021 by Red Hat, Inc.
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
module: baremetal_node_info
|
||||
short_description: Retrieve information about Bare Metal nodes from OpenStack
|
||||
author: OpenStack Ansible SIG
|
||||
description:
|
||||
- Retrieve information about Bare Metal nodes from OpenStack.
|
||||
options:
|
||||
node:
|
||||
description:
|
||||
- Name or globally unique identifier (UUID) to identify the host.
|
||||
type: str
|
||||
mac:
|
||||
description:
|
||||
- Unique mac address that is used to attempt to identify the host.
|
||||
type: str
|
||||
ironic_url:
|
||||
description:
|
||||
- If noauth mode is utilized, this is required to be set to the
|
||||
endpoint URL for the Ironic API. Use with "auth" and "auth_type"
|
||||
settings set to None.
|
||||
type: str
|
||||
requirements:
|
||||
- "python >= 3.6"
|
||||
- "openstacksdk"
|
||||
|
||||
extends_documentation_fragment:
|
||||
- openstack.cloud.openstack
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# Gather information about all baremeal nodes
|
||||
- openstack.cloud.baremetal_node_info:
|
||||
cloud: "devstack"
|
||||
register: result
|
||||
- debug:
|
||||
msg: "{{ result.baremetal_nodes }}"
|
||||
# Gather information about a baremeal node
|
||||
- openstack.cloud.baremetal_node_info:
|
||||
cloud: "devstack"
|
||||
node: "00000000-0000-0000-0000-000000000002"
|
||||
register: result
|
||||
- debug:
|
||||
msg: "{{ result.baremetal_nodes }}"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
baremetal_nodes:
|
||||
description: Bare Metal node list. A subset of the dictionary keys
|
||||
listed below may be returned, depending on your cloud
|
||||
provider.
|
||||
returned: always, but can be null
|
||||
type: complex
|
||||
contains:
|
||||
allocation_uuid:
|
||||
description: The UUID of the allocation associated with the node.
|
||||
If not null, will be the same as instance_uuid (the
|
||||
opposite is not always true). Unlike instance_uuid,
|
||||
this field is read-only. Please use the Allocation API
|
||||
to remove allocations.
|
||||
returned: success
|
||||
type: str
|
||||
automated_clean:
|
||||
description: Indicates whether the node will perform automated
|
||||
clean or not.
|
||||
returned: success
|
||||
type: bool
|
||||
bios_interface:
|
||||
description: The bios interface to be used for this node.
|
||||
returned: success
|
||||
type: str
|
||||
boot_interface:
|
||||
description: The boot interface for a Node, e.g. "pxe".
|
||||
returned: success
|
||||
type: str
|
||||
boot_mode:
|
||||
description: The boot mode for a node, either "uefi" or "bios"
|
||||
returned: success
|
||||
type: str
|
||||
chassis_uuid:
|
||||
description: UUID of the chassis associated with this Node. May be
|
||||
empty or None.
|
||||
returned: success
|
||||
type: str
|
||||
clean_step:
|
||||
description: The current clean step.
|
||||
returned: success
|
||||
type: str
|
||||
conductor:
|
||||
description: The conductor currently servicing a node. This field
|
||||
is read-only.
|
||||
returned: success
|
||||
type: str
|
||||
conductor_group:
|
||||
description: The conductor group for a node. Case-insensitive
|
||||
string up to 255 characters, containing a-z, 0-9, _,
|
||||
-, and ..
|
||||
returned: success
|
||||
type: str
|
||||
console_enabled:
|
||||
description: Indicates whether console access is enabled or
|
||||
disabled on this node.
|
||||
returned: success
|
||||
type: bool
|
||||
console_interface:
|
||||
description: The console interface for a node, e.g. "no-console".
|
||||
returned: success
|
||||
type: str
|
||||
created_at:
|
||||
description: Bare Metal node created at timestamp.
|
||||
returned: success
|
||||
type: str
|
||||
deploy_interface:
|
||||
description: The deploy interface for a node, e.g. "direct".
|
||||
returned: success
|
||||
type: str
|
||||
deploy_step:
|
||||
description: The current deploy step.
|
||||
returned: success
|
||||
type: str
|
||||
driver:
|
||||
description: The name of the driver.
|
||||
returned: success
|
||||
type: str
|
||||
driver_info:
|
||||
description: All the metadata required by the driver to manage this
|
||||
Node. List of fields varies between drivers, and can
|
||||
be retrieved from the
|
||||
/v1/drivers/<DRIVER_NAME>/properties resource.
|
||||
returned: success
|
||||
type: dict
|
||||
driver_internal_info:
|
||||
description: Internal metadata set and stored by the Node's driver.
|
||||
returned: success
|
||||
type: dict
|
||||
extra:
|
||||
description: A set of one or more arbitrary metadata key and value
|
||||
pairs.
|
||||
returned: success
|
||||
type: dict
|
||||
fault:
|
||||
description: The fault indicates the active fault detected by
|
||||
ironic, typically the Node is in "maintenance mode".
|
||||
None means no fault has been detected by ironic.
|
||||
"power failure" indicates ironic failed to retrieve
|
||||
power state from this node. There are other possible
|
||||
types, e.g., "clean failure" and "rescue abort
|
||||
failure".
|
||||
returned: success
|
||||
type: str
|
||||
id:
|
||||
description: The UUID for the resource.
|
||||
returned: success
|
||||
type: str
|
||||
inspect_interface:
|
||||
description: The interface used for node inspection.
|
||||
returned: success
|
||||
type: str
|
||||
instance_info:
|
||||
description: Information used to customize the deployed image. May
|
||||
include root partition size, a base 64 encoded config
|
||||
drive, and other metadata. Note that this field is
|
||||
erased automatically when the instance is deleted
|
||||
(this is done by requesting the Node provision state
|
||||
be changed to DELETED).
|
||||
returned: success
|
||||
type: dict
|
||||
instance_uuid:
|
||||
description: UUID of the Nova instance associated with this Node.
|
||||
returned: success
|
||||
type: str
|
||||
last_error:
|
||||
description: Any error from the most recent (last) transaction that
|
||||
started but failed to finish.
|
||||
returned: success
|
||||
type: str
|
||||
maintenance:
|
||||
description: Whether or not this Node is currently in "maintenance
|
||||
mode". Setting a Node into maintenance mode removes it
|
||||
from the available resource pool and halts some
|
||||
internal automation. This can happen manually (eg, via
|
||||
an API request) or automatically when Ironic detects a
|
||||
hardware fault that prevents communication with the
|
||||
machine.
|
||||
returned: success
|
||||
type: bool
|
||||
maintenance_reason:
|
||||
description: User-settable description of the reason why this Node
|
||||
was placed into maintenance mode
|
||||
returned: success
|
||||
type: str
|
||||
management_interface:
|
||||
description: Interface for out-of-band node management.
|
||||
returned: success
|
||||
type: str
|
||||
name:
|
||||
description: Human-readable identifier for the Node resource. May
|
||||
be undefined. Certain words are reserved.
|
||||
returned: success
|
||||
type: str
|
||||
network_interface:
|
||||
description: Which Network Interface provider to use when plumbing
|
||||
the network connections for this Node.
|
||||
returned: success
|
||||
type: str
|
||||
owner:
|
||||
description: A string or UUID of the tenant who owns the object.
|
||||
returned: success
|
||||
type: str
|
||||
portgroups:
|
||||
description: List of ironic portgroups on this node.
|
||||
returned: success
|
||||
type: list
|
||||
elements: dict
|
||||
contains:
|
||||
address:
|
||||
description: Physical hardware address of this Portgroup,
|
||||
typically the hardware MAC address.
|
||||
returned: success
|
||||
type: str
|
||||
created_at:
|
||||
description: The UTC date and time when the resource was
|
||||
created, ISO 8601 format.
|
||||
returned: success
|
||||
type: str
|
||||
extra:
|
||||
description: A set of one or more arbitrary metadata key and
|
||||
value pairs.
|
||||
returned: success
|
||||
type: dict
|
||||
id:
|
||||
description: The UUID for the resource.
|
||||
returned: success
|
||||
type: str
|
||||
internal_info:
|
||||
description: Internal metadata set and stored by the Portgroup.
|
||||
This field is read-only.
|
||||
returned: success
|
||||
type: dict
|
||||
is_standalone_ports_supported:
|
||||
description: Indicates whether ports that are members of this
|
||||
portgroup can be used as stand-alone ports.
|
||||
returned: success
|
||||
type: bool
|
||||
mode:
|
||||
description: Mode of the port group. For possible values, refer
|
||||
to https://www.kernel.org/doc/Documentation/networking/bonding.txt.
|
||||
If not specified in a request to create a port
|
||||
group, it will be set to the value of the
|
||||
[DEFAULT]default_portgroup_mode configuration
|
||||
option. When set, can not be removed from the port
|
||||
group.
|
||||
returned: success
|
||||
type: str
|
||||
name:
|
||||
description: Human-readable identifier for the Portgroup
|
||||
resource. May be undefined.
|
||||
returned: success
|
||||
type: str
|
||||
node_id:
|
||||
description: UUID of the Node this resource belongs to.
|
||||
returned: success
|
||||
type: str
|
||||
ports:
|
||||
description: List of port UUID's of ports belonging to this
|
||||
portgroup.
|
||||
returned: success
|
||||
type: list
|
||||
properties:
|
||||
description: Key/value properties related to the port group's
|
||||
configuration.
|
||||
returned: success
|
||||
type: dict
|
||||
updated_at:
|
||||
description: The UTC date and time when the resource was
|
||||
updated, ISO 8601 format. May be "null".
|
||||
returned: success
|
||||
type: str
|
||||
ports:
|
||||
description: List of ironic ports on this node.
|
||||
returned: success
|
||||
type: list
|
||||
elements: dict
|
||||
contains:
|
||||
address:
|
||||
description: Physical hardware address of this network Port,
|
||||
typically the hardware MAC address.
|
||||
returned: success
|
||||
type: str
|
||||
created_at:
|
||||
description: The UTC date and time when the resource was
|
||||
created, ISO 8601 format.
|
||||
returned: success
|
||||
type: str
|
||||
extra:
|
||||
description: A set of one or more arbitrary metadata key and
|
||||
value pairs.
|
||||
returned: success
|
||||
type: dict
|
||||
id:
|
||||
description: The UUID for the resource.
|
||||
returned: success
|
||||
type: str
|
||||
internal_info:
|
||||
description: Internal metadata set and stored by the Port. This
|
||||
field is read-only.
|
||||
returned: success
|
||||
type: dict
|
||||
local_link_connection:
|
||||
description: The Port binding profile. If specified, must
|
||||
contain switch_id (only a MAC address or an
|
||||
OpenFlow based datapath_id of the switch are
|
||||
accepted in this field) and port_id (identifier of
|
||||
the physical port on the switch to which node's
|
||||
port is connected to) fields. switch_info is an
|
||||
optional string field to be used to store any
|
||||
vendor-specific information.
|
||||
returned: success
|
||||
type: dict
|
||||
name:
|
||||
description: The name of the resource.
|
||||
returned: success
|
||||
type: str
|
||||
node_uuid:
|
||||
description: UUID of the Node this resource belongs to.
|
||||
returned: success
|
||||
type: str
|
||||
physical_network:
|
||||
description: The name of the physical network to which a port
|
||||
is connected. May be empty.
|
||||
returned: success
|
||||
type: str
|
||||
portgroup_uuid:
|
||||
description: UUID of the Portgroup this resource belongs to.
|
||||
returned: success
|
||||
type: str
|
||||
pxe_enabled:
|
||||
description: Indicates whether PXE is enabled or disabled on
|
||||
the Port.
|
||||
returned: success
|
||||
type: str
|
||||
updated_at:
|
||||
description: The UTC date and time when the resource was
|
||||
updated, ISO 8601 format. May be "null".
|
||||
returned: success
|
||||
type: str
|
||||
uuid:
|
||||
description: The UUID for the resource.
|
||||
returned: success
|
||||
type: str
|
||||
power_interface:
|
||||
description: Interface used for performing power actions on the
|
||||
node, e.g. "ipmitool".
|
||||
returned: success
|
||||
type: str
|
||||
power_state:
|
||||
description: The current power state of this Node. Usually, "power
|
||||
on" or "power off", but may be "None" if Ironic is
|
||||
unable to determine the power state (eg, due to
|
||||
hardware failure).
|
||||
returned: success
|
||||
type: str
|
||||
properties:
|
||||
description: Physical characteristics of this Node. Populated by
|
||||
ironic-inspector during inspection. May be edited via
|
||||
the REST API at any time.
|
||||
returned: success
|
||||
type: dict
|
||||
protected:
|
||||
description: Whether the node is protected from undeploying,
|
||||
rebuilding and deletion.
|
||||
returned: success
|
||||
type: bool
|
||||
protected_reason:
|
||||
description: The reason the node is marked as protected.
|
||||
returned: success
|
||||
type: str
|
||||
provision_state:
|
||||
description: The current provisioning state of this Node.
|
||||
returned: success
|
||||
type: str
|
||||
raid_config:
|
||||
description: Represents the current RAID configuration of the node.
|
||||
Introduced with the cleaning feature.
|
||||
returned: success
|
||||
type: dict
|
||||
raid_interface:
|
||||
description: Interface used for configuring RAID on this node.
|
||||
returned: success
|
||||
type: str
|
||||
rescue_interface:
|
||||
description: The interface used for node rescue, e.g. "no-rescue".
|
||||
returned: success
|
||||
type: str
|
||||
reservation:
|
||||
description: The name of an Ironic Conductor host which is holding
|
||||
a lock on this node, if a lock is held. Usually
|
||||
"null", but this field can be useful for debugging.
|
||||
returned: success
|
||||
type: str
|
||||
resource_class:
|
||||
description: A string which can be used by external schedulers to
|
||||
identify this Node as a unit of a specific type of
|
||||
resource. For more details, see
|
||||
https://docs.openstack.org/ironic/latest/install/configure-nova-flavors.html
|
||||
returned: success
|
||||
type: str
|
||||
retired:
|
||||
description: Whether the node is retired and can hence no longer be
|
||||
provided, i.e. move from manageable to available, and
|
||||
will end up in manageable after cleaning (rather than
|
||||
available).
|
||||
returned: success
|
||||
type: bool
|
||||
retired_reason:
|
||||
description: The reason the node is marked as retired.
|
||||
returned: success
|
||||
type: str
|
||||
secure_boot:
|
||||
description: Indicates whether node is currently booted with
|
||||
secure_boot turned on.
|
||||
returned: success
|
||||
type: bool
|
||||
storage_interface:
|
||||
description: Interface used for attaching and detaching volumes on
|
||||
this node, e.g. "cinder".
|
||||
returned: success
|
||||
type: str
|
||||
target_power_state:
|
||||
description: If a power state transition has been requested, this
|
||||
field represents the requested (ie, "target") state,
|
||||
either "power on" or "power off".
|
||||
returned: success
|
||||
type: str
|
||||
target_provision_state:
|
||||
description: If a provisioning action has been requested, this
|
||||
field represents the requested (ie, "target") state.
|
||||
Note that a Node may go through several states during
|
||||
its transition to this target state. For instance,
|
||||
when requesting an instance be deployed to an
|
||||
AVAILABLE Node, the Node may go through the following
|
||||
state change progression, AVAILABLE -> DEPLOYING ->
|
||||
DEPLOYWAIT -> DEPLOYING -> ACTIVE
|
||||
returned: success
|
||||
type: str
|
||||
target_raid_config:
|
||||
description: Represents the requested RAID configuration of the
|
||||
node, which will be applied when the Node next
|
||||
transitions through the CLEANING state. Introduced
|
||||
with the cleaning feature.
|
||||
returned: success
|
||||
type: dict
|
||||
traits:
|
||||
description: List of traits for this node.
|
||||
returned: success
|
||||
type: list
|
||||
updated_at:
|
||||
description: Bare Metal node updated at timestamp.
|
||||
returned: success
|
||||
type: str
|
||||
uuid:
|
||||
description: The UUID for the resource.
|
||||
returned: success
|
||||
type: str
|
||||
vendor_interface:
|
||||
description: Interface for vendor-specific functionality on this
|
||||
node, e.g. "no-vendor".
|
||||
returned: success
|
||||
type: str
|
||||
'''
|
||||
|
||||
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.ironic import (
|
||||
IronicModule,
|
||||
ironic_argument_spec,
|
||||
)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module
|
||||
)
|
||||
|
||||
|
||||
def cleanup_node_properties(machine, cloud):
|
||||
# states are links, not useful
|
||||
machine.pop('states', None)
|
||||
|
||||
for port in machine.ports:
|
||||
# links are not useful
|
||||
port.pop('links', None)
|
||||
# redundant, location is in on machine as well
|
||||
port.pop('location', None)
|
||||
|
||||
for portgroup in machine.portgroups:
|
||||
# links are not useful
|
||||
portgroup.pop('links', None)
|
||||
# redundant, location is in on machine as well
|
||||
portgroup.pop('location', None)
|
||||
# links to ports are not useful, replace with list of port uuid's
|
||||
portgroup['ports'] = [x.id for x in list(
|
||||
cloud.baremetal.ports(portgroup=portgroup['id']))]
|
||||
|
||||
|
||||
def get_ports_and_portgroups(cloud, machine):
|
||||
machine.ports = cloud.list_nics_for_machine(machine.uuid)
|
||||
machine.portgroups = [dict(x) for x in
|
||||
list(cloud.baremetal.port_groups(node=machine.uuid,
|
||||
details=True))]
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = ironic_argument_spec(
|
||||
node=dict(required=False),
|
||||
mac=dict(required=False),
|
||||
)
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module_kwargs['supports_check_mode'] = True
|
||||
|
||||
module = IronicModule(argument_spec, **module_kwargs)
|
||||
|
||||
machine = None
|
||||
machines = list()
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
if module.params['node']:
|
||||
machine = cloud.get_machine(module.params['node'])
|
||||
elif module.params['mac']:
|
||||
machine = cloud.get_machine_by_mac(module.params['mac'])
|
||||
|
||||
# Fail if node not found
|
||||
if (module.params['node'] or module.params['mac']) and not machine:
|
||||
module.fail_json(msg='The baremetal node was not found')
|
||||
|
||||
if machine:
|
||||
machines.append(machine)
|
||||
else:
|
||||
machines = cloud.list_machines()
|
||||
|
||||
for machine in machines:
|
||||
get_ports_and_portgroups(cloud, machine)
|
||||
cleanup_node_properties(machine, cloud)
|
||||
|
||||
module.exit_json(changed=False, baremetal_nodes=machines)
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
373
plugins/modules/baremetal_port.py
Normal file
373
plugins/modules/baremetal_port.py
Normal file
@@ -0,0 +1,373 @@
|
||||
#!/usr/bin/python
|
||||
# coding: utf-8 -*-
|
||||
# Copyright (c) 2021 by Red Hat, Inc.
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
DOCUMENTATION = '''
|
||||
module: baremetal_port
|
||||
short_description: Create/Delete Bare Metal port Resources from OpenStack
|
||||
author: OpenStack Ansible SIG
|
||||
description:
|
||||
- Create, Update and Remove ironic ports from OpenStack.
|
||||
options:
|
||||
state:
|
||||
description:
|
||||
- Indicates desired state of the resource
|
||||
choices: ['present', 'absent']
|
||||
default: present
|
||||
type: str
|
||||
uuid:
|
||||
description:
|
||||
- globally unique identifier (UUID) to be given to the resource. Will
|
||||
be auto-generated if not specified.
|
||||
type: str
|
||||
node:
|
||||
description:
|
||||
- UUID or Name of the Node this resource belongs to.
|
||||
type: str
|
||||
address:
|
||||
description:
|
||||
- Physical hardware address of this network Port, typically the
|
||||
hardware MAC address.
|
||||
type: str
|
||||
portgroup:
|
||||
description:
|
||||
- UUID or Name of the Portgroup this resource belongs to.
|
||||
type: str
|
||||
local_link_connection:
|
||||
description:
|
||||
- The Port binding profile.
|
||||
type: dict
|
||||
suboptions:
|
||||
switch_id:
|
||||
description:
|
||||
- A MAC address or an OpenFlow based datapath_id of the switch.
|
||||
type: str
|
||||
port_id:
|
||||
description:
|
||||
- Identifier of the physical port on the switch to which node's
|
||||
port is connected to.
|
||||
type: str
|
||||
switch_info:
|
||||
description:
|
||||
- An optional string field to be used to store any vendor-specific
|
||||
information.
|
||||
type: str
|
||||
is_pxe_enabled:
|
||||
description:
|
||||
- Whether PXE should be enabled or disabled on the Port.
|
||||
type: bool
|
||||
physical_network:
|
||||
description:
|
||||
- The name of the physical network to which a port is connected.
|
||||
type: str
|
||||
extra:
|
||||
description:
|
||||
- A set of one or more arbitrary metadata key and value pairs.
|
||||
type: dict
|
||||
ironic_url:
|
||||
description:
|
||||
- If noauth mode is utilized, this is required to be set to the
|
||||
endpoint URL for the Ironic API. Use with "auth" and "auth_type"
|
||||
settings set to None.
|
||||
type: str
|
||||
|
||||
requirements:
|
||||
- "python >= 3.6"
|
||||
- "openstacksdk"
|
||||
extends_documentation_fragment:
|
||||
- openstack.cloud.openstack
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# Create Bare Metal port
|
||||
- name: Create Bare Metal port
|
||||
openstack.cloud.baremetal_port:
|
||||
cloud: devstack
|
||||
state: present
|
||||
node: bm-0
|
||||
address: fa:16:3e:aa:aa:aa
|
||||
pxe_enabled: True
|
||||
local_link_connection:
|
||||
switch_id: 0a:1b:2c:3d:4e:5f
|
||||
port_id: Ethernet3/1
|
||||
switch_info: switch1
|
||||
extra:
|
||||
something: extra
|
||||
physical_network: datacenter
|
||||
register: result
|
||||
# Delete Bare Metal port
|
||||
- name: Delete Bare Metal port
|
||||
openstack.cloud.baremetal_port:
|
||||
cloud: devstack
|
||||
state: absent
|
||||
address: fa:16:3e:aa:aa:aa
|
||||
register: result
|
||||
# Update Bare Metal port
|
||||
- name: Update Bare Metal port
|
||||
openstack.cloud.baremetal_port:
|
||||
cloud: devstack
|
||||
state: present
|
||||
uuid: 1a85ebca-22bf-42eb-ad9e-f640789b8098
|
||||
pxe_enabled: False
|
||||
local_link_connection:
|
||||
switch_id: a0:b1:c2:d3:e4:f5
|
||||
port_id: Ethernet4/12
|
||||
switch_info: switch2
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
id:
|
||||
description: Unique UUID of the port.
|
||||
returned: always, but can be null
|
||||
type: str
|
||||
result:
|
||||
description: A short text describing the result.
|
||||
returned: success
|
||||
type: str
|
||||
changes:
|
||||
description: Map showing from -> to values for properties that was changed
|
||||
after port update.
|
||||
returned: success
|
||||
type: dict
|
||||
port:
|
||||
description: A port dictionary, subset of the dictionary keys listed below
|
||||
may be returned, depending on your cloud provider.
|
||||
returned: success
|
||||
type: complex
|
||||
contains:
|
||||
address:
|
||||
description: Physical hardware address of this network Port,
|
||||
typically the hardware MAC address.
|
||||
returned: success
|
||||
type: str
|
||||
created_at:
|
||||
description: Bare Metal port created at timestamp.
|
||||
returned: success
|
||||
type: str
|
||||
extra:
|
||||
description: A set of one or more arbitrary metadata key and value
|
||||
pairs.
|
||||
returned: success
|
||||
type: dict
|
||||
id:
|
||||
description: The UUID for the Baremetal Port resource.
|
||||
returned: success
|
||||
type: str
|
||||
internal_info:
|
||||
description: Internal metadata set and stored by the Port. This
|
||||
field is read-only.
|
||||
returned: success
|
||||
type: dict
|
||||
is_pxe_enabled:
|
||||
description: Whether PXE is enabled or disabled on the Port.
|
||||
returned: success
|
||||
type: bool
|
||||
local_link_connection:
|
||||
description: The Port binding profile. If specified, must contain
|
||||
switch_id (only a MAC address or an OpenFlow based
|
||||
datapath_id of the switch are accepted in this field
|
||||
and port_id (identifier of the physical port on the
|
||||
switch to which node's port is connected to) fields.
|
||||
switch_info is an optional string field to be used to
|
||||
store any vendor-specific information.
|
||||
returned: success
|
||||
type: dict
|
||||
location:
|
||||
description: Cloud location of this resource (cloud, project,
|
||||
region, zone)
|
||||
returned: success
|
||||
type: dict
|
||||
name:
|
||||
description: Bare Metal port name.
|
||||
returned: success
|
||||
type: str
|
||||
node_id:
|
||||
description: UUID of the Bare Metal Node this resource belongs to.
|
||||
returned: success
|
||||
type: str
|
||||
physical_network:
|
||||
description: The name of the physical network to which a port is
|
||||
connected.
|
||||
returned: success
|
||||
type: str
|
||||
port_group_id:
|
||||
description: UUID of the Portgroup this resource belongs to.
|
||||
returned: success
|
||||
type: str
|
||||
updated_at:
|
||||
description: Bare Metal port updated at timestamp.
|
||||
returned: success
|
||||
type: str
|
||||
'''
|
||||
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.ironic import (
|
||||
IronicModule,
|
||||
ironic_argument_spec,
|
||||
)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module
|
||||
)
|
||||
|
||||
_PROP_TO_ATTR_MAP = {
|
||||
'pxe_enabled': 'is_pxe_enabled',
|
||||
'address': 'address',
|
||||
'extra': 'extra',
|
||||
'local_link_connection': 'local_link_connection',
|
||||
'physical_network': 'physical_network',
|
||||
'node_uuid': 'node_id',
|
||||
'portgroup_uuid': 'port_group_id',
|
||||
'uuid': 'id',
|
||||
}
|
||||
|
||||
|
||||
def find_port(module, cloud):
|
||||
port = None
|
||||
if module.params['uuid']:
|
||||
port = cloud.baremetal.find_port(module.params['uuid'])
|
||||
elif module.params['address']:
|
||||
ports = list(cloud.baremetal.ports(address=module.params['address'],
|
||||
details=True))
|
||||
if ports and len(ports) == 1:
|
||||
port = ports[0]
|
||||
elif len(ports) > 1:
|
||||
module.fail_json(
|
||||
msg="Multiple ports with address {address} found. A uuid must "
|
||||
"be defined in order to identify the correct port"
|
||||
.format(address=module.params['address']))
|
||||
|
||||
return port
|
||||
|
||||
|
||||
def add_port(module, cloud):
|
||||
port = find_port(module, cloud)
|
||||
if port:
|
||||
update_port(module, cloud, port=port)
|
||||
|
||||
if not module.params['node'] or not module.params['address']:
|
||||
module.fail_json(
|
||||
msg="A Bare Metal node (name or uuid) and an address is required "
|
||||
"to create a port")
|
||||
|
||||
machine = cloud.get_machine(module.params['node'])
|
||||
if not machine:
|
||||
module.fail_json(
|
||||
msg="Bare Metal node {node} could not be found".format(
|
||||
node=module.params['node']))
|
||||
|
||||
module.params['node_uuid'] = machine.id
|
||||
props = {k: module.params[k] for k in _PROP_TO_ATTR_MAP.keys()
|
||||
if k in module.params}
|
||||
port = cloud.baremetal.create_port(**props)
|
||||
port_dict = port.to_dict()
|
||||
port_dict.pop('links', None)
|
||||
module.exit_json(
|
||||
changed=True,
|
||||
result="Port successfully created",
|
||||
changes=None,
|
||||
port=port_dict,
|
||||
id=port_dict['id'])
|
||||
|
||||
|
||||
def update_port(module, cloud, port=None):
|
||||
if not port:
|
||||
port = find_port(module, cloud)
|
||||
|
||||
if module.params['node']:
|
||||
machine = cloud.get_machine(module.params['node'])
|
||||
if machine:
|
||||
module.params['node_uuid'] = machine.id
|
||||
|
||||
old_props = {k: port[v] for k, v in _PROP_TO_ATTR_MAP.items()}
|
||||
new_props = {k: module.params[k] for k in _PROP_TO_ATTR_MAP.keys()
|
||||
if k in module.params and module.params[k] is not None}
|
||||
prop_diff = {k: new_props[k] for k in _PROP_TO_ATTR_MAP.keys()
|
||||
if k in new_props and old_props[k] != new_props[k]}
|
||||
|
||||
if not prop_diff:
|
||||
port_dict = port.to_dict()
|
||||
port_dict.pop('links', None)
|
||||
module.exit_json(
|
||||
changed=False,
|
||||
result="No port update required",
|
||||
changes=None,
|
||||
port=port_dict,
|
||||
id=port_dict['id'])
|
||||
|
||||
port = cloud.baremetal.update_port(port.id, **prop_diff)
|
||||
port_dict = port.to_dict()
|
||||
port_dict.pop('links', None)
|
||||
module.exit_json(
|
||||
changed=True,
|
||||
result="Port successfully updated",
|
||||
changes={k: {'to': new_props[k], 'from': old_props[k]}
|
||||
for k in prop_diff},
|
||||
port=port_dict,
|
||||
id=port_dict['id'])
|
||||
|
||||
|
||||
def remove_port(module, cloud):
|
||||
if not module.params['uuid'] and not module.params['address']:
|
||||
module.fail_json(
|
||||
msg="A uuid or an address value must be defined in order to "
|
||||
"remove a port.")
|
||||
if module.params['uuid']:
|
||||
port = cloud.baremetal.delete_port(module.params['uuid'])
|
||||
if not port:
|
||||
module.exit_json(
|
||||
changed=False,
|
||||
result="Port not found",
|
||||
changes=None,
|
||||
id=module.params['uuid'])
|
||||
else:
|
||||
port = find_port(module, cloud)
|
||||
if not port:
|
||||
module.exit_json(
|
||||
changed=False,
|
||||
result="Port not found",
|
||||
changes=None,
|
||||
id=None)
|
||||
port = cloud.baremetal.delete_port(port.id)
|
||||
|
||||
module.exit_json(
|
||||
changed=True,
|
||||
result="Port successfully removed",
|
||||
changes=None,
|
||||
id=port.id)
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = ironic_argument_spec(
|
||||
uuid=dict(required=False),
|
||||
node=dict(required=False),
|
||||
address=dict(required=False),
|
||||
portgroup=dict(required=False),
|
||||
local_link_connection=dict(required=False, type='dict'),
|
||||
is_pxe_enabled=dict(required=False, type='bool'),
|
||||
physical_network=dict(required=False),
|
||||
extra=dict(required=False, type='dict'),
|
||||
state=dict(required=False,
|
||||
default='present',
|
||||
choices=['present', 'absent'])
|
||||
)
|
||||
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = IronicModule(argument_spec, **module_kwargs)
|
||||
|
||||
module.params['pxe_enabled'] = module.params.pop('is_pxe_enabled', None)
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
if module.params['state'] == 'present':
|
||||
add_port(module, cloud)
|
||||
|
||||
if module.params['state'] == 'absent':
|
||||
remove_port(module, cloud)
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
208
plugins/modules/baremetal_port_info.py
Normal file
208
plugins/modules/baremetal_port_info.py
Normal file
@@ -0,0 +1,208 @@
|
||||
#!/usr/bin/python
|
||||
# coding: utf-8 -*-
|
||||
# Copyright (c) 2021 by Red Hat, Inc.
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
DOCUMENTATION = '''
|
||||
module: baremetal_port_info
|
||||
short_description: Retrieve information about Bare Metal ports from OpenStack
|
||||
author: OpenStack Ansible SIG
|
||||
description:
|
||||
- Retrieve information about Bare Metal ports from OpenStack.
|
||||
options:
|
||||
uuid:
|
||||
description:
|
||||
- Name or globally unique identifier (UUID) to identify the port.
|
||||
type: str
|
||||
address:
|
||||
description:
|
||||
- Physical hardware address of this network Port, typically the
|
||||
hardware MAC address.
|
||||
type: str
|
||||
node:
|
||||
description:
|
||||
- Name or globally unique identifier (UUID) to identify a Baremetal
|
||||
Node.
|
||||
type: str
|
||||
ironic_url:
|
||||
description:
|
||||
- If noauth mode is utilized, this is required to be set to the
|
||||
endpoint URL for the Ironic API. Use with "auth" and "auth_type"
|
||||
settings set to None.
|
||||
type: str
|
||||
requirements:
|
||||
- "python >= 3.6"
|
||||
- "openstacksdk"
|
||||
extends_documentation_fragment:
|
||||
- openstack.cloud.openstack
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# Gather information about all baremetal ports
|
||||
- openstack.cloud.baremetal_port_info:
|
||||
cloud: devstack
|
||||
register: result
|
||||
# Gather information about a baremetal port by address
|
||||
- openstack.cloud.baremetal_port_info:
|
||||
cloud: devstack
|
||||
address: fa:16:3e:aa:aa:aa
|
||||
register: result
|
||||
# Gather information about a baremetal port by address
|
||||
- openstack.cloud.baremetal_port_info:
|
||||
cloud: devstack
|
||||
uuid: a2b6bd99-77b9-43f0-9ddc-826568e68dec
|
||||
register: result
|
||||
# Gather information about a baremetal ports associated with a baremetal node
|
||||
- openstack.cloud.baremetal_port_info:
|
||||
cloud: devstack
|
||||
node: bm-0
|
||||
register: result
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
baremetal_ports:
|
||||
description: Bare Metal port list. A subset of the dictionary keys
|
||||
listed below may be returned, depending on your cloud
|
||||
provider.
|
||||
returned: always, but can be null
|
||||
type: list
|
||||
elements: dict
|
||||
contains:
|
||||
address:
|
||||
description: Physical hardware address of this network Port,
|
||||
typically the hardware MAC address.
|
||||
returned: success
|
||||
type: str
|
||||
created_at:
|
||||
description: Bare Metal port created at timestamp.
|
||||
returned: success
|
||||
type: str
|
||||
extra:
|
||||
description: A set of one or more arbitrary metadata key and
|
||||
value pairs.
|
||||
returned: success
|
||||
type: dict
|
||||
id:
|
||||
description: The UUID for the Baremetal Port resource.
|
||||
returned: success
|
||||
type: str
|
||||
internal_info:
|
||||
description: Internal metadata set and stored by the Port. This
|
||||
field is read-only.
|
||||
returned: success
|
||||
type: dict
|
||||
is_pxe_enabled:
|
||||
description: Whether PXE is enabled or disabled on the Port.
|
||||
returned: success
|
||||
type: bool
|
||||
local_link_connection:
|
||||
description: The Port binding profile.
|
||||
returned: success
|
||||
type: dict
|
||||
contains:
|
||||
switch_id:
|
||||
description: A MAC address or an OpenFlow based datapath_id of
|
||||
the switch.
|
||||
type: str
|
||||
port_id:
|
||||
description: Identifier of the physical port on the switch to
|
||||
which node's port is connected to.
|
||||
type: str
|
||||
switch_info:
|
||||
description: An optional string field to be used to store any
|
||||
vendor-specific information.
|
||||
type: str
|
||||
location:
|
||||
description: Cloud location of this resource (cloud, project,
|
||||
region, zone)
|
||||
returned: success
|
||||
type: dict
|
||||
name:
|
||||
description: Bare Metal port name.
|
||||
returned: success
|
||||
type: str
|
||||
node_id:
|
||||
description: UUID of the Bare Metal Node this resource belongs to.
|
||||
returned: success
|
||||
type: str
|
||||
physical_network:
|
||||
description: The name of the physical network to which a port is
|
||||
connected.
|
||||
returned: success
|
||||
type: str
|
||||
port_group_id:
|
||||
description: UUID of the Portgroup this resource belongs to.
|
||||
returned: success
|
||||
type: str
|
||||
updated_at:
|
||||
description: Bare Metal port updated at timestamp.
|
||||
returned: success
|
||||
type: str
|
||||
'''
|
||||
|
||||
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.ironic import (
|
||||
IronicModule,
|
||||
ironic_argument_spec,
|
||||
)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = ironic_argument_spec(
|
||||
uuid=dict(required=False),
|
||||
address=dict(required=False),
|
||||
node=dict(required=False),
|
||||
)
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module_kwargs['supports_check_mode'] = True
|
||||
module = IronicModule(argument_spec, **module_kwargs)
|
||||
|
||||
ports = list()
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
if module.params['uuid']:
|
||||
port = cloud.baremetal.find_port(module.params['uuid'])
|
||||
if not port:
|
||||
module.fail_json(
|
||||
msg='Baremetal port with uuid {uuid} was not found'
|
||||
.format(uuid=module.params['uuid']))
|
||||
ports.append(port)
|
||||
|
||||
elif module.params['address']:
|
||||
ports = list(
|
||||
cloud.baremetal.ports(address=module.params['address'],
|
||||
details=True))
|
||||
if not ports:
|
||||
module.fail_json(
|
||||
msg='Baremetal port with address {address} was not found'
|
||||
.format(address=module.params['address']))
|
||||
|
||||
elif module.params['node']:
|
||||
machine = cloud.get_machine(module.params['node'])
|
||||
if not machine:
|
||||
module.fail_json(
|
||||
msg='Baremetal node {node} was not found'
|
||||
.format(node=module.params['node']))
|
||||
ports = list(
|
||||
cloud.baremetal.ports(node_uuid=machine.uuid, details=True))
|
||||
|
||||
else:
|
||||
ports = list(cloud.baremetal.ports(details=True))
|
||||
|
||||
# Convert ports to dictionaries and cleanup properties
|
||||
ports = [port.to_dict() for port in ports]
|
||||
for port in ports:
|
||||
# links are not useful
|
||||
port.pop('links', None)
|
||||
|
||||
module.exit_json(changed=False, baremetal_ports=ports)
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user