mirror of
https://opendev.org/openstack/ansible-collections-openstack.git
synced 2026-03-27 14:03:03 +00:00
Compare commits
403 Commits
1.1.0
...
stable/1.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e0458dd1a6 | ||
|
|
f448ac258d | ||
|
|
e4be201f20 | ||
|
|
bc16f70e1d | ||
|
|
dec8ecda5a | ||
|
|
dd383c010c | ||
|
|
acd0f01443 | ||
|
|
a4260040c6 | ||
|
|
ef5b217411 | ||
|
|
6592363c7c | ||
|
|
922032cb9f | ||
|
|
a11943d9b1 | ||
|
|
84160f6f78 | ||
|
|
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 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,7 +1,6 @@
|
||||
.tox
|
||||
build_artifact
|
||||
ansible_collections
|
||||
galaxy.yml
|
||||
FILES.json
|
||||
MANIFEST.json
|
||||
importer_result.json
|
||||
|
||||
647
.zuul.yaml
647
.zuul.yaml
@@ -1,338 +1,499 @@
|
||||
# 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/.*
|
||||
- .zuul.yaml
|
||||
vars:
|
||||
zuul_work_dir: src/opendev.org/openstack/ansible-collections-openstack
|
||||
tox_envlist: ansible-2.9
|
||||
tox_envlist: ansible_latest
|
||||
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-magnum-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 Magnum plugin enabled
|
||||
# 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/magnum
|
||||
- openstack/python-magnumclient
|
||||
files:
|
||||
- ^ci/roles/coe_cluster/.*$
|
||||
- ^plugins/modules/coe_cluster.py
|
||||
- ^plugins/modules/coe_cluster_template.py
|
||||
timeout: 10800
|
||||
vars:
|
||||
devstack_localrc:
|
||||
# NOTE: extend default glance limit from 1GB
|
||||
GLANCE_LIMIT_IMAGE_SIZE_TOTAL: 5000
|
||||
devstack_plugins:
|
||||
magnum: https://opendev.org/openstack/magnum
|
||||
devstack_services:
|
||||
magnum-api: true
|
||||
magnum-cond: true
|
||||
# Disable swift and dependent c-bak service to support upload of .qcow2.xz image in the gate
|
||||
s-account: false
|
||||
s-container: false
|
||||
s-object: false
|
||||
s-proxy: false
|
||||
c-bak: false
|
||||
tox_extra_args: -vv --skip-missing-interpreters=false -- coe_cluster coe_cluster_template
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-magnum
|
||||
parent: ansible-collections-openstack-functional-devstack-magnum-base
|
||||
branches: master
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
with Magnum plugin enabled, using master of openstacksdk and latest
|
||||
ansible release. Run it only on coe_cluster{,_template} changes.
|
||||
|
||||
- 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
|
||||
# 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
|
||||
|
||||
- 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_envlist: ansible-2.9
|
||||
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-2.10
|
||||
parent: ansible-collections-openstack-functional-devstack
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using master of openstacksdk and stable 2.10 branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.10
|
||||
vars:
|
||||
tox_envlist: ansible
|
||||
|
||||
# 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
|
||||
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
|
||||
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 stable/yoga branch instead of non-existing stable/1.0.0 branch
|
||||
name: openstack/devstack
|
||||
override-checkout: stable/yoga
|
||||
- name: openstack/openstacksdk
|
||||
# Yoga has the latest SDK release of the 0.*.* series atm
|
||||
override-checkout: stable/yoga
|
||||
vars:
|
||||
tox_envlist: ansible-2.9
|
||||
tox_envlist: ansible_2_9
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-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 master of openstacksdk and devel branch of ansible
|
||||
voting: false
|
||||
using 0.*.* releases of openstacksdk and stable 2.12 branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: devel
|
||||
override-checkout: stable-2.11
|
||||
- # Choose parent devstack job from stable/yoga branch instead of non-existing stable/1.0.0 branch
|
||||
name: openstack/devstack
|
||||
override-checkout: stable/yoga
|
||||
- name: openstack/openstacksdk
|
||||
# Yoga has the latest SDK release of the 0.*.* series atm
|
||||
override-checkout: stable/yoga
|
||||
vars:
|
||||
tox_envlist: ansible
|
||||
tox_envlist: ansible_2_11
|
||||
|
||||
# Pip installation job
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-pip
|
||||
parent: ansible-collections-openstack-functional-devstack
|
||||
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 master of openstacksdk with latest ansible release.
|
||||
Ansible collection is built using PIP.
|
||||
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 stable/yoga branch instead of non-existing stable/1.0.0 branch
|
||||
name: openstack/devstack
|
||||
override-checkout: stable/yoga
|
||||
- name: openstack/openstacksdk
|
||||
# Yoga has the latest SDK release of the 0.*.* series atm
|
||||
override-checkout: stable/yoga
|
||||
vars:
|
||||
tox_envlist: ansible-pip
|
||||
tox_envlist: ansible_2_12
|
||||
|
||||
# Stable branches tests
|
||||
|
||||
# Stable branches
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ussuri-ansible-2.9
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
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/designate
|
||||
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/designate
|
||||
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/designate
|
||||
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 brach of openstacksdk and stable 2.9 branch of ansible
|
||||
voting: true
|
||||
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.9
|
||||
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/designate
|
||||
override-checkout: stable/ussuri
|
||||
- name: openstack/openstacksdk
|
||||
override-branch: ussuri
|
||||
- name: openstack/devstack
|
||||
override-checkout: ussuri
|
||||
override-checkout: stable/ussuri
|
||||
vars:
|
||||
tox_envlist: ansible-2.9
|
||||
tox_envlist: ansible_2_11
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-train-ansible-2.9
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
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 stable 2.9 branch of ansible
|
||||
voting: true
|
||||
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.9
|
||||
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/designate
|
||||
override-checkout: train-eol
|
||||
- name: openstack/openstacksdk
|
||||
override-branch: train
|
||||
- name: openstack/devstack
|
||||
override-checkout: train
|
||||
override-checkout: stable/train
|
||||
vars:
|
||||
tox_envlist: ansible-2.9
|
||||
|
||||
- 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
|
||||
vars:
|
||||
tox_envlist: ansible-2.9
|
||||
|
||||
- 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
|
||||
vars:
|
||||
tox_envlist: ansible-2.9
|
||||
|
||||
- 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:
|
||||
tox_envlist: ansible-2.9
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-queens-ansible-2.10
|
||||
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.10 branch of ansible
|
||||
voting: true
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.10
|
||||
- name: openstack/openstacksdk
|
||||
override-branch: master
|
||||
- name: openstack/devstack
|
||||
override-checkout: queens
|
||||
vars:
|
||||
tox_envlist: ansible
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-queens-ansible-devel
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
description: |
|
||||
Run openstack collections functional tests against a queens devstack
|
||||
using master brach of openstacksdk and devel branch of ansible
|
||||
voting: true
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: devel
|
||||
- name: openstack/openstacksdk
|
||||
override-branch: master
|
||||
- name: openstack/devstack
|
||||
override-checkout: queens
|
||||
vars:
|
||||
tox_envlist: ansible
|
||||
|
||||
tox_envlist: ansible_2_11
|
||||
|
||||
# Linters
|
||||
- job:
|
||||
name: openstack-tox-linters-ansible-devel
|
||||
name: openstack-tox-linters-ansible
|
||||
parent: openstack-tox-linters
|
||||
description: |
|
||||
Run openstack collections linter tests using the devel branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: devel
|
||||
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_latest
|
||||
tox_install_siblings: true
|
||||
|
||||
- job:
|
||||
name: openstack-tox-linters-ansible-devel
|
||||
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
|
||||
|
||||
- job:
|
||||
name: openstack-tox-linters-ansible-2.10
|
||||
parent: openstack-tox-linters
|
||||
description: |
|
||||
Run openstack collections linter tests using the 2.10 branch of ansible
|
||||
voting: true
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.10
|
||||
|
||||
- job:
|
||||
name: openstack-tox-linters-ansible-2.9
|
||||
parent: openstack-tox-linters
|
||||
description: |
|
||||
Run openstack collections linter tests using the 2.9 branch of ansible
|
||||
voting: true
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.9
|
||||
vars:
|
||||
tox_envlist: linters-2.9
|
||||
python_version: '3.10'
|
||||
bindep_profile: test py310
|
||||
|
||||
- job:
|
||||
name: openstack-tox-linters-ansible-2.12
|
||||
parent: openstack-tox-linters-ansible
|
||||
nodeset: ubuntu-focal
|
||||
description: |
|
||||
Run openstack collections linter tests using the 2.12 branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.12
|
||||
vars:
|
||||
ensure_tox_version: '<4'
|
||||
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-bionic
|
||||
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-bionic
|
||||
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
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-release
|
||||
parent: base
|
||||
run: ci/publish/publish_collection.yml
|
||||
|
||||
- project:
|
||||
check:
|
||||
jobs:
|
||||
- tox-pep8
|
||||
- openstack-tox-linters-ansible-devel
|
||||
- openstack-tox-linters-ansible-2.10
|
||||
- openstack-tox-linters-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack:
|
||||
dependencies: &deps_unit_lint
|
||||
- tox-pep8
|
||||
- openstack-tox-linters-ansible-2.9
|
||||
irrelevant-files: &ignore_files
|
||||
- changelogs/.*
|
||||
- COPYING
|
||||
- docs/.*
|
||||
- .*\.md
|
||||
- .*\.rst
|
||||
- tools/run-ansible-sanity.sh
|
||||
- tests/sanity/.*
|
||||
- contrib/.*
|
||||
|
||||
- ansible-collections-openstack-functional-devstack:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-releases:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.9:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.10:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-ansible-devel:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-ansible-pip:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-ussuri-ansible-2.9:
|
||||
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-2.9:
|
||||
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:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
|
||||
- bifrost-collections-src:
|
||||
voting: false
|
||||
- bifrost-keystone-collections-src:
|
||||
voting: false
|
||||
dependencies:
|
||||
- tox-pep8
|
||||
|
||||
gate:
|
||||
jobs:
|
||||
- tox-pep8
|
||||
- openstack-tox-linters-ansible-2.10
|
||||
- openstack-tox-linters-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack
|
||||
- ansible-collections-openstack-functional-devstack-releases
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.10
|
||||
- ansible-collections-openstack-functional-devstack-ansible-pip
|
||||
- ansible-collections-openstack-functional-devstack-ussuri-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
|
||||
|
||||
periodic:
|
||||
jobs:
|
||||
- openstack-tox-linters-ansible-devel
|
||||
- openstack-tox-linters-ansible-2.10
|
||||
- openstack-tox-linters-ansible-2.9
|
||||
- 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.10
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
- ansible-collections-openstack-functional-devstack-ansible-pip
|
||||
- ansible-collections-openstack-functional-devstack-ussuri-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-queens-ansible-2.10
|
||||
- ansible-collections-openstack-functional-devstack-queens-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-magnum
|
||||
- ansible-collections-openstack-functional-devstack-octavia
|
||||
|
||||
experimental:
|
||||
jobs:
|
||||
- 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
|
||||
|
||||
450
CHANGELOG.rst
450
CHANGELOG.rst
@@ -5,6 +5,450 @@ 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
|
||||
======
|
||||
|
||||
@@ -24,12 +468,6 @@ Minor Changes
|
||||
- inventory_openstack - Add openstack logger and Ansible display utility
|
||||
- loadbalancer - Add support for setting the Flavor when creating a load balancer
|
||||
|
||||
Deprecated Features
|
||||
-------------------
|
||||
|
||||
- foo - The bar option has been deprecated. Use the username option instead.
|
||||
- send_request - The quic option has been deprecated. Use the protocol option instead.
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
.. _contributing:
|
||||
|
||||
=============================================
|
||||
Contributing to ansible-collections-openstack
|
||||
=============================================
|
||||
|
||||
If you're interested in contributing to the ansible-collections-openstack project,
|
||||
the following will help get you started.
|
||||
|
||||
Developer Workflow
|
||||
------------------
|
||||
|
||||
OpenStack uses OpenDev for it's development, and patches are submitted to
|
||||
`OpenDev Gerrit`_. Please read `DeveloperWorkflow`_ before sending your
|
||||
first patch for review.
|
||||
|
||||
Pull requests submitted through GitHub will be ignored.
|
||||
|
||||
.. seealso::
|
||||
|
||||
* https://wiki.openstack.org/wiki/How_To_Contribute
|
||||
* https://wiki.openstack.org/wiki/CLA
|
||||
|
||||
.. _OpenDev Gerrit: https://review.opendev.org/
|
||||
.. _DeveloperWorkflow: https://docs.openstack.org/infra/manual/developers.html#development-workflow
|
||||
|
||||
Project Hosting Details
|
||||
-----------------------
|
||||
|
||||
Bug tracker
|
||||
https://storyboard.openstack.org/#!/project/openstack/ansible-collections-openstack
|
||||
|
||||
Mailing list (prefix subjects with ``[ansible]`` for faster responses)
|
||||
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-discuss
|
||||
|
||||
Code Hosting
|
||||
https://opendev.org/openstack/ansible-collections-openstack
|
||||
|
||||
Code Review
|
||||
https://review.opendev.org/#/q/status:open+project:openstack/ansible-collections-openstack,n,z
|
||||
154
README.md
154
README.md
@@ -1,58 +1,75 @@
|
||||
[](http://zuul.opendev.org/t/openstack/builds?project=openstack%2Fansible-collections-openstack#)
|
||||
[](
|
||||
http://zuul.opendev.org/t/openstack/builds?project=openstack%2Fansible-collections-openstack)
|
||||
|
||||
# Ansible Collection: openstack.cloud
|
||||
# Ansible OpenStack Collection
|
||||
|
||||
Ansible OpenStack collection aka `openstack.cloud` provides Ansible modules and Ansible plugins for managing OpenStack
|
||||
clouds. It is supported and maintained by the OpenStack community.
|
||||
|
||||
This repo hosts the `openstack.cloud` Ansible Collection.
|
||||
## Branches and Non Backward Compatibility ⚠️
|
||||
|
||||
The collection includes the Openstack modules and plugins supported by Openstack community to help the management of Openstack infrastructure.
|
||||
Our codebase has been split into two separate release series, `2.x.x` and `1.x.x`:
|
||||
|
||||
## Installation and Usage
|
||||
* `2.x.x` releases of Ansible OpenStack collection are compatible with [OpenStack SDK][openstacksdk] `1.x.x` and its
|
||||
release candidates `0.99.0` and later *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][openstacksdk] `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.
|
||||
* `2.x.x` releases of Ansible OpenStack collection are not backward compatible to `1.x.x` releases ⚠️
|
||||
|
||||
### Installing dependencies
|
||||
For rationale and details please read our [branching docs](docs/branching.md). 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!
|
||||
|
||||
For using Openstack Cloud collection firstly need to install `ansible` and `openstacksdk` Python modules on Ansible controller.
|
||||
For example with pip:
|
||||
[openstacksdk]: https://opendev.org/openstack/openstacksdk
|
||||
|
||||
```bash
|
||||
pip install ansible openstacksdk
|
||||
## Installation
|
||||
|
||||
For using this collection, first you have to install both Python packages `ansible` and `openstacksdk` on your Ansible
|
||||
controller:
|
||||
|
||||
```sh
|
||||
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 not standard Python interpreter on the target host.
|
||||
Using Python verison 3 is highly recommended for OpenstackSDK and strongly required from OpenstackSDK version 0.39.0.
|
||||
[OpenStack SDK][openstacksdk] has to be available on the Ansible host running the OpenStack modules. Depending on the
|
||||
Ansible playbook and roles you use, this host is not necessarily the Ansible controller. Sometimes Ansible might invoke
|
||||
a non-standard Python interpreter on the target Ansible host. Using Python 3.6 is required for modules in this
|
||||
collection.
|
||||
|
||||
---
|
||||
Always use the last stable version of [OpenStack SDK][openstacksdk] if possible, also when running against older
|
||||
OpenStack deployments. OpenStack SDK is backward compatible to older OpenStack deployments, so its safe to run last
|
||||
version of the SDK against older OpenStack clouds. The installed version of the OpenStack SDK does not have to match
|
||||
your OpenStack cloud, but it has to match the release series of this collection which you are using. For notes about
|
||||
our release series and branches please read the introduction above.
|
||||
|
||||
#### NOTE
|
||||
Before using this collection, you have to install it with `ansible-galaxy`:
|
||||
|
||||
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.
|
||||
```sh
|
||||
ansible-galaxy collection install openstack.cloud
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 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:
|
||||
|
||||
```yaml
|
||||
collections:
|
||||
- name: openstack.cloud
|
||||
```
|
||||
|
||||
### Playbooks
|
||||
And then install it with:
|
||||
|
||||
To use a module from Openstack Cloud collection, please reference the full namespace, collection name, and modules name that you want to use:
|
||||
```sh
|
||||
ansible-galaxy collection install -r requirements.yml
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
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
|
||||
---
|
||||
- name: Using Openstack Cloud collection
|
||||
- name: Using OpenStack Cloud collection
|
||||
hosts: localhost
|
||||
tasks:
|
||||
- openstack.cloud.server:
|
||||
@@ -66,11 +83,11 @@ 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
|
||||
---
|
||||
- name: Using Openstack Cloud collection
|
||||
- name: Using the Ansible OpenStack Collection
|
||||
hosts: localhost
|
||||
collections:
|
||||
- openstack.cloud
|
||||
@@ -83,41 +100,64 @@ Or you can add full namepsace and collecton name in the `collections` element:
|
||||
device: /dev/vdb
|
||||
```
|
||||
|
||||
[Ansible module defaults][ansible-module-defaults] are supported as well:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- module_defaults:
|
||||
group/openstack.cloud.openstack:
|
||||
cloud: devstack-admin
|
||||
#
|
||||
#
|
||||
# Listing modules individually is required for
|
||||
# backward compatibility with Ansible 2.9 only
|
||||
openstack.cloud.compute_flavor_info:
|
||||
cloud: devstack-admin
|
||||
openstack.cloud.server_info:
|
||||
cloud: devstack-admin
|
||||
block:
|
||||
- name: List compute flavors
|
||||
openstack.cloud.compute_flavor_info:
|
||||
|
||||
- name: List servers
|
||||
openstack.cloud.server_info:
|
||||
```
|
||||
|
||||
[ansible-module-defaults]: https://docs.ansible.com/ansible/latest/user_guide/playbooks_module_defaults.html
|
||||
|
||||
## Documentation
|
||||
|
||||
See collection docs at Ansible's main page:
|
||||
|
||||
* [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)
|
||||
Thank you for your interest in our Ansible OpenStack collection ☺️
|
||||
|
||||
There are many ways in which you can participate in the project, for example:
|
||||
|
||||
- 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
|
||||
- [Report and verify bugs and help with solving issues](
|
||||
https://storyboard.openstack.org/#!/project/openstack/ansible-collections-openstack).
|
||||
- [Submit and review patches](
|
||||
https://review.opendev.org/#/q/project:openstack/ansible-collections-openstack).
|
||||
- Follow OpenStack's [How To Contribute](https://wiki.openstack.org/wiki/How_To_Contribute) guide.
|
||||
|
||||
We work with [OpenDev Gerrit](https://review.opendev.org/), pull requests submitted through GitHub will be ignored.
|
||||
|
||||
## Testing and Development
|
||||
|
||||
If you want to develop new content for this collection or improve what is already here, the easiest way to work on the collection is to clone it into one of the configured [`COLLECTIONS_PATHS`](https://docs.ansible.com/ansible/latest/reference_appendices/config.html#collections-paths), and work on it there.
|
||||
|
||||
### Testing with `ansible-test`
|
||||
|
||||
We use `ansible-test` for sanity:
|
||||
|
||||
```bash
|
||||
tox -e linters
|
||||
```
|
||||
|
||||
## More Information
|
||||
|
||||
TBD
|
||||
Please read our [Contributions and Development Guide](docs/contributing.md) (⚠️) and our [Review Guide](
|
||||
docs/reviewing.md) (⚠️) before sending your first patch. Pull requests submitted through GitHub will be ignored.
|
||||
|
||||
## 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.
|
||||
We have a Special Interest Group for the Ansible OpenStack collection. Join us in `#openstack-ansible-sig` on
|
||||
[OFTC IRC](https://www.oftc.net/) and ping Artem Goncharov <artem.goncharov@gmail.com> (gtema), Jakob Meng
|
||||
<mail@jakobmeng.de> (jm1) or Sagi Shnaidman <sshnaidm@redhat.com> (sshnaidm) 🍪
|
||||
|
||||
## License
|
||||
|
||||
GNU General Public License v3.0 or later
|
||||
|
||||
See [LICENCE](https://opendev.org/openstack/ansible-collections-openstack/src/branch/master/COPYING) to see the full text.
|
||||
See [LICENCE](COPYING) to see the full text.
|
||||
|
||||
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]
|
||||
@@ -1,72 +1,406 @@
|
||||
ancestor: null
|
||||
releases:
|
||||
1.1.0:
|
||||
release_date: '2020-08-17'
|
||||
changes:
|
||||
release_summary: Starting redesign modules and bugfixes.
|
||||
minor_changes:
|
||||
- Added changelog.
|
||||
- A basic module subclass was introduced and a few modules moved to inherit from it.
|
||||
- Added pip installation option for collection.
|
||||
- Added template for generation of artibtrary module.
|
||||
- Added more useful information from exception
|
||||
- inventory_openstack - Add openstack logger and Ansible display utility
|
||||
- loadbalancer - Add support for setting the Flavor when creating a load balancer
|
||||
- baremetal modules - Do not require ironic_url if cloud or auth.endpoint is provided
|
||||
deprecated_features:
|
||||
- foo - The bar option has been deprecated. Use the username option instead.
|
||||
- send_request - The quic option has been deprecated. Use the protocol option instead.
|
||||
bugfixes:
|
||||
- security_group_rule - Don't pass tenant_id for remote group
|
||||
- Fix non existing attribuites in SDK exception
|
||||
modules:
|
||||
- name: volume_info
|
||||
description: Retrieve information about Openstack volumes.
|
||||
namespace: ''
|
||||
1.0.1:
|
||||
release_date: '2020-05-22'
|
||||
changes:
|
||||
release_summary: Bugfix for server_info
|
||||
bugfixes:
|
||||
- server_info - Fix broken server_info module and add tests
|
||||
1.0.0:
|
||||
release_date: '2020-05-19'
|
||||
changes:
|
||||
release_summary: Initial release of collection.
|
||||
minor_changes:
|
||||
- Renaming all modules and removing "os" prefix from names.
|
||||
- server_action - pass imageRef to rebuild
|
||||
- subnet - Updated allocation pool checks
|
||||
- project - Add properties for os_project
|
||||
- config - Update os_client_config to use openstacksdk
|
||||
- host_aggregate - Add support for not 'purging' missing hosts
|
||||
- baremetal_node_action - Support json type for the ironic_node config_drive parameter
|
||||
bugfixes:
|
||||
- federation_mapping - Fixup some minor nits found in followup reviews
|
||||
- coe_cluster - Retrive id/uuid correctly
|
||||
- baremetal_node - Correct parameter name
|
||||
- network - Bump minimum openstacksdk version when using os_network/dns_domain
|
||||
- inventory_openstack - Fix constructed compose
|
||||
- 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
|
||||
- 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:
|
||||
- name: keystone_federation_protocol_info
|
||||
description: Add support for getting information about Keystone federation Protocols
|
||||
namespace: ''
|
||||
- name: keystone_federation_protocol
|
||||
description: Add support for Keystone federation Protocols
|
||||
namespace: ''
|
||||
- name: federation_idp_info
|
||||
description: Add support for fetching the information about federation IDPs
|
||||
namespace: ''
|
||||
- name: federation_idp
|
||||
description: Add support for Keystone Identity Providers
|
||||
namespace: ''
|
||||
- name: federation_mapping_info
|
||||
description: Add support for fetching the information about Keystone mappings
|
||||
namespace: ''
|
||||
- name: federation_mapping
|
||||
description: Add support for Keystone mappings
|
||||
namespace: ''
|
||||
- name: routers_info
|
||||
description: Retrieve information about one or more OpenStack routers.
|
||||
namespace: ''
|
||||
- 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'
|
||||
|
||||
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 }}"
|
||||
5
ci/requirements.yml
Normal file
5
ci/requirements.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
collections:
|
||||
- ansible.posix
|
||||
- ansible.utils
|
||||
- community.general
|
||||
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
|
||||
18
ci/roles/coe_cluster/defaults/main.yml
Normal file
18
ci/roles/coe_cluster/defaults/main.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
expected_fields:
|
||||
# Magnum might return more fields according to its documentation [0] but
|
||||
# openstacksdk normalizes coe cluster resources, moving most fields from
|
||||
# top level into a 'properties' field [1].
|
||||
# [0] https://docs.openstack.org/api-ref/container-infrastructure-management/#create-new-cluster
|
||||
# [1] https://opendev.org/openstack/openstacksdk/src/commit/d57c1fcab3b6cbe806cbae735fefa4983b200ab2/openstack/cloud/_normalize.py#L484
|
||||
- cluster_template_id
|
||||
- create_timeout
|
||||
- id
|
||||
- keypair
|
||||
- location
|
||||
- master_count
|
||||
- name
|
||||
- node_count
|
||||
- properties
|
||||
- stack_id
|
||||
- status
|
||||
- uuid
|
||||
181
ci/roles/coe_cluster/tasks/main.yml
Normal file
181
ci/roles/coe_cluster/tasks/main.yml
Normal file
@@ -0,0 +1,181 @@
|
||||
---
|
||||
- name: Create keypair
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_keypair
|
||||
state: present
|
||||
register: keypair
|
||||
|
||||
- name: List all images
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: images
|
||||
|
||||
- name: Identify Fedora CoreOS image id
|
||||
set_fact:
|
||||
image_id: "{{ images.images|community.general.json_query(query)|first }}"
|
||||
vars:
|
||||
query: "[?starts_with(name, 'fedora-coreos')].id"
|
||||
|
||||
- name: Create external network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
external: true
|
||||
name: ansible_external_network
|
||||
state: present
|
||||
register: external_network
|
||||
|
||||
- name: Create external subnet
|
||||
openstack.cloud.subnet:
|
||||
cidr: 10.6.6.0/24
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_external_subnet
|
||||
network_name: ansible_external_network
|
||||
state: present
|
||||
|
||||
- name: Create internal network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_internal_network
|
||||
external: false
|
||||
|
||||
- name: Create internal subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
network_name: ansible_internal_network
|
||||
name: ansible_internal_subnet
|
||||
cidr: 10.7.7.0/24
|
||||
|
||||
- name: Create router
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
external_fixed_ips:
|
||||
- subnet: ansible_external_subnet
|
||||
ip: 10.6.6.10
|
||||
interfaces:
|
||||
- net: ansible_internal_network
|
||||
subnet: ansible_internal_subnet
|
||||
portip: 10.7.7.1
|
||||
name: ansible_router
|
||||
network: ansible_external_network
|
||||
state: present
|
||||
|
||||
- name: Create Kubernetes cluster template
|
||||
openstack.cloud.coe_cluster_template:
|
||||
cloud: "{{ cloud }}"
|
||||
coe: kubernetes
|
||||
external_network_id: '{{ external_network.network.id }}'
|
||||
fixed_network: ansible_internal_network
|
||||
fixed_subnet: ansible_internal_subnet
|
||||
floating_ip_enabled: true
|
||||
image_id: '{{ image_id }}'
|
||||
keypair_id: '{{ keypair.keypair.id }}'
|
||||
name: k8s
|
||||
state: present
|
||||
register: coe_cluster_template
|
||||
|
||||
- name: Create Kubernetes cluster
|
||||
openstack.cloud.coe_cluster:
|
||||
cloud: "{{ cloud }}"
|
||||
cluster_template_id: "{{ coe_cluster_template.cluster_template.uuid }}"
|
||||
keypair: ansible_keypair
|
||||
name: k8s
|
||||
state: present
|
||||
# cluster creation takes longer than max tenant timeout of 10800
|
||||
wait: false
|
||||
register: coe_cluster
|
||||
|
||||
- name: Assert return values of coe_cluster module
|
||||
assert:
|
||||
that:
|
||||
# openstack.cloud.coe_cluster will only return 'id' on cluster creation when wait is false
|
||||
- "['id']|difference(coe_cluster.cluster.keys())|length == 0"
|
||||
|
||||
- name: Pause for 1 minutes to allow Magnum to create the Kubernetes cluster
|
||||
ansible.builtin.pause:
|
||||
minutes: 1
|
||||
|
||||
- name: Create Kubernetes cluster again
|
||||
openstack.cloud.coe_cluster:
|
||||
cloud: "{{ cloud }}"
|
||||
cluster_template_id: "{{ coe_cluster_template.cluster_template.uuid }}"
|
||||
keypair: ansible_keypair
|
||||
name: k8s
|
||||
state: present
|
||||
# cluster creation takes longer than max tenant timeout of 10800
|
||||
wait: false
|
||||
register: coe_cluster
|
||||
|
||||
- name: Assert return values of coe_cluster module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(coe_cluster.cluster.keys())|length == 0
|
||||
|
||||
- name: Delete Kubernetes cluster
|
||||
openstack.cloud.coe_cluster:
|
||||
cloud: "{{ cloud }}"
|
||||
name: k8s
|
||||
state: absent
|
||||
register: coe_cluster
|
||||
|
||||
- name: Assert return values of coe_cluster module
|
||||
assert:
|
||||
that:
|
||||
- coe_cluster is changed
|
||||
|
||||
- name: Delete Kubernetes cluster again
|
||||
openstack.cloud.coe_cluster:
|
||||
cloud: "{{ cloud }}"
|
||||
name: k8s
|
||||
state: absent
|
||||
register: coe_cluster
|
||||
|
||||
- name: Assert return values of coe_cluster module
|
||||
assert:
|
||||
that:
|
||||
- coe_cluster is not changed
|
||||
|
||||
- name: Delete Kubernetes cluster template
|
||||
openstack.cloud.coe_cluster_template:
|
||||
cloud: "{{ cloud }}"
|
||||
name: k8s
|
||||
state: absent
|
||||
|
||||
- name: Delete router
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_router
|
||||
state: absent
|
||||
|
||||
- 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_network
|
||||
|
||||
- name: Delete external subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_external_subnet
|
||||
state: absent
|
||||
|
||||
- name: Delete external network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_external_network
|
||||
state: absent
|
||||
|
||||
- name: Delete keypair
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_keypair
|
||||
state: absent
|
||||
40
ci/roles/coe_cluster_template/defaults/main.yml
Normal file
40
ci/roles/coe_cluster_template/defaults/main.yml
Normal file
@@ -0,0 +1,40 @@
|
||||
expected_fields:
|
||||
# Magnum might return more fields according to its documentation [0] but
|
||||
# openstacksdk normalizes coe cluster template resources, moving most
|
||||
# fields from top level into a 'properties' field [1].
|
||||
# [0] https://docs.openstack.org/api-ref/container-infrastructure-management/#create-new-cluster
|
||||
# [1] https://opendev.org/openstack/openstacksdk/src/commit/d57c1fcab3b6cbe806cbae735fefa4983b200ab2/openstack/cloud/_normalize.py#L522
|
||||
- apiserver_port
|
||||
- cluster_distro
|
||||
- coe
|
||||
- created_at
|
||||
- dns_nameserver
|
||||
- docker_volume_size
|
||||
- external_network_id
|
||||
- fixed_network
|
||||
- fixed_subnet
|
||||
- flavor_id
|
||||
- floating_ip_enabled
|
||||
- http_proxy
|
||||
- https_proxy
|
||||
- id
|
||||
- image_id
|
||||
- insecure_registry
|
||||
- is_public
|
||||
- is_registry_enabled
|
||||
- is_tls_disabled
|
||||
- keypair_id
|
||||
- labels
|
||||
- location
|
||||
- master_flavor_id
|
||||
- name
|
||||
- network_driver
|
||||
- no_proxy
|
||||
- properties
|
||||
- public
|
||||
- registry_enabled
|
||||
- server_type
|
||||
- tls_disabled
|
||||
- updated_at
|
||||
- uuid
|
||||
- volume_driver
|
||||
81
ci/roles/coe_cluster_template/tasks/main.yml
Normal file
81
ci/roles/coe_cluster_template/tasks/main.yml
Normal file
@@ -0,0 +1,81 @@
|
||||
---
|
||||
- name: Create keypair
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_keypair
|
||||
state: present
|
||||
register: keypair
|
||||
|
||||
- name: List all images
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: images
|
||||
|
||||
- name: Identify Fedora CoreOS image id
|
||||
set_fact:
|
||||
image_id: "{{ images.images|community.general.json_query(query)|first }}"
|
||||
vars:
|
||||
query: "[?starts_with(name, 'fedora-coreos')].id"
|
||||
|
||||
- name: Create Kubernetes cluster template
|
||||
openstack.cloud.coe_cluster_template:
|
||||
cloud: "{{ cloud }}"
|
||||
coe: kubernetes
|
||||
floating_ip_enabled: false
|
||||
image_id: '{{ image_id }}'
|
||||
keypair_id: '{{ keypair.keypair.id }}'
|
||||
name: k8s
|
||||
state: present
|
||||
register: coe_cluster_template
|
||||
|
||||
- name: Assert return values of coe_cluster_template module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(coe_cluster_template.cluster_template.keys())|length == 0
|
||||
|
||||
- name: Create Kubernetes cluster template again
|
||||
openstack.cloud.coe_cluster_template:
|
||||
cloud: "{{ cloud }}"
|
||||
coe: kubernetes
|
||||
floating_ip_enabled: false
|
||||
image_id: '{{ image_id }}'
|
||||
keypair_id: '{{ keypair.keypair.id }}'
|
||||
name: k8s
|
||||
state: present
|
||||
register: coe_cluster_template
|
||||
|
||||
- name: Assert return values of coe_cluster_template module
|
||||
assert:
|
||||
that:
|
||||
- coe_cluster_template is not changed
|
||||
|
||||
- name: Delete Kubernetes cluster template
|
||||
openstack.cloud.coe_cluster_template:
|
||||
cloud: "{{ cloud }}"
|
||||
name: k8s
|
||||
state: absent
|
||||
register: coe_cluster_template
|
||||
|
||||
- name: Assert return values of coe_cluster_template module
|
||||
assert:
|
||||
that:
|
||||
- coe_cluster_template is changed
|
||||
|
||||
- name: Delete Kubernetes cluster template again
|
||||
openstack.cloud.coe_cluster_template:
|
||||
cloud: "{{ cloud }}"
|
||||
name: k8s
|
||||
state: absent
|
||||
register: coe_cluster_template
|
||||
|
||||
- name: Assert return values of coe_cluster_template module
|
||||
assert:
|
||||
that:
|
||||
- coe_cluster_template is not changed
|
||||
|
||||
- name: Delete keypair
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_keypair
|
||||
state: absent
|
||||
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: Check output of list flavors with filter
|
||||
assert:
|
||||
that:
|
||||
- flavor.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.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.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
|
||||
477
ci/roles/floating_ip/tasks/main.yml
Normal file
477
ci/roles/floating_ip/tasks/main.yml
Normal file
@@ -0,0 +1,477 @@
|
||||
---
|
||||
# Prepare environment
|
||||
- name: List all images
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: images
|
||||
|
||||
- name: Identify CirrOS image name
|
||||
set_fact:
|
||||
image_name: "{{ images.openstack_images|community.general.json_query(query)|first }}"
|
||||
vars:
|
||||
query: "[?starts_with(name, 'cirros')].name"
|
||||
|
||||
- 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_name }}"
|
||||
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_name }}"
|
||||
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
|
||||
72
ci/roles/identity_user_info/tasks/main.yml
Normal file
72
ci/roles/identity_user_info/tasks/main.yml
Normal file
@@ -0,0 +1,72 @@
|
||||
- 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 +0,0 @@
|
||||
image_name: ansible_image
|
||||
@@ -10,24 +10,37 @@
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ image_name }}"
|
||||
name: ansible_image
|
||||
filename: "{{ tmp_file.stdout }}"
|
||||
disk_format: raw
|
||||
tags:
|
||||
- test
|
||||
- ansible
|
||||
register: image
|
||||
|
||||
- debug: var=image
|
||||
- name: Get details of created image
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: ansible_image
|
||||
register: image_info_result
|
||||
|
||||
- name: Verify image info
|
||||
assert:
|
||||
that:
|
||||
- image_info_result.openstack_images[0].name == "ansible_image"
|
||||
- image_info_result.openstack_images[0].tags | sort == ['test', 'ansible'] | sort
|
||||
|
||||
- name: Delete raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ image_name }}"
|
||||
name: ansible_image
|
||||
|
||||
- name: Create raw image (complex)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ image_name }}"
|
||||
name: ansible_image
|
||||
filename: "{{ tmp_file.stdout }}"
|
||||
disk_format: raw
|
||||
is_public: True
|
||||
@@ -40,13 +53,100 @@
|
||||
distro: ubuntu
|
||||
register: image
|
||||
|
||||
- debug: var=image
|
||||
|
||||
- name: Delete raw image (complex)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ image_name }}"
|
||||
name: ansible_image
|
||||
|
||||
- name: Try to get details of deleted image
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: ansible_image
|
||||
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: ansible_image
|
||||
filename: "{{ tmp_file.stdout }}"
|
||||
disk_format: raw
|
||||
tags:
|
||||
- test
|
||||
- ansible
|
||||
project: image_owner_project
|
||||
register: image
|
||||
|
||||
- name: Get details of created image (owner by project name)
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: ansible_image
|
||||
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: ansible_image
|
||||
|
||||
- name: Create raw image (owner by project name and domain name)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
filename: "{{ tmp_file.stdout }}"
|
||||
disk_format: raw
|
||||
tags:
|
||||
- test
|
||||
- ansible
|
||||
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: ansible_image
|
||||
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: ansible_image
|
||||
|
||||
- name: Delete owner project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: image_owner_project
|
||||
domain_id: default
|
||||
|
||||
- name: Delete test image file
|
||||
file:
|
||||
|
||||
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
|
||||
70
ci/roles/loadbalancer/tasks/main.yml
Normal file
70
ci/roles/loadbalancer/tasks/main.yml
Normal file
@@ -0,0 +1,70 @@
|
||||
---
|
||||
- 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
|
||||
|
||||
- name: Upload Amphora image for Octavia to test load balancers
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
container_format: bare
|
||||
disk_format: qcow2
|
||||
filename: /tmp/test-only-amphora-x64-haproxy-ubuntu-bionic.qcow2
|
||||
is_public: false
|
||||
name: test-only-amphora-x64-haproxy-ubuntu-bionic
|
||||
owner: service
|
||||
properties:
|
||||
hw_architecture: x86_64
|
||||
hw_rng_model: virtio
|
||||
state: present
|
||||
tags:
|
||||
- amphora
|
||||
|
||||
- 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 }}"
|
||||
|
||||
@@ -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
|
||||
flavor: m1.tiny
|
||||
server_alt_network: private_alt
|
||||
server_alt_subnet: subnet_alt
|
||||
server_alt_name: ansible_server_alt
|
||||
flavor_name: m1.tiny
|
||||
floating_ip_pool_name: public
|
||||
boot_volume_size: 5
|
||||
|
||||
@@ -1,11 +1,22 @@
|
||||
---
|
||||
- name: List all images
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: images
|
||||
|
||||
- name: Identify CirrOS image name
|
||||
set_fact:
|
||||
image_name: "{{ images.openstack_images|community.general.json_query(query)|first }}"
|
||||
vars:
|
||||
query: "[?starts_with(name, 'cirros')].name"
|
||||
|
||||
- name: Create server with meta as CSV
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ server_name }}"
|
||||
image: "{{ image }}"
|
||||
flavor: "{{ flavor }}"
|
||||
image: "{{ image_name }}"
|
||||
flavor: "{{ flavor_name }}"
|
||||
network: "{{ server_network }}"
|
||||
auto_floating_ip: false
|
||||
meta: "key1=value1,key2=value2"
|
||||
@@ -46,8 +57,8 @@
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ server_name }}"
|
||||
image: "{{ image }}"
|
||||
flavor: "{{ flavor }}"
|
||||
image: "{{ image_name }}"
|
||||
flavor: "{{ flavor_name }}"
|
||||
auto_floating_ip: false
|
||||
network: "{{ server_network }}"
|
||||
meta:
|
||||
@@ -67,7 +78,7 @@
|
||||
- name: Check info about server name
|
||||
assert:
|
||||
that:
|
||||
info.openstack_servers[0].name == "{{ server_name }}"
|
||||
info.openstack_servers[0].name == server_name
|
||||
|
||||
- name: Delete server with meta as dict
|
||||
openstack.cloud.server:
|
||||
@@ -81,8 +92,8 @@
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ server_name }}"
|
||||
image: "{{ image }}"
|
||||
flavor: "{{ flavor }}"
|
||||
image: "{{ image_name }}"
|
||||
flavor: "{{ flavor_name }}"
|
||||
network: "{{ server_network }}"
|
||||
floating_ip_pools:
|
||||
- "{{ floating_ip_pool_name }}"
|
||||
@@ -101,7 +112,7 @@
|
||||
- name: Check info about server image name
|
||||
assert:
|
||||
that:
|
||||
info.openstack_servers[0].image.name == "{{ image }}"
|
||||
info.openstack_servers[0].image.name == image_name
|
||||
|
||||
- name: Delete server (FIP from pool/network)
|
||||
openstack.cloud.server:
|
||||
@@ -115,8 +126,8 @@
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ server_name }}"
|
||||
image: "{{ image }}"
|
||||
flavor: "{{ flavor }}"
|
||||
image: "{{ image_name }}"
|
||||
flavor: "{{ flavor_name }}"
|
||||
network: "{{ server_network }}"
|
||||
auto_floating_ip: false
|
||||
boot_from_volume: true
|
||||
@@ -127,6 +138,27 @@
|
||||
|
||||
- debug: var=server
|
||||
|
||||
- name: Delete server with volume
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ server_name }}"
|
||||
wait: true
|
||||
|
||||
- name: Create a minimal server
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ server_name }}"
|
||||
image: "{{ image_name }}"
|
||||
flavor: "{{ flavor_name }}"
|
||||
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 }}"
|
||||
@@ -150,7 +182,7 @@
|
||||
that:
|
||||
info.openstack_servers|length > 0
|
||||
|
||||
- name: Delete server with volume
|
||||
- name: Delete minimal server
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ server_name }}"
|
||||
image: "{{ image }}"
|
||||
flavor: "{{ flavor }}"
|
||||
image: "{{ image_name }}"
|
||||
flavor: "{{ flavor_name }}"
|
||||
network: "{{ server_network }}"
|
||||
auto_floating_ip: false
|
||||
wait: true
|
||||
@@ -200,7 +200,10 @@
|
||||
that:
|
||||
- info10.openstack_servers.0.status == 'ACTIVE'
|
||||
# not in all versions 'locked' is supported
|
||||
- info10.openstack_servers.0.locked in (None, True)
|
||||
- >-
|
||||
(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
|
||||
@@ -222,7 +225,10 @@
|
||||
that:
|
||||
- info11.openstack_servers.0.status == 'ACTIVE'
|
||||
# not in all versions 'locked' is supported
|
||||
- info11.openstack_servers.0.locked in (None, True)
|
||||
- >-
|
||||
(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
|
||||
@@ -244,7 +250,10 @@
|
||||
that:
|
||||
- info12.openstack_servers.0.status == 'ACTIVE'
|
||||
# not in all versions 'locked' is supported
|
||||
- info12.openstack_servers.0.locked in (None, False)
|
||||
- >-
|
||||
(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
|
||||
@@ -267,7 +276,10 @@
|
||||
- info13.openstack_servers.0.status == 'ACTIVE'
|
||||
- server is changed # no support for unlock idempotency
|
||||
# not in all versions 'locked' is supported
|
||||
- info13.openstack_servers.0.locked in (None, False)
|
||||
- >-
|
||||
(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:
|
||||
@@ -368,7 +380,7 @@
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
image: "{{ image }}"
|
||||
image: "{{ image_name }}"
|
||||
action: rebuild
|
||||
wait: true
|
||||
register: server
|
||||
@@ -389,7 +401,7 @@
|
||||
openstack.cloud.server_action:
|
||||
cloud: "{{ cloud }}"
|
||||
server: "{{ server_name }}"
|
||||
image: "{{ image }}"
|
||||
image: "{{ image_name }}"
|
||||
action: rebuild
|
||||
wait: true
|
||||
admin_password: random
|
||||
@@ -406,3 +418,195 @@
|
||||
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_name }}"
|
||||
flavor: "{{ flavor_name }}"
|
||||
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
|
||||
116
ci/run-ansible-tests-collection.sh
Normal file → Executable file
116
ci/run-ansible-tests-collection.sh
Normal file → Executable file
@@ -1,3 +1,4 @@
|
||||
#!/bin/bash
|
||||
#############################################################################
|
||||
# run-ansible-tests.sh
|
||||
#
|
||||
@@ -6,20 +7,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,33 +34,47 @@
|
||||
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} ;;
|
||||
e) ENVDIR=${OPTARG} ;;
|
||||
?) echo "Invalid option: -${OPTARG}"
|
||||
c) CLOUD=$OPTARG ;;
|
||||
u) CLOUD_ALT=$OPTARG ;;
|
||||
e) ENVDIR=$OPTARG ;;
|
||||
?) echo "Invalid option: -$OPTARG"
|
||||
exit 1;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z ${ENVDIR} ]
|
||||
then
|
||||
# Shift arguments read by getopts
|
||||
shift $((OPTIND-1))
|
||||
|
||||
# Remaining arguments are Ansible tags
|
||||
TAGS=$( echo "$*" | tr ' ' , )
|
||||
|
||||
if [ -z "$ENVDIR" ]; then
|
||||
echo "Option -e is required"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
shift $((OPTIND-1))
|
||||
TAGS=$( echo "$*" | tr ' ' , )
|
||||
if [ ! -d ci ]; then
|
||||
echo "Script must be run from collection's root directory"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Install collections before dealing with Ansible virtual environments
|
||||
if [[ -z "$PIP_INSTALL" ]]; then
|
||||
# Install Ansible collections before dealing with virtual environments for Ansible
|
||||
|
||||
# Install collections used in ci
|
||||
ansible-galaxy collection install --requirements-file ci/requirements.yml
|
||||
|
||||
# Install this collection
|
||||
if [ -z "$PIP_INSTALL" ]; then
|
||||
tox -ebuild
|
||||
ansible-galaxy collection install $(ls build_artifact/openstack-cloud-*) --force
|
||||
ansible-galaxy collection install "$(find build_artifact/ -maxdepth 1 -name 'openstack-cloud-*')" --force
|
||||
TEST_COLLECTIONS_PATHS=${HOME}/.ansible/collections:$ANSIBLE_COLLECTIONS_PATHS
|
||||
else
|
||||
pip freeze | grep ansible-collections-openstack
|
||||
@@ -66,25 +83,16 @@ fi
|
||||
|
||||
# We need to source the current tox environment so that Ansible will
|
||||
# be setup for the correct python environment.
|
||||
source $ENVDIR/bin/activate
|
||||
source "$ENVDIR/bin/activate"
|
||||
|
||||
if [ ${USE_DEV} -eq 1 ]
|
||||
then
|
||||
if [ -d ${ENVDIR}/ansible ]
|
||||
then
|
||||
if [ "$USE_DEV" -eq 1 ]; then
|
||||
if [ -d "$ENVDIR/ansible" ]; then
|
||||
echo "Using existing Ansible source repo"
|
||||
else
|
||||
echo "Installing Ansible source repo at $ENVDIR"
|
||||
git clone --recursive https://github.com/ansible/ansible.git ${ENVDIR}/ansible
|
||||
git clone --recursive https://github.com/ansible/ansible.git "$ENVDIR/ansible"
|
||||
fi
|
||||
source $ENVDIR/ansible/hacking/env-setup
|
||||
fi
|
||||
|
||||
# Run the shade Ansible tests
|
||||
tag_opt=""
|
||||
if [ ! -z ${TAGS} ]
|
||||
then
|
||||
tag_opt="--tags ${TAGS}"
|
||||
source "$ENVDIR/ansible/hacking/env-setup"
|
||||
fi
|
||||
|
||||
# Loop through all ANSIBLE_VAR_ environment variables to allow passing the further
|
||||
@@ -96,22 +104,32 @@ for var in $(env | grep -e '^ANSIBLE_VAR_'); do
|
||||
ANSIBLE_VARS+="${ANSIBLE_VAR_NAME}=${ANSIBLE_VAR_VALUE} " # concat variables
|
||||
done
|
||||
|
||||
# Until we have a module that lets us determine the image we want from
|
||||
# within a playbook, we have to find the image here and pass it in.
|
||||
# We use the openstack client instead of nova client since it can use clouds.yaml.
|
||||
IMAGE=`openstack --os-cloud=${CLOUD} image list -f value -c Name | grep cirros | grep -v -e ramdisk -e kernel`
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo "Failed to find Cirros image"
|
||||
exit 1
|
||||
# Discover openstacksdk version
|
||||
SDK_VER=$(python -c "import openstack; print(openstack.version.__version__)")
|
||||
|
||||
# Choose integration tests
|
||||
tag_opt=""
|
||||
if [ -n "$TAGS" ]; then
|
||||
tag_opt="--tags $TAGS"
|
||||
fi
|
||||
|
||||
# Discover openstackSDK version
|
||||
SDK_VER=$(python -c "import openstack; print(openstack.version.__version__)")
|
||||
pushd ci/
|
||||
# run tests
|
||||
if ! systemctl is-enabled devstack@o-api.service 2>&1; then
|
||||
# Skip loadbalancer tasks if Octavia is not available
|
||||
tag_opt+=" --skip-tags loadbalancer"
|
||||
fi
|
||||
|
||||
# TODO: Replace with more robust test for Magnum availability
|
||||
if [ ! -e /etc/magnum ]; then
|
||||
# Skip coe tasks if Magnum is not available
|
||||
tag_opt+=" --skip-tags coe_cluster,coe_cluster_template"
|
||||
fi
|
||||
|
||||
cd ci/
|
||||
|
||||
# Run tests
|
||||
set -o pipefail
|
||||
# shellcheck disable=SC2086
|
||||
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}
|
||||
popd
|
||||
-e "sdk_version=${SDK_VER} cloud=${CLOUD} cloud_alt=${CLOUD_ALT} ${ANSIBLE_VARS}" \
|
||||
${tag_opt} 2>&1 | sudo tee /opt/stack/logs/test_output.log
|
||||
|
||||
@@ -4,12 +4,31 @@
|
||||
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: coe_cluster, tags: coe_cluster }
|
||||
- { role: coe_cluster_template, tags: coe_cluster_template }
|
||||
- { 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 +40,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 }
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/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
|
||||
@@ -1,110 +0,0 @@
|
||||
#!/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()
|
||||
@@ -1,149 +0,0 @@
|
||||
#!/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()
|
||||
@@ -1,81 +0,0 @@
|
||||
##### 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: []
|
||||
115
docs/branching.md
Normal file
115
docs/branching.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# Ansible OpenStack Collection and its branches
|
||||
|
||||
Our codebase has been split into two separate release series, `2.x.x` and `1.x.x`:
|
||||
|
||||
* `2.x.x` releases of Ansible OpenStack collection are compatible with [OpenStack SDK][openstacksdk] `1.x.x` and its
|
||||
release candidates `0.99.0` and later *only* (OpenStack Zed and later). Our [`master` branch][a-c-o-branch-master]
|
||||
tracks our `2.x.x` releases.
|
||||
* `1.x.x` releases of Ansible OpenStack collection are compatible with [OpenStack SDK][openstacksdk] `0.x.x` prior to
|
||||
`0.99.0` *only* (OpenStack Yoga and earlier). Our [`stable/1.0.0` branch][a-c-o-branch-stable-1-0-0] tracks our
|
||||
`1.x.x` releases.
|
||||
* `2.x.x` releases of Ansible OpenStack collection are not backward compatible to `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!
|
||||
|
||||
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.0`) 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][openstacksdk-release-notes-zed]. The Ansible OpenStack collection is heavily based on OpenStack SDK.
|
||||
With OpenStack SDK becoming backward incompatible, so does our Ansible OpenStack collection. For example, with
|
||||
openstacksdk `>=0.99.0` most Ansible modules return dictionaries instead `Munch` objects and many of their keys have
|
||||
been renamed. We simply lack the development resources to maintain a backward compatible interface in Ansible OpenStack
|
||||
collection across several SDK releases.
|
||||
|
||||
[a-c-o-branch-master]: https://opendev.org/openstack/ansible-collections-openstack/src/branch/master
|
||||
[a-c-o-branch-stable-1-0-0]: https://opendev.org/openstack/ansible-collections-openstack/src/branch/stable/1.0.0
|
||||
[ansible-tags]: https://docs.ansible.com/ansible/latest/user_guide/playbooks_tags.html
|
||||
[openstacksdk-cloud-layer-stays]: https://meetings.opendev.org/irclogs/%23openstack-sdks/%23openstack-sdks.2022-04-27.log.html
|
||||
[openstacksdk-release-notes-zed]: https://docs.openstack.org/releasenotes/openstacksdk/zed.html
|
||||
[openstacksdk-to-dict]: https://opendev.org/openstack/openstacksdk/src/branch/master/openstack/resource.py
|
||||
[openstacksdk]: https://opendev.org/openstack/openstacksdk
|
||||
|
||||
## Notable changes between release series 2.x.x and 1.x.x
|
||||
|
||||
When we ported our collection to [openstacksdk][openstacksdk] `>=0.99.0`, a series of changes were applied to our
|
||||
`master` branch. We went through each module in our collection and did the following:
|
||||
|
||||
* Identify function calls which use [openstacksdk][openstacksdk]'s cloud layer, e.g. `self.conn.get_network()`. Change
|
||||
these calls to functions from openstacksdk's resource proxies, e.g. `self.conn.network.find_network()`, if possible.
|
||||
As a guideline use this decision tree:
|
||||
- If a functionality requires a single api call (to the OpenStack API), then use functions from openstacksdk's
|
||||
resource proxies.
|
||||
- If a functionality requires multiple api calls (to the OpenStack API), e.g. when creating and attaching a floating
|
||||
ip to a server, then use functions from openstacksdk's cloud layer.
|
||||
- When unsure which of openstacksdk's layers to use, then first go to resource proxies and then to its cloud layer.
|
||||
Mainly this applies to functions retrieving information, i.e. all calls where we get info about cloud resources
|
||||
should be changed to openstacksdk functions which return proxy resources.
|
||||
**Note**: Using openstacksdk's cloud layer for functionality which is not provided by openstacksdk's proxy layer is
|
||||
acceptable. [openstacksdk's cloud layer is not going away][openstacksdk-cloud-layer-stays]. For example, listing
|
||||
functions in openstacksdk's cloud layer such as `search_users()` often allow to filter results with function parameter
|
||||
`filters`. openstacksdk's proxy layer does not provide an equivalent and thus using `search_users()` is fine.
|
||||
* Functions in openstacksdk's cloud layer often have different return values then pre-0.99.0 releases. When return
|
||||
values have changed in any of the functions which a module uses, update `RETURN` variable. If a module has no `RETURN`
|
||||
variable, define it.
|
||||
* Only return data types such as lists or dictionaries to Ansible. For example, the return statement
|
||||
`self.exit_json(changed=False, floating_ips=floating_ips)` in module [`floating_ip_info`](
|
||||
../plugins/modules/floating_ip_info.py) shall return a list of `dict`'s. Use openstacksdk's `to_dict` function to
|
||||
convert resources to dictionaries. Setting its parameters such as `computed` to `False` will drop computed attributes
|
||||
from the resulting dict. Read [`to_dict`'s docstring][openstacksdk-to-dict] for more parameters. Using `to_dict` might
|
||||
change the return values of your Ansible module. Please document changes to return values in `RETURN`.
|
||||
* Older openstacksdk releases did not provide the `to_dict` function. We decided to allow breaking backward
|
||||
compatibility with release `2.x.x`, so workarounds such as `(o.to_dict() if hasattr(o, 'to_dict') else dict(o))` are
|
||||
not required anymore and shall be avoided.
|
||||
* Manually dropping attributes such as `location` or `link` from openstacksdk resources is no longer necessary.
|
||||
Workarounds such as
|
||||
```Python
|
||||
for raw in self.conn.block_storage.backups(**attrs):
|
||||
dt = raw.to_dict()
|
||||
dt.pop('location')
|
||||
data.append(dt)
|
||||
```
|
||||
are no longer necessary and can be removed.
|
||||
* Add tests to [ci/run-collection.yml](../ci/run-collection.yml) and [ci/roles](../ci/roles). Each module has a
|
||||
dedicated Ansible role with tests in `ci/roles`. Create one if no such directory exist.
|
||||
* With release of openstacksdk 0.99.0 most of our CI tests in [ci/](../ci/) failed. To prove that module patches
|
||||
actually fix issues all CI tests for unrelated broken modules have to be skipped. To run CI tests for patched modules
|
||||
only, temporarily list the [Ansible tags][ansible-tags] of all CI tests which should run in
|
||||
`vars: { tox_extra_args: ... }` of job `ansible-collections-openstack-functional-devstack-ansible` in `.zuul.yaml`
|
||||
([example](https://review.opendev.org/c/openstack/ansible-collections-openstack/+/825291/16/.zuul.yaml)) and send the
|
||||
patch for review. Once all CI tests are passing in Zuul CI, undo changes to [`.zuul.yaml`](../.zuul.yaml), i.e. revert
|
||||
changes to `tox_extra_args` and submit final patch for review.
|
||||
* ~~Cherry-pick or backport patches for `master` branch to `stable/1.0.0` branch. Both branches should divert only if
|
||||
necessary in order to keep maintainence of two separate branches simple. When applying patches to the `stable/1.0.0`
|
||||
branch, it is often necessary to make changes to not break backward compatibility on the `stable/1.0.0` branch. On
|
||||
`master` we use `.to_dict(computed=False)` which we have to change to `.to_dict(computed=True)` on `stable/1.0.0`. For
|
||||
example, this [patch for `master` branch](
|
||||
https://review.opendev.org/c/openstack/ansible-collections-openstack/+/828108) has been [tweaked and cherry-picked to
|
||||
`stable/1.0.0` branch](https://review.opendev.org/c/openstack/ansible-collections-openstack/+/836312).~~
|
||||
Backporting patches from `master` to `stable/1.0.0` branch have been abandoned due to lack of time and resources ⚠️
|
||||
* Version checks in modules are no longer necessary because we require openstacksdk >=0.99.0 globally. For example,
|
||||
drop `min_ver`/`max_ver` constraints on module arguments.
|
||||
* Rename module parameter names to the attribute names that openstacksdk uses, e.g. `shared` becomes `is_shared`. Keep
|
||||
old names as aliases for input backward compatibility.
|
||||
* Some modules have if-else branches for handling cases where a `name` is given. For most modules these can be dropped
|
||||
safely because names can be passed as a query parameter.
|
||||
* Some modules do not use `name` as module parameters for resource names. For example, `port` module had an attribute
|
||||
called `port` instead of `name`. Rename those attributes to `name` to be consistent with other modules and because
|
||||
openstacksdk is doing the same. Add old attribute names as aliases to keep input backward compatibility.
|
||||
* Replacing `self.conn.get_*` with `self.conn.*.find_*` functions provide a `ignore_missing=False` parameter. This
|
||||
allows to drop `self.fail_json()` calls in modules. Less code means less to maintain.
|
||||
* Some modules pass `ignore_missing=True` to `self.conn.*.find_*` functions and then fail if the return value is `None`.
|
||||
Often this code can be simplified by changing `ignore_missing` to `False` and dropping the if-else branches.
|
||||
* When module attribute that have choices, always doubt its values. The module code was probably written long ago and
|
||||
the choices given might be outdated. It might also make sense to drop the `choices` parameter completely when choices
|
||||
are to narrow and might soon be outdated again.
|
||||
* Check comments whether they are still relevant.
|
||||
* Sanity check existing integration tests. For example, return values of module calls should be tested else running a
|
||||
test could be useless in the first place.
|
||||
* Most functions in openstacksdk's cloud layer no longer return `Munch` objects. Instead they return resources which
|
||||
should be converted to dictionaries. Update `RETURN` docs in modules, e.g. change from `type: complex` to
|
||||
`type: dict`.
|
||||
* Move list of expected module results to role defaults, e.g. define a variable `expected_fields`. This enables easier
|
||||
reuse.
|
||||
* Following and applying our [development guide](contributing.md) and [review guide](reviewing.md)
|
||||
189
docs/contributing.md
Normal file
189
docs/contributing.md
Normal file
@@ -0,0 +1,189 @@
|
||||
# Development Guide for Ansible OpenStack Collection
|
||||
|
||||
Ansible OpenStack collection is a set of Ansible modules for interacting with the OpenStack API as either an admin or an
|
||||
end user.
|
||||
|
||||
We, and the OpenStack community in general, use OpenDev for its development. Patches are submitted to [OpenDev Gerrit][
|
||||
opendev-gerrit]. Pull requests submitted through GitHub will be ignored. Please read OpenStack's [Developer Workflow][
|
||||
openstack-developer-workflow] for details.
|
||||
|
||||
For hacking on the Ansible OpenStack collection it helps to [prepare a DevStack environment](devstack.md) first.
|
||||
|
||||
## Hosting
|
||||
|
||||
* [Bug tracker][storyboard]
|
||||
* [Mailing list `openstack-discuss@lists.openstack.org`][openstack-discuss].
|
||||
Prefix subjects with `[aoc]` or `[aco]` for faster responses.
|
||||
* [Code Hosting][opendev-a-c-o]
|
||||
* [Code Review][gerrit-a-c-o]
|
||||
|
||||
## Branches
|
||||
|
||||
For rationale behind our `master` and `stable/1.0.0` branches and details on our relation to [openstacksdk][
|
||||
openstacksdk], please read our [branching docs](branching.md).
|
||||
|
||||
## Examples
|
||||
|
||||
* For an example on how to write a `*_info` module, have a look at module
|
||||
[`openstack.cloud.neutron_rbac_policies_info`](../plugins/modules/neutron_rbac_policies_info.py).
|
||||
* For an example on how to write a regular non-`*_info` module, have a look at module
|
||||
[`openstack.cloud.neutron_rbac_policy`](../plugins/modules/neutron_rbac_policy.py) or any other module which
|
||||
contains a `_will_change` method.
|
||||
* Do NOT use modules which define a `_system_state_change` function as examples, because they often do not properly
|
||||
define Ansible's check mode, idempotency and/or updates. Refer to modules which define a `_will_change` function
|
||||
instead.
|
||||
|
||||
## Naming
|
||||
|
||||
* This collection is named `openstack.cloud`. There is no need for further namespace prefixing.
|
||||
* Name any module that a cloud consumer would expect from [openstackclient (OSC)][openstackclient], for example `server`
|
||||
instead of `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 ip address
|
||||
are managed by Nova or Neutron.
|
||||
|
||||
## 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`, that should be returned instead of
|
||||
the `id`.
|
||||
* Modules should return a value of type `dict`, `list` or other primitive data types. For example, `floating_ips` in
|
||||
`self.exit_json(changed=False, floating_ips=floating_ips)` should to be a list of `dict`s. Use `to_dict()` on
|
||||
[openstacksdk][openstacksdk] objects to convert resources to dictionaries. Setting its parameters such as `computed`
|
||||
to `False` will drop computed attributes from the resulting dict. Read [`to_dict`'s docstring][openstacksdk-to-dict]
|
||||
for more parameters.
|
||||
* Module results have to be documented in `RETURN` docstring.
|
||||
* We should document which attribute cannot be updated in `DOCUMENTATION` variable. For example, insert
|
||||
`'This attribute cannot be updated.'` to `DOCUMENTATION` like we did for the `server` module and others.
|
||||
* Sorting module options in `DOCUMENTATION`, attributes in `RETURN`, entries in `argument_spec` and expected fields in
|
||||
integration tests will make reviewing easier and faster.
|
||||
|
||||
## Interoperability
|
||||
|
||||
* It should be assumed that the cloud consumer does not know details about the deployment choices their cloud provider
|
||||
made. A best effort should be made to present one sane interface to the Ansible user regardless of deployer choices.
|
||||
* It should be assumed that a user may have more than one cloud account that they wish to combine as part of a single
|
||||
Ansible-managed infrastructure.
|
||||
* All modules should work appropriately against all existing versions of OpenStack regardless of upstream EOL status.
|
||||
The reason for this is that the Ansible modules are for consumers of cloud APIs who are not in a position to impact
|
||||
what version of OpenStack their cloud provider is running. It is known that there are OpenStack Public Clouds running
|
||||
rather old versions of OpenStack, but from a user point of view the Ansible modules can still support these users
|
||||
without impacting use of more modern versions.
|
||||
|
||||
## Coding Guidelines
|
||||
|
||||
* Modules should
|
||||
+ be idempotent (not being idempotent requires a solid reason),
|
||||
+ return whether something has `changed`,
|
||||
+ support `check mode`,
|
||||
+ be based on (be subclasses of) `OpenStackModule` in
|
||||
`ansible_collections.openstack.cloud.plugins.module_utils.openstack`,
|
||||
+ should include `extends_documentation_fragment: openstack` in their `DOCUMENTATION` docstring,
|
||||
+ be registered in `meta/action_groups.yml` for enabling the variables to be set in
|
||||
[group level][ansible-module-defaults].
|
||||
* Complex functionality, cloud interaction or interoperability code should be moved to [openstacksdk][openstacksdk].
|
||||
* OpenStack API interactions should happen via [openstacksdk][openstacksdk] and not via OpenStack component libraries.
|
||||
The OpenStack component libraries do no have end users as a primary audience, they are for intra-server communication.
|
||||
* When a resource exist and should be deleted (absent), then pass the resource to the `delete_*` function, not its name.
|
||||
Passing a name requires openstacksdk to find that resource again, doing a unnecessary api call, because we queried the
|
||||
resource before.
|
||||
* `*_info` modules never raise exceptions when resources cannot be found. When resources cannot be found, then a
|
||||
`*_info` module returns an empty list instead. For example, module `openstack.cloud.neutron_rbac_policies_info` will
|
||||
return an empty list when no project with name given in module parameter `project` can be found.
|
||||
* When a id is given in `*_info` modules, then we do not need nor want extra code to handle that. Instead most
|
||||
[openstacksdk][openstacksdk] resources allow to pass ids as query arguments to OpenStack API. For example,
|
||||
`identity.identity_providers()` can be used for both cases: Where an id is given and where no id is given. No need to
|
||||
call `get_identity_provider()`.
|
||||
* `EXAMPLES` docstring in modules (and Ansible's own modules) consist of a list of tasks. They do not contain YAML
|
||||
directives end marker line (---) and do not define playbooks (e.g. hosts keyword). They shall be simple, e.g. do not
|
||||
do fancy loops, heavy use of variables or use Ansible directives for no apparent reason such as ignore_errors or
|
||||
register.
|
||||
* `self.params.get('...')` can be replaced with `self.params['...']` because parameters from `argument_spec` will always
|
||||
be in `self.params`. If not defined differently, they have a default value of `None`.
|
||||
* Writing code to check that some options cannot be updated and to fail if user still tries to update that value is most
|
||||
often not worth it. It would require much more code to catch all cases where updates are impossible and we would have
|
||||
to implement it consistently across modules. Atm we are fine with documenting which attribute cannot be updated in
|
||||
`DOCUMENTATION` variable. We could simply drop these checks and insert `'This attribute cannot be updated.'` to
|
||||
`DOCUMENTATION` like we did for the server module and others.
|
||||
* [openstacksdk][openstacksdk] functions often accept IDs but no names, e.g. `find_address_scope()` and
|
||||
`create_address_scope()` accept a `project_id` parameter. Most modules in our collection use names for finding
|
||||
resources, so we want to support the same for resources attributes such as `project_id` in `AddressScope`.
|
||||
* Constraints for module parameters and error handling can often be implemented in `argument_spec` or `module_kwargs`
|
||||
`module_kwargs` allows to define dependencies between module options such as [`mutually_exclusive`,
|
||||
`required_together`, `required_if` etc.][ansible-argument-spec-dependencies].
|
||||
* When using [openstacksdk][openstacksdk]'s `find_*` functions (`self.conn.*.find_*`), then pass `ignore_missing=False`
|
||||
instead of checking its return value and failing with `self.fail_json()` if it is `None`.
|
||||
* Use module option names which match attribute names used in [openstacksdk][openstacksdk], e.g. use `is_shared` instead
|
||||
of `shared`. When refactoring modules, keep old option names as aliases to keep backward compatibility. Using
|
||||
openstacksdk names provides two benefits:
|
||||
- The module inputs and outputs do match, are consistent and thus the module is easier to use.
|
||||
- Most code for filters and query arguments can be replaced with loops. [This patch for floating_ip_info has some
|
||||
ideas for how to write loops](https://review.opendev.org/c/openstack/ansible-collections-openstack/+/828613).
|
||||
* Use functions from [openstacksdk][openstacksdk]'s proxy layer instead of its cloud layer, if possible. For example,
|
||||
use `self.conn.network.find_network()`, not `self.conn.get_network()`. As a guideline use this decision tree:
|
||||
- If a functionality requires a single api call (to the OpenStack API), then use functions from openstacksdk's proxy
|
||||
layer.
|
||||
- If a functionality requires several api calls (to the OpenStack API), e.g. when creating and attaching a floating ip
|
||||
to a server, then use functions from openstacksdk's cloud layer.
|
||||
- When unsure which of openstacksdk's layers to use, then first go to proxy layer, then to its cloud layer and if this
|
||||
is not sufficient, then use its resource layer. Mainly, this applies to functions retrieving information, i.e. all
|
||||
calls where we get info about cloud resources should be changed to openstacksdk functions which return proxy
|
||||
resources.
|
||||
- It is perfectly fine to use openstacksdk's cloud layer for functionality which is not provided by openstacksdk's
|
||||
proxy layer. [SDK's cloud layer is not going away][openstacksdk-cloud-layer-stays].
|
||||
For example, `list_*` functions from openstacksdk's cloud layer such as `search_users()` allow to filter retrieved
|
||||
results with function parameter `filters`. openstacksdk's proxy layer does not provide an equivalent and thus the
|
||||
use of `search_users()` is perfectly fine.
|
||||
|
||||
## Testing
|
||||
|
||||
* Modules have to be tested with CI integration tests (if possible).
|
||||
* Each module has a corresponding Ansible role containing integration tests in [`ci/roles`](../ci/roles) directory.
|
||||
* Ensure role names of integration tests in [`ci/roles`](../ci/roles) match the module names.
|
||||
Only exception are `*_info` modules: Their integration tests are located in the same Ansible roles as their
|
||||
non-`*_info` equivalents (to reduce redundant code). For example, tests for both modules `federation_mapping` and
|
||||
`federation_mapping_info` can be found in role `federation_mapping`.
|
||||
* Zuul CI jobs are defined in [`.zuul.yaml`](../.zuul.yaml).
|
||||
* Add assertions on return values from Ansible modules in integration tests. For an example, refer to
|
||||
[`ci/roles/floating_ip/tasks/main.yml`](../ci/roles/floating_ip/tasks/main.yml).
|
||||
We need those checks to validate return values from [openstacksdk][openstacksdk], which might change across releases.
|
||||
Adding those assertions will be done in minutes, while checking the output manually during code reviews takes much
|
||||
more time.
|
||||
* Our Zuul CI jobs will run `ansible-test` for sanity checking.
|
||||
* Use `tox -elinters_latest` to run various linters against your code.
|
||||
|
||||
## Upload
|
||||
|
||||
* Study our [Review Guidelines](reviewing.md) before submitting a patch.
|
||||
* Use Gerrit's work-in-progress feature to mark the status of the patch. A minus workflow (-w) will be reset when a new
|
||||
patchset is uploaded and hence easy to miss.
|
||||
* When you edit a patch, first rebase your patch on top of the current branch. Sometimes we replace code in all modules
|
||||
which might cause merge conflicts for you otherwise. For example, we dropped all options with default values from
|
||||
`argument_spec` such as `required=False`.
|
||||
|
||||
## Release
|
||||
|
||||
Read [Release Guide](releasing.md) on how to publish new releases.
|
||||
|
||||
## Permissions
|
||||
|
||||
* Only [members of group `ansible-collections-openstack-core`][group-a-c-o-core] are allowed to merge patches.
|
||||
* Only [members of group `ansible-collections-openstack-release`][group-a-c-o-release] are allowed to push tags and
|
||||
trigger our release job `ansible-collections-openstack-release` in [galaxy.yml](../galaxy.yml).
|
||||
* Only members of `openstack` namespace in Ansible Galaxy are allowed to apply changes to meta properties of Ansible
|
||||
collection [`openstack.cloud`][ansible-galaxy-openstack-cloud] on Ansible Galaxy.
|
||||
|
||||
[ansible-argument-spec-dependencies]: https://docs.ansible.com/ansible/latest/dev_guide/developing_program_flow_modules.html#argument-spec-dependencies
|
||||
[ansible-galaxy-openstack-cloud]: https://galaxy.ansible.com/openstack/cloud
|
||||
[ansible-module-defaults]: https://docs.ansible.com/ansible/latest/user_guide/playbooks_module_defaults.html
|
||||
[gerrit-a-c-o]: https://review.opendev.org/q/status:open+project:openstack/ansible-collections-openstack
|
||||
[group-a-c-o-core]: https://review.opendev.org/admin/groups/0e01228e912733e8b9a8d957631e41665aa0ffbd,members
|
||||
[group-a-c-o-release]: https://review.opendev.org/admin/groups/8bca2018f3710f94374aee4b3c9771b9ff0a2254,members
|
||||
[opendev-a-c-o]: https://opendev.org/openstack/ansible-collections-openstack
|
||||
[opendev-gerrit]: https://review.opendev.org/
|
||||
[openstack-developer-workflow]: https://docs.openstack.org/infra/manual/developers.html#development-workflow
|
||||
[openstack-discuss]: http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-discuss
|
||||
[openstackclient]: https://docs.openstack.org/python-openstackclient/latest/
|
||||
[openstacksdk-cloud-layer-stays]: https://meetings.opendev.org/irclogs/%23openstack-sdks/%23openstack-sdks.2022-04-27.log.html
|
||||
[openstacksdk-to-dict]: https://opendev.org/openstack/openstacksdk/src/branch/master/openstack/resource.py
|
||||
[openstacksdk]: https://opendev.org/openstack/openstacksdk
|
||||
[storyboard]: https://storyboard.openstack.org/#!/project/openstack/ansible-collections-openstack
|
||||
107
docs/devstack.md
Normal file
107
docs/devstack.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# Preparing a DevStack environment for Ansible collection development
|
||||
|
||||
For developing on the Ansible OpenStack collection, it helps to install DevStack and two Python [`virtualenv`][
|
||||
virtualenv]s, one with [openstacksdk][openstacksdk] `<0.99.0` and one with [openstacksdk][openstacksdk] `>=1.0.0` (or
|
||||
one of its release candidates `>=0.99.0`). The first is for patches against our `stable/1.0.0` branch of the collection,
|
||||
while the newer openstacksdk is for patches against our `master` branch.
|
||||
|
||||
First, [follow DevStack's guide][devstack] to set up DevStack on a virtual machine. An Ansible inventory and a playbook
|
||||
to set up your own local DevStack as a libvirt domain can be found in Ansible collection [`jm1.cloudy`][jm1-cloudy],
|
||||
look for host `lvrt-lcl-session-srv-200-devstack`.
|
||||
|
||||
**Beware:** DevStack's purpose is to be set up quickly and destroyed after development or testing is done. It cannot
|
||||
be rebooted safely or upgraded easily.
|
||||
|
||||
Some Ansible modules and unit tests in the Ansible OpenStack collection require additional DevStack plugins which
|
||||
are not enabled by default. [Plugins are enabled in DevStack's `local.conf`][devstack-plugins]. Examples:
|
||||
|
||||
- Use the DevStack configuration which the Zuul CI jobs are applying when testing the Ansible OpenStack collection. For
|
||||
example, go to the logs of job [`ansible-collections-openstack-functional-devstack`][devstack-jobs] and use file
|
||||
`controller/logs/local_conf.txt` as your `local.conf` for DevStack.
|
||||
- https://gist.github.com/sshnaidm/43ca23c3f23bd6015d18868ac7405a13
|
||||
- https://paste.opendev.org/show/812460/
|
||||
|
||||
For a list of plugins refer to [DevStack's plugin registry][devstack-plugin-registry].
|
||||
|
||||
Next, prepare two Python [`virtualenv`][virtualenv]s, one with [openstacksdk][openstacksdk] `<0.99.0` and one with
|
||||
[openstacksdk][openstacksdk] `>=1.0.0` (or one of its release candidates `>=0.99.0`):
|
||||
|
||||
```sh
|
||||
# DevStack is presumed to be installed on the development machine
|
||||
# and its configuration file available at ~/devstack/openrc
|
||||
|
||||
git clone https://opendev.org/openstack/ansible-collections-openstack.git
|
||||
mkdir -p ~/.ansible/collections/ansible_collections/openstack/
|
||||
ln -s ansible-collections-openstack ~/.ansible/collections/ansible_collections/openstack/cloud
|
||||
|
||||
# Prepare environment for developing patches against
|
||||
# Ansible OpenStack collection 2.x.x and openstacksdk>=0.99.0
|
||||
cd ansible-collections-openstack/
|
||||
git checkout master
|
||||
virtualenv -p python3 ~/.local/share/virtualenv/ansible-openstacksdk-1
|
||||
source ~/.local/share/virtualenv/ansible-openstacksdk-1/bin/activate
|
||||
pip install -r test-requirements.txt
|
||||
pip install git+https://opendev.org/openstack/openstacksdk
|
||||
pip install ipython
|
||||
source ~/devstack/openrc admin admin
|
||||
ipython
|
||||
|
||||
cd ..
|
||||
|
||||
# Prepare environment for developing patches against
|
||||
# Ansible OpenStack collection 1.x.x and openstacksdk<0.99.0
|
||||
virtualenv -p python3 ~/.local/share/virtualenv/ansible-openstacksdk-0
|
||||
source ~/.local/share/virtualenv/ansible-openstacksdk-0/bin/activate
|
||||
cd ansible-collections-openstack/
|
||||
git checkout stable/1.0.0
|
||||
pip install -r test-requirements.txt
|
||||
pip install 'openstacksdk<0.99.0'
|
||||
pip install ipython
|
||||
source ~/devstack/openrc admin admin
|
||||
ipython
|
||||
```
|
||||
|
||||
The first IPython instance uses openstacksdk >=0.99.0 and is for developing at the 2.x.x series of the Ansible OpenStack
|
||||
collection. The second IPython instance uses openstacksdk <0.99.0 and is suited for the 1.x.x series of the collection.
|
||||
For example, type in each IPython instance:
|
||||
|
||||
```python
|
||||
import openstack
|
||||
conn = openstack.connect()
|
||||
|
||||
# optional
|
||||
openstack.enable_logging(debug=True)
|
||||
|
||||
# and start hacking..
|
||||
list(conn.network.ips())[0].to_dict(computed=False)
|
||||
```
|
||||
|
||||
To run the unit tests of the collection, run this in a Bash shell:
|
||||
|
||||
```sh
|
||||
SDK_VER=$(python -c "import openstack; print(openstack.version.__version__)")
|
||||
ansible-playbook -vvv ci/run-collection.yml -e "sdk_version=${SDK_VER} cloud=devstack-admin cloud_alt=devstack-alt"
|
||||
```
|
||||
|
||||
Use `ansible-playbook`'s `--tags` and `--skip-tags` parameters to skip CI tests. For a list of available tags, refer to
|
||||
[`ci/run-collection.yml`](../ci/run-collection.yml).
|
||||
|
||||
Or run Ansible modules individually:
|
||||
|
||||
```sh
|
||||
ansible localhost -m openstack.cloud.floating_ip -a 'server=ansible_server1 wait=true' -vvv
|
||||
```
|
||||
|
||||
When submitting a patch with `git review`, our Zuul CI jobs will test your changes against different versions of
|
||||
openstacksdk, Ansible and DevStack. Refer to [`.zuul.yaml`](../.zuul.yaml) for a complete view of all CI jobs. To
|
||||
trigger experimental jobs, write a comment in Gerrit which contains `check experimental`.
|
||||
|
||||
Happy hacking!
|
||||
|
||||
[devstack-jobs]: https://zuul.opendev.org/t/openstack/builds?job_name=ansible-collections-openstack-functional-devstack&project=openstack/ansible-collections-openstack
|
||||
[devstack-plugin-registry]: https://docs.openstack.org/devstack/latest/plugin-registry.html
|
||||
[devstack-plugins]: https://docs.openstack.org/devstack/latest/plugins.html
|
||||
[devstack]: https://docs.openstack.org/devstack/latest/
|
||||
[jm1-cloudy]: https://github.com/JM1/ansible-collection-jm1-cloudy
|
||||
[openstacksdk]: https://opendev.org/openstack/openstacksdk/
|
||||
[virtualenv]: https://virtualenv.pypa.io/en/latest/
|
||||
@@ -1,67 +0,0 @@
|
||||
.. _OpenStack_module_development:
|
||||
|
||||
OpenStack Ansible Modules
|
||||
=========================
|
||||
|
||||
These are a set of modules for interacting with the OpenStack API as either an admin
|
||||
or an end user.
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
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:
|
||||
``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.
|
||||
|
||||
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.
|
||||
|
||||
Interoperability
|
||||
----------------
|
||||
|
||||
* It should be assumed that the cloud consumer does not know
|
||||
details about the deployment choices their cloud provider made. A best
|
||||
effort should be made to present one sane interface to the Ansible user
|
||||
regardless of deployer choices.
|
||||
* It should be assumed that a user may have more than one cloud account that
|
||||
they wish to combine as part of a single Ansible-managed infrastructure.
|
||||
* All modules should work appropriately against all existing versions of
|
||||
OpenStack regardless of upstream EOL status. The reason for this is that
|
||||
the Ansible modules are for consumers of cloud APIs who are not in a
|
||||
position to impact what version of OpenStack their cloud provider is
|
||||
running. It is known that there are OpenStack Public Clouds running rather
|
||||
old versions of OpenStack, but from a user point of view the Ansible
|
||||
modules can still support these users without impacting use of more
|
||||
modern versions.
|
||||
|
||||
Libraries
|
||||
---------
|
||||
|
||||
* All modules should use ``OpenStackModule`` from
|
||||
``ansible_collections.openstack.cloud.plugins.module_utils.openstack``
|
||||
as their base class.
|
||||
* All modules should include ``extends_documentation_fragment: openstack``.
|
||||
* 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
|
||||
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>`.
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
* Integration testing is currently done in `OpenStack's CI system
|
||||
<https://opendev.org/openstack/ansible-collections-openstack/src/branch/master/zuul.yaml>`
|
||||
125
docs/releasing.md
Normal file
125
docs/releasing.md
Normal file
@@ -0,0 +1,125 @@
|
||||
# Release process for Ansible OpenStack collection
|
||||
|
||||
## Publishing to Ansible Galaxy
|
||||
|
||||
1. Create entry in [changelog.yaml](../changelogs/changelog.yaml) with commits since last release.
|
||||
* Modules should be in a separate section `modules`
|
||||
* Bugfixes and minor changes in their sections
|
||||
2. Change version in [galaxy.yml](../galaxy.yml). Apply [Semantic Versioning](https://semver.org/):
|
||||
* Increase major version for breaking changes or modules were removed
|
||||
* Increase minor version when modules were added
|
||||
* Increase patch version for bugfixes
|
||||
3. Run `antsibull-changelog release` command (run `pip install antsibull` before) to generate [CHANGELOG.rst](
|
||||
../CHANGELOG.rst) and verify correctness of generated files.
|
||||
4. Commit changes to `changelog.yaml` and `galaxy.yml`, submit patch and wait until it has been merged
|
||||
5. Tag the release with version as it's described in [OpenStack docs](
|
||||
https://docs.opendev.org/opendev/infra-manual/latest/drivers.html#tagging-a-release):
|
||||
* [Make sure you have a valid GnuPG key pair](
|
||||
https://docs.github.com/en/authentication/managing-commit-signature-verification/generating-a-new-gpg-key)
|
||||
* `git checkout <your_branch>`
|
||||
* `git pull --ff-only`
|
||||
* `git tag -s <version number>` where `<version number>` is your tag
|
||||
* `git push gerrit <version number>`
|
||||
6. When your tag has been pushed in the previous step, our release job `ansible-collections-openstack-release`, defined
|
||||
in [galaxy.yml](../galaxy.yml), will run automatically and publish a new release with your tag to [Ansible Galaxy](
|
||||
https://galaxy.ansible.com/openstack/cloud). When it has finished, its status and logs can be accessed on [Zuul CI's
|
||||
builds page](https://zuul.opendev.org/t/openstack/builds?job_name=ansible-collections-openstack-release).
|
||||
7. When release job `ansible-collections-openstack-release` has failed, you can manually build the collection locally
|
||||
and publish your release to Ansible Galaxy:
|
||||
* `git checkout <version number>` where `<version number>` is your tag
|
||||
* Delete untracked files and directories with `git clean -n; git clean -fd`
|
||||
* Build collection with `ansible-galaxy`, for example:
|
||||
```sh
|
||||
ansible-galaxy collection build --force --output-path /path/to/collection/dir
|
||||
```
|
||||
* On success you will find a `*.tar.gz` file in `/path/to/collection/dir`, e.g. `openstack-cloud-1.5.0.tar.gz`
|
||||
* Go to [your content page on Ansible Galaxy](https://galaxy.ansible.com/my-content/namespaces), open namespace
|
||||
`openstack`, click on `Upload New Version` and upload your release `*.tar.gz`, e.g. `openstack-cloud-1.5.0.tar.gz`.
|
||||
Push collection tarballs to the `openstack.cloud` namespace requires membership in `openstack` namespace on Ansible
|
||||
Galaxy.
|
||||
* Instead of using Ansible Galaxy web interface, you could also upload your release from cli. For example:
|
||||
```sh
|
||||
ansible-galaxy collection publish --token $API_GALAXY_TOKEN -v /path/to/openstack-cloud-1.5.0.tar.gz
|
||||
```
|
||||
where `$API_GALAXY_TOKEN` is your API key from [Ansible Galaxy](https://galaxy.ansible.com/me/preferences).
|
||||
* [Monitor import progress on Ansible Galaxy](https://galaxy.ansible.com/my-imports/) and act accordingly to issues.
|
||||
8. Announce new release to [The Bullhorn](https://github.com/ansible/community/wiki/News#the-bullhorn): Join
|
||||
[Ansible Social room on Matrix](https://matrix.to/#/#social:ansible.com) and mention [newsbot](
|
||||
https://matrix.to/#/@newsbot:ansible.im) to have your news item tagged for review for the next issue!
|
||||
|
||||
## Publishing to Fedora
|
||||
|
||||
**NOTE:** Before publishing an updated RPM for Fedora or RDO, contact Alfredo Moralejo Alonso <amoralej@redhat.com>
|
||||
(amoralej) or Joel Capitao <jcapitao@redhat.com> (jcapitao[m]) in `#rdo` on [OFTC IRC](https://www.oftc.net/) about the
|
||||
latest release process.
|
||||
|
||||
**NOTE:** If your username is in Fedora's `admins` group, you can push your commit directly to Fedora's repository for
|
||||
Ansible OpenStack collection. Otherwise you will have to open pull requests to sent changes.
|
||||
|
||||
1. Get familiar with packaging for Fedora. Useful resources are:
|
||||
* [Fedora's Package Update Guide](https://docs.fedoraproject.org/en-US/package-maintainers/Package_Update_Guide/)
|
||||
* [Fedora package source for Ansible OpenStack collection](
|
||||
https://src.fedoraproject.org/rpms/ansible-collections-openstack)
|
||||
* [Koji page for `ansible-collections-openstack`](https://koji.fedoraproject.org/koji/packageinfo?packageID=33611)
|
||||
* [Bodhi's page `Create New Update`](https://bodhi.fedoraproject.org/updates/new)
|
||||
2. Install all necessary packaging tools, mainly `fedpkg`.
|
||||
3. Create a scratch space with `mkdir fedora-scm`.
|
||||
4. Fork Fedora repository [rpms/ansible-collections-openstack](
|
||||
https://src.fedoraproject.org/rpms/ansible-collections-openstack).
|
||||
5. Clone [rpms/ansible-collections-openstack](https://src.fedoraproject.org/rpms/ansible-collections-openstack) with
|
||||
`fedpkg clone rpms/ansible-collections-openstack`. Or clone your forked repository (something like
|
||||
`https://src.fedoraproject.org/fork/sshnaidm/rpms/ansible-collections-openstack`) with
|
||||
`fedpkg clone forks/sshnaidm/rpms/ansible-collections-openstack` where `sshnaidm` has to be replaced with your
|
||||
username.
|
||||
6. `cd ansible-collections-openstack` and go to branch `rawhide` with `fedpkg switch-branch rawhide`.
|
||||
7. Download new collection sources from Ansible Galaxy using
|
||||
`wget https://galaxy.ansible.com/download/openstack-cloud-<version_tag>.tar.gz` where `<version_tag>` is a your new
|
||||
version, e.g. `1.10.0`. Or run `spectool -g *.spec` *after* having changed the `*.spec` file in the next step.
|
||||
8. Bump version in `*.spec` file as in this [example for `1.9.4`](
|
||||
https://src.fedoraproject.org/rpms/ansible-collection-containers-podman/c/6dc5eb79a3aa082e062768993bed66675ff9d520):
|
||||
```diff
|
||||
+Version: <version-tag>
|
||||
+Release: 1%{?dist}
|
||||
```
|
||||
and add changelog, sort of:
|
||||
```diff
|
||||
+* Tue Jun 08 2021 Sagi Shnaidman <sshnaidm@redhat.com> - <version-tag>-1
|
||||
+- Bump to <version-tag>-1
|
||||
```
|
||||
9. Upload sources you downloaded before with `fedpkg new-sources <version-tag>.tar.gz`.
|
||||
10. Optionally check build with `fedpkg mockbuild`.
|
||||
11. Verify and commit updated `*.spec` file with:
|
||||
```sh
|
||||
fedpkg diff
|
||||
fedpkg lint # run linters against your changes
|
||||
fedpkg commit # with message such as 'Bumped Ansible OpenStack collection to <version-tag>'
|
||||
```
|
||||
12. Push changes for `rawhide` with `fedpkg push`.
|
||||
13. Ask Koji to build your package with `fedpkg build`.
|
||||
14. Optionally check [Koji's page for `ansible-collections-openstack`](
|
||||
https://koji.fedoraproject.org/koji/packageinfo?packageID=33611).
|
||||
15. Repeat release process for older Fedora branches such as Fedora 36 aka `f36`:
|
||||
```sh
|
||||
fedpkg switch-branch f36
|
||||
git merge rawhide
|
||||
fedpkg push
|
||||
fedpkg build
|
||||
fedpkg update # or use Bodhi's page "Create New Update" at https://bodhi.fedoraproject.org/updates/new
|
||||
```
|
||||
|
||||
## Publishing to RDO
|
||||
|
||||
**NOTE:** Before publishing an updated RPM for Fedora or RDO, contact Alfredo Moralejo Alonso <amoralej@redhat.com>
|
||||
(amoralej) or Joel Capitao <jcapitao@redhat.com> (jcapitao[m]) in `#rdo` on [OFTC IRC](https://www.oftc.net/) about the
|
||||
latest release process.
|
||||
|
||||
[All `master` branches on RDO trunk](https://trunk.rdoproject.org) consume code from the `master` branch of the Ansible
|
||||
OpenStack collection. Its RPM is (re)build whenever a new patch has been merged to the collection repository. Afterwards
|
||||
[it is promoted as any other TripleO components in `client` component CI](
|
||||
https://docs.openstack.org/tripleo-docs/latest/ci/stages-overview.html).
|
||||
|
||||
To update stable RDO branches such as [`CentOS 9 Zed`](https://trunk.rdoproject.org/centos9-zed/), patches have to be
|
||||
submitted to CentOS Cloud SIG repositories. In this case, create a patch for stable branches such as `wallaby-rdo`, and
|
||||
`ussuri-rdo` at [ansible-collections-openstack-distgit](
|
||||
https://github.com/rdo-packages/ansible-collections-openstack-distgit). [Example](
|
||||
https://review.rdoproject.org/r/c/openstack/ansible-collections-openstack-distgit/+/34282).
|
||||
66
docs/reviewing.md
Normal file
66
docs/reviewing.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# Reviews
|
||||
|
||||
How to do a review? What to look for when reviewing patches?
|
||||
|
||||
* Should functionality be implemented in Ansible modules or in openstacksdk? Ansible modules should only be "wrappers"
|
||||
for functionality in openstacksdk. Big code chunks are a good indicator that functionality should better be moved to
|
||||
openstacksdk.
|
||||
* For each function call(s) and code section which has been refactored, does the new code return the same results?
|
||||
Pay special attention whenever a function from openstacksdk's cloud layer has been replaced because those functions
|
||||
often have different semantics than functions of SDK's proxy layer.
|
||||
* Can API calls (to OpenStack API, not openstacksdk API) be reduced any further to improve performance?
|
||||
* Can calls to OpenStack API be tweaked to return less data?
|
||||
For example, listing calls such as `image.images()` or `network.networks()` provide filters to reduce the number of
|
||||
returned values.
|
||||
* Sanity check `argument_spec` and `module_kwargs`. Some modules try to be clever and add checks to fail early instead
|
||||
of letting `openstacksdk` or OpenStack API handle incompatible arguments.
|
||||
* Are `choices` in module attributes apropriate? Sometimes it makes sense to get rid of the choices because the choices
|
||||
are simply to narrow and might soon be outdated again.
|
||||
* Are `choices` in module attributes still valid? Module code might be written long ago and thus the choices might be
|
||||
horrible outdated.
|
||||
* Does a module use `name` as module options for resource names instead of e.g. `port` in `port` module? Rename those
|
||||
attributes to `name` to be consistent with other modules and with openstacksdk. When refactoring a module, then add
|
||||
the old attribute as an alias to keep backward compatibility.
|
||||
* Does the module have integration tests in `ci/roles`?
|
||||
* Is documentation in `DOCUMENTATION`, `RETURN` and `EXAMPLES` up to date?
|
||||
* Does `RETURN` list all values which are returned by the module?
|
||||
* Are descriptions, keys, names, types etc. in `RETURN` up to date and sorted?
|
||||
- For example, [`type: complex` often can be changed to `type: list` / `elements: dict`](
|
||||
https://docs.ansible.com/ansible/latest/dev_guide/developing_modules_documenting.html).
|
||||
- `returned: always, but can be null` often has to be changed to `returned: always, but can be empty` or shorter
|
||||
`returned: always`.
|
||||
- Are there any values in `RETURN` which are not returned by OpenStack SDK any longer?
|
||||
- Module return value documentation can be found in [OpenStack SDK docs](
|
||||
https://docs.openstack.org/openstacksdk/latest/), e.g. [Identity v3 API](
|
||||
https://docs.openstack.org/openstacksdk/latest/user/proxies/identity_v3.html).
|
||||
For more detailed descriptions on return values refer to [OpenStack API](https://docs.openstack.org/api-ref/).
|
||||
* Do integration tests have assertions of module's return values?
|
||||
* Does `RETURN` documentation and assertions in integration tests match?
|
||||
* Does `RETURN` documentation and `self.exit_json()` statements match?
|
||||
* Do all modules use `to_dict(computed=False)` before returning values?
|
||||
* Because `id` is already part of most resource dictionaries returned from modules, we can safely drop dedicated `id`
|
||||
attributes in `self.exit_json()` calls. We will not loose data and we break backward compatibility anyway.
|
||||
* Is `EXAMPLES` documentation up to date?
|
||||
When module arguments have been changed, examples have to be updated as well.
|
||||
* Do integration tests execute successfully in your local dev environment? \
|
||||
Example:
|
||||
```sh
|
||||
ansible-playbook -vvv ci/run-collection.yml \
|
||||
-e "sdk_version=1.0.0 cloud=devstack-admin cloud_alt=devstack-alt" \
|
||||
--tags floating_ip_info
|
||||
```
|
||||
* Does a patch remove any functionality or break backwards compatibility? The author must give a good explanation for
|
||||
both.
|
||||
- One valid reason is that a functionality has never worked before.
|
||||
- Not a valid reason for dropping functionality or backwards compatibility is that functions from openstacksdk's proxy
|
||||
layer do not support the functionality from openstacksdk's cloud layer. [SDK's cloud layer is not going away](
|
||||
https://meetings.opendev.org/irclogs/%23openstack-sdks/%23openstack-sdks.2022-04-27.log.html) and can be used for
|
||||
functionality which openstacksdk's proxy layer does not support. For example, `list_*` functions from openstacksdk's
|
||||
cloud layer such as `search_users()` allow to filter retrieved results with function parameter `filters`.
|
||||
openstacksdk's proxy layer does not provide an equivalent and thus the use of `search_users()` is perfectly fine.
|
||||
* Try to look at the patch from user perspective:
|
||||
- Will users understand and approve the change(s)?
|
||||
- Will the patch break their code?
|
||||
**Note**: For operators / administrators, a stable and reliable and bug free API is more important than the number
|
||||
of features.
|
||||
- If a change breaks or changes the behavior of their code, will it be easy to spot the difference?
|
||||
35
galaxy.yml
Normal file
35
galaxy.yml
Normal file
@@ -0,0 +1,35 @@
|
||||
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
|
||||
- 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,8 @@ build_ignore:
|
||||
- .zuul.yaml
|
||||
- .pytest_cache
|
||||
- importer_result.json
|
||||
- .tox
|
||||
- .env
|
||||
- .vscode
|
||||
- ansible_collections_openstack.egg-info
|
||||
- changelogs
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
requires_ansible: ">=2.8"
|
||||
action_groups:
|
||||
openstack:
|
||||
- address_scope
|
||||
- auth
|
||||
- baremetal_inspect
|
||||
- baremetal_inspect
|
||||
@@ -7,6 +9,9 @@ action_groups:
|
||||
- baremetal_node
|
||||
- baremetal_node_action
|
||||
- baremetal_node_action
|
||||
- baremetal_node_info
|
||||
- baremetal_port_info
|
||||
- baremetal_port
|
||||
- catalog_endpoint
|
||||
- catalog_service
|
||||
- catalog_service
|
||||
@@ -17,10 +22,12 @@ action_groups:
|
||||
- compute_flavor
|
||||
- compute_flavor_info
|
||||
- compute_flavor_info
|
||||
- compute_service_info
|
||||
- compute_service_info
|
||||
- config
|
||||
- config
|
||||
- dns_zone
|
||||
- dns_zone
|
||||
- dns_zone_info
|
||||
- endpoint
|
||||
- endpoint
|
||||
- federation_idp
|
||||
@@ -32,6 +39,7 @@ action_groups:
|
||||
- federation_mapping_info
|
||||
- federation_mapping_info
|
||||
- floating_ip
|
||||
- floating_ip_info
|
||||
- group_assignment
|
||||
- group_assignment
|
||||
- host_aggregate
|
||||
@@ -53,6 +61,7 @@ action_groups:
|
||||
- image
|
||||
- image_info
|
||||
- keypair
|
||||
- keypair_info
|
||||
- keystone_federation_protocol
|
||||
- keystone_federation_protocol_info
|
||||
- lb_listener
|
||||
@@ -65,6 +74,7 @@ action_groups:
|
||||
- network
|
||||
- networks_info
|
||||
- object
|
||||
- object_container
|
||||
- port
|
||||
- port_info
|
||||
- project
|
||||
@@ -77,7 +87,9 @@ action_groups:
|
||||
- router
|
||||
- routers_info
|
||||
- security_group
|
||||
- security_group_info
|
||||
- security_group_rule
|
||||
- security_group_rule_info
|
||||
- server
|
||||
- server_action
|
||||
- server_group
|
||||
@@ -87,9 +99,13 @@ action_groups:
|
||||
- stack
|
||||
- subnet
|
||||
- subnets_info
|
||||
- subnet_pool
|
||||
- volume
|
||||
- volume_backup
|
||||
- volume_backup_info
|
||||
- volume_info
|
||||
- volume_snapshot
|
||||
- volume_snapshot_info
|
||||
os:
|
||||
- auth
|
||||
- baremetal_inspect
|
||||
@@ -144,6 +160,7 @@ action_groups:
|
||||
- image
|
||||
- image_info
|
||||
- keypair
|
||||
- keypair_info
|
||||
- keystone_federation_protocol
|
||||
- keystone_federation_protocol_info
|
||||
- lb_listener
|
||||
@@ -156,6 +173,7 @@ action_groups:
|
||||
- network
|
||||
- networks_info
|
||||
- object
|
||||
- object_container
|
||||
- port
|
||||
- port_info
|
||||
- project
|
||||
@@ -168,7 +186,9 @@ action_groups:
|
||||
- router
|
||||
- routers_info
|
||||
- security_group
|
||||
- security_group_info
|
||||
- security_group_rule
|
||||
- security_group_rule_info
|
||||
- server
|
||||
- server_action
|
||||
- server_group
|
||||
@@ -179,8 +199,11 @@ action_groups:
|
||||
- subnet
|
||||
- subnets_info
|
||||
- volume
|
||||
- volume_backup
|
||||
- volume_backup_info
|
||||
- volume_info
|
||||
- volume_snapshot
|
||||
- volume_snapshot_info
|
||||
- os_auth
|
||||
- os_client_config
|
||||
- os_client_config
|
||||
|
||||
@@ -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
|
||||
- "python >= 3.6"
|
||||
- "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,11 +10,8 @@
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
name: openstack
|
||||
plugin_type: inventory
|
||||
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
|
||||
@@ -22,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.
|
||||
@@ -42,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
|
||||
@@ -50,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
|
||||
@@ -58,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: |
|
||||
@@ -74,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
|
||||
@@ -88,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:
|
||||
@@ -98,17 +105,22 @@ 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.36, < 0.99.0"
|
||||
extends_documentation_fragment:
|
||||
- inventory_cache
|
||||
- constructed
|
||||
|
||||
'''
|
||||
|
||||
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
|
||||
@@ -121,6 +133,9 @@ 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")
|
||||
@@ -155,13 +170,20 @@ 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)
|
||||
@@ -233,6 +255,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||
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 = []
|
||||
try:
|
||||
@@ -307,7 +330,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 = []
|
||||
@@ -355,14 +382,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):
|
||||
|
||||
|
||||
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']
|
||||
)
|
||||
@@ -29,7 +29,16 @@
|
||||
|
||||
import abc
|
||||
import copy
|
||||
from distutils.version import StrictVersion
|
||||
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
|
||||
|
||||
@@ -67,6 +76,42 @@ OVERRIDES = {'os_client_config': 'config',
|
||||
|
||||
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
|
||||
@@ -128,6 +173,9 @@ 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']),
|
||||
)
|
||||
# Filter out all our custom parameters before passing to AnsibleModule
|
||||
kwargs_copy = copy.deepcopy(kwargs)
|
||||
@@ -150,24 +198,20 @@ def openstack_module_kwargs(**kwargs):
|
||||
|
||||
|
||||
# for compatibility with old versions
|
||||
def openstack_cloud_from_module(module, min_version='0.12.0'):
|
||||
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:
|
||||
@@ -240,6 +284,8 @@ class OpenStackModule:
|
||||
deprecated_names = ()
|
||||
argument_spec = {}
|
||||
module_kwargs = {}
|
||||
module_min_sdk_version = None
|
||||
module_max_sdk_version = None
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize Openstack base class.
|
||||
@@ -252,12 +298,15 @@ class OpenStackModule:
|
||||
**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()
|
||||
|
||||
def log(self, msg):
|
||||
"""Prints log message to system log.
|
||||
@@ -277,6 +326,16 @@ class OpenStackModule:
|
||||
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.
|
||||
"""
|
||||
@@ -286,7 +345,7 @@ class OpenStackModule:
|
||||
"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.10')
|
||||
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
|
||||
@@ -295,11 +354,19 @@ class OpenStackModule:
|
||||
try:
|
||||
# Due to the name shadowing we should import other way
|
||||
sdk = importlib.import_module('openstack')
|
||||
sdk_version_lib = importlib.import_module('openstack.version')
|
||||
self.sdk_version = sdk_version_lib.__version__
|
||||
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:
|
||||
|
||||
197
plugins/modules/address_scope.py
Normal file
197
plugins/modules/address_scope.py
Normal file
@@ -0,0 +1,197 @@
|
||||
#!/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
|
||||
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()
|
||||
@@ -10,9 +10,6 @@ short_description: Retrieve an auth token
|
||||
author: OpenStack Ansible SIG
|
||||
description:
|
||||
- Retrieve an auth token from an OpenStack Cloud
|
||||
requirements:
|
||||
- "python >= 3.6"
|
||||
- "openstacksdk"
|
||||
extends_documentation_fragment:
|
||||
- openstack.cloud.openstack
|
||||
'''
|
||||
@@ -38,29 +35,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__':
|
||||
|
||||
@@ -36,11 +36,6 @@ options:
|
||||
- A timeout in seconds to tell the role to wait for the node to complete introspection if wait is set to True.
|
||||
default: 1200
|
||||
type: int
|
||||
|
||||
requirements:
|
||||
- "python >= 3.6"
|
||||
- "openstacksdk"
|
||||
|
||||
extends_documentation_fragment:
|
||||
- openstack.cloud.openstack
|
||||
'''
|
||||
@@ -75,10 +70,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,37 +89,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', 'none']
|
||||
and module.params['ironic_url'] is None
|
||||
and not module.params['cloud']
|
||||
and not (module.params['auth']
|
||||
and module.params['auth'].get('endpoint'))
|
||||
):
|
||||
module.fail_json(msg="Authentication appears to be disabled, "
|
||||
"Please define either ironic_url, or cloud, "
|
||||
"or auth.endpoint")
|
||||
|
||||
if (
|
||||
module.params['ironic_url']
|
||||
and module.params['auth_type'] in [None, 'None', 'none']
|
||||
and not (module.params['auth']
|
||||
and module.params['auth'].get('endpoint'))
|
||||
):
|
||||
module.params['auth'] = dict(
|
||||
endpoint=module.params['ironic_url']
|
||||
)
|
||||
module = IronicModule(argument_spec, **module_kwargs)
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
|
||||
@@ -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"'
|
||||
@@ -81,6 +123,7 @@ options:
|
||||
description:
|
||||
- Definition of the physical characteristics of this server, used for scheduling purposes
|
||||
type: dict
|
||||
default: {}
|
||||
suboptions:
|
||||
cpu_arch:
|
||||
description:
|
||||
@@ -120,14 +163,10 @@ options:
|
||||
re-assert the password field.
|
||||
- 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
|
||||
requirements:
|
||||
- "python >= 3.6"
|
||||
- "openstacksdk"
|
||||
- "jsonpatch"
|
||||
|
||||
extends_documentation_fragment:
|
||||
- openstack.cloud.openstack
|
||||
'''
|
||||
@@ -150,10 +189,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"
|
||||
|
||||
'''
|
||||
@@ -164,37 +202,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
|
||||
|
||||
|
||||
@@ -225,48 +272,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.0.0')]
|
||||
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', 'none']
|
||||
and module.params['ironic_url'] is None
|
||||
and not module.params['cloud']
|
||||
and not (module.params['auth']
|
||||
and module.params['auth'].get('endpoint'))
|
||||
):
|
||||
module.fail_json(msg="Authentication appears to be disabled, "
|
||||
"Please define either ironic_url, or cloud, "
|
||||
"or auth.endpoint")
|
||||
|
||||
if (
|
||||
module.params['ironic_url']
|
||||
and module.params['auth_type'] in [None, 'None', 'none']
|
||||
and not (module.params['auth']
|
||||
and module.params['auth'].get('endpoint'))
|
||||
):
|
||||
module.params['auth'] = dict(
|
||||
endpoint=module.params['ironic_url']
|
||||
)
|
||||
|
||||
node_id = _choose_id_value(module)
|
||||
|
||||
@@ -286,6 +328,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']
|
||||
|
||||
@@ -91,10 +91,6 @@ options:
|
||||
wait for the node activation or deactivation to complete.
|
||||
default: 1800
|
||||
type: int
|
||||
requirements:
|
||||
- "python >= 3.6"
|
||||
- "openstacksdk"
|
||||
|
||||
extends_documentation_fragment:
|
||||
- openstack.cloud.openstack
|
||||
'''
|
||||
@@ -132,10 +128,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 +228,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,28 +242,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', 'none']
|
||||
and module.params['ironic_url'] is None
|
||||
and not module.params['cloud']
|
||||
and not (module.params['auth']
|
||||
and module.params['auth'].get('endpoint'))
|
||||
):
|
||||
module.fail_json(msg="Authentication appears to be disabled, "
|
||||
"Please define either ironic_url, or cloud, "
|
||||
"or auth.endpoint")
|
||||
|
||||
if (
|
||||
module.params['ironic_url']
|
||||
and module.params['auth_type'] in [None, 'None', 'none']
|
||||
and not (module.params['auth']
|
||||
and module.params['auth'].get('endpoint'))
|
||||
):
|
||||
module.params['auth'] = dict(
|
||||
endpoint=module.params['ironic_url']
|
||||
)
|
||||
module = IronicModule(argument_spec, **module_kwargs)
|
||||
|
||||
if (
|
||||
module.params['config_drive']
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user