mirror of
https://opendev.org/openstack/ansible-collections-openstack.git
synced 2026-03-27 14:03:03 +00:00
Compare commits
332 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1ce7dd8b5f | ||
|
|
438bbea34b | ||
|
|
e065818024 | ||
|
|
0764e671a9 | ||
|
|
5f4db3583e | ||
|
|
6262474c94 | ||
|
|
f9fcd35018 | ||
|
|
5dbf47cb49 | ||
|
|
57c63e7918 | ||
|
|
ed5829d462 | ||
|
|
b025e7c356 | ||
|
|
782340833e | ||
|
|
73aab9e80c | ||
|
|
ae7e8260a3 | ||
|
|
030df96dc0 | ||
|
|
c5d0d3ec82 | ||
|
|
0cff7eb3a2 | ||
|
|
29e3f3dac8 | ||
|
|
d18ea87091 | ||
|
|
529c1e8dcc | ||
|
|
99b7af529c | ||
|
|
2ed3ffe1d0 | ||
|
|
ae5dbf0fc0 | ||
|
|
4074db1bd0 | ||
|
|
3248ba9960 | ||
|
|
2d5ca42629 | ||
|
|
83456005fc | ||
|
|
5b61019a34 | ||
|
|
630dac3787 | ||
|
|
54c2257376 | ||
|
|
c843feb338 | ||
|
|
28541ee158 | ||
|
|
c09029ada0 | ||
|
|
903eeb7db7 | ||
|
|
03ebbaed93 | ||
|
|
8d9b8b9a35 | ||
|
|
fef5e127d4 | ||
|
|
01d3011895 | ||
|
|
d4f25d2282 | ||
|
|
3df5c38ca6 | ||
|
|
474b3804eb | ||
|
|
5a8ad4cdf0 | ||
|
|
e742016861 | ||
|
|
40a384214c | ||
|
|
1188af2486 | ||
|
|
e42e21f621 | ||
|
|
e6379e3038 | ||
|
|
e0dc4776bb | ||
|
|
22941e86d1 | ||
|
|
b089d56136 | ||
|
|
536fe731f7 | ||
|
|
4a8214b196 | ||
|
|
d1b77a3546 | ||
|
|
8aefe5dc3a | ||
|
|
217e965357 | ||
|
|
94afde008b | ||
|
|
032a5222c1 | ||
|
|
fa6eb547ab | ||
|
|
23290a568b | ||
|
|
69801f268f | ||
|
|
0c6aee5378 | ||
|
|
fb258ababa | ||
|
|
4c186a2ae6 | ||
|
|
598cc2d743 | ||
|
|
e0139fe940 | ||
|
|
bc65d42f52 | ||
|
|
ac4d105813 | ||
|
|
747c4d23bc | ||
|
|
93d51498e9 | ||
|
|
cfd2d1f773 | ||
|
|
e009f80ffc | ||
|
|
08c93cf9b1 | ||
|
|
fff978d273 | ||
|
|
9fb544d94a | ||
|
|
94ed95c8b6 | ||
|
|
4ab054790c | ||
|
|
2c68080758 | ||
|
|
6e680d594b | ||
|
|
b25e93dbdd | ||
|
|
0aedc268f1 | ||
|
|
9b47cb4b59 | ||
|
|
8612171af3 | ||
|
|
8f321eaeb2 | ||
|
|
147ad6c452 | ||
|
|
407369da6e | ||
|
|
0a371445eb | ||
|
|
2808d1c155 | ||
|
|
c30e4db77c | ||
|
|
ab6f2e45c6 | ||
|
|
568adcb890 | ||
|
|
18cf839db4 | ||
|
|
454a05452b | ||
|
|
ad9594dcd7 | ||
|
|
62c0169e64 | ||
|
|
497f020100 | ||
|
|
92c3e87467 | ||
|
|
f73a0e385e | ||
|
|
b6b5f63877 | ||
|
|
edd4e1b2e9 | ||
|
|
01e1742acf | ||
|
|
5b77519b89 | ||
|
|
19d1d41ee0 | ||
|
|
f758dfa626 | ||
|
|
34017d511b | ||
|
|
70c029fa50 | ||
|
|
d5ab2bf33f | ||
|
|
754ae5e50d | ||
|
|
546f24940f | ||
|
|
f507465c9e | ||
|
|
90b110794f | ||
|
|
c9afdbfd73 | ||
|
|
4a27306440 | ||
|
|
8534990840 | ||
|
|
16a8a9e5d4 | ||
|
|
a4a6e6d4ec | ||
|
|
778cf14f1b | ||
|
|
1b38b7c500 | ||
|
|
a46bbd0d48 | ||
|
|
39ffebea4c | ||
|
|
cc9ca5a34b | ||
|
|
1f8c9fee05 | ||
|
|
0c75f19e4c | ||
|
|
e34f259566 | ||
|
|
5aaa41c9c4 | ||
|
|
eaa26c6b9c | ||
|
|
0071fdcd97 | ||
|
|
124e174d27 | ||
|
|
4dc6c421db | ||
|
|
4cf6842222 | ||
|
|
647ffef375 | ||
|
|
97c4531d15 | ||
|
|
407b50c8b2 | ||
|
|
122afc170c | ||
|
|
52e7bfe7a4 | ||
|
|
7d9de2858a | ||
|
|
852d971d50 | ||
|
|
3b0ae6c43f | ||
|
|
7945d7f01a | ||
|
|
85fa2bb2b6 | ||
|
|
133af96666 | ||
|
|
51f1fea8b3 | ||
|
|
94c150b2e7 | ||
|
|
6b911ebd21 | ||
|
|
cec58d7560 | ||
|
|
0e07b15f92 | ||
|
|
7c536e69b3 | ||
|
|
1ca6f208f7 | ||
|
|
00ec3f1c92 | ||
|
|
0f37ed795b | ||
|
|
daf79de37e | ||
|
|
961bdb5bd5 | ||
|
|
d3c5ddd40f | ||
|
|
114bc855c0 | ||
|
|
5862d91615 | ||
|
|
4fe73c978a | ||
|
|
cd002a5555 | ||
|
|
d0ac32eefd | ||
|
|
d07778c24a | ||
|
|
a8f6dbd904 | ||
|
|
b3c2e8f1ce | ||
|
|
8c889f8eb3 | ||
|
|
764a8bff64 | ||
|
|
e9cd9bff2a | ||
|
|
8955110586 | ||
|
|
a180f339a8 | ||
|
|
53da712635 | ||
|
|
1e27b6b69c | ||
|
|
65ac75b518 | ||
|
|
2f87448567 | ||
|
|
4e1718db49 | ||
|
|
97fa59bf6f | ||
|
|
c13fac3796 | ||
|
|
99074ccd12 | ||
|
|
65a7e74b2b | ||
|
|
902b2f8147 | ||
|
|
f51898bd2f | ||
|
|
7bad5cfd42 | ||
|
|
34b0abb4ca | ||
|
|
0ade33eb6f | ||
|
|
ed36d82a0c | ||
|
|
41299b9666 | ||
|
|
a660a35d86 | ||
|
|
f0cb7f6802 | ||
|
|
6ab3d76696 | ||
|
|
40d913d2a6 | ||
|
|
41f3007a80 | ||
|
|
b416a3e242 | ||
|
|
ebaa1ac357 | ||
|
|
57cc3e6aad | ||
|
|
9f3f0837c8 | ||
|
|
8a80113d54 | ||
|
|
ffa84bd705 | ||
|
|
c0bc0b0796 | ||
|
|
fb0fb529b7 | ||
|
|
2d0656f072 | ||
|
|
515cc66287 | ||
|
|
73827a3d57 | ||
|
|
f2bf56d984 | ||
|
|
6d8c965333 | ||
|
|
81a81ad759 | ||
|
|
b99218c143 | ||
|
|
d47cf4333c | ||
|
|
8563e2327c | ||
|
|
4df7a12ebf | ||
|
|
0ec16fbecc | ||
|
|
5e7c29d97e | ||
|
|
d0eb83e934 | ||
|
|
ce6193cd2f | ||
|
|
fdc67892e3 | ||
|
|
d2eb98d048 | ||
|
|
1bf22feb2d | ||
|
|
ac401bb354 | ||
|
|
3fdbd56a58 | ||
|
|
0b2b56765c | ||
|
|
ccbbc319ce | ||
|
|
0215e2a5d4 | ||
|
|
ceae5c1030 | ||
|
|
2d60a045a6 | ||
|
|
b87ae7dcce | ||
|
|
fd15087c4d | ||
|
|
960e5df17f | ||
|
|
bae75b84bd | ||
|
|
eda2e301c3 | ||
|
|
b250b76c33 | ||
|
|
fc2dda1d86 | ||
|
|
1f5a2019a0 | ||
|
|
7ec8e4d087 | ||
|
|
070e77feca | ||
|
|
a120db2d60 | ||
|
|
96be88af21 | ||
|
|
d600284645 | ||
|
|
0e675a9129 | ||
|
|
19cd6262cf | ||
|
|
e0958c605e | ||
|
|
aa19d74cde | ||
|
|
2419b5ab19 | ||
|
|
caf1bc49da | ||
|
|
ad3a3a89f2 | ||
|
|
c6c1c6a070 | ||
|
|
bcca2efe1a | ||
|
|
802e46d554 | ||
|
|
160d0dea4d | ||
|
|
8f27184f30 | ||
|
|
9b62cd7734 | ||
|
|
595f7d1093 | ||
|
|
86b573883a | ||
|
|
c54b34db3f | ||
|
|
6767db64c2 | ||
|
|
452404ee87 | ||
|
|
8d5195fdf2 | ||
|
|
7c7e61d36b | ||
|
|
9272146cf7 | ||
|
|
a9fa496ebe | ||
|
|
d6cdad2c42 | ||
|
|
d65ea4d560 | ||
|
|
4ea2c5b50d | ||
|
|
97b05533f1 | ||
|
|
dee39a71b6 | ||
|
|
1b59c19a24 | ||
|
|
4bfa135b20 | ||
|
|
c7ae7a5f98 | ||
|
|
4db7a6238b | ||
|
|
a6805cd019 | ||
|
|
80ef209336 | ||
|
|
c1a9794207 | ||
|
|
1d22a94a90 | ||
|
|
fdf4999747 | ||
|
|
b31fdf8320 | ||
|
|
fd1b9fc0d2 | ||
|
|
a8589e9f4d | ||
|
|
2df07f3523 | ||
|
|
c83e0e39b1 | ||
|
|
92566dedae | ||
|
|
cc1b5ecae8 | ||
|
|
4a7330364e | ||
|
|
cf5007d478 | ||
|
|
c10cc9dd8c | ||
|
|
3ead86904a | ||
|
|
9f60f0f26d | ||
|
|
e85a0b809a | ||
|
|
bba1da17c9 | ||
|
|
bc6622e0e7 | ||
|
|
e869564e3c | ||
|
|
0c6e8bed69 | ||
|
|
5a43bdb873 | ||
|
|
bb25330ddc | ||
|
|
ecf4897a55 | ||
|
|
f09cccdb9e | ||
|
|
2bf82c2669 | ||
|
|
5fc8fca06b | ||
|
|
411c2ddc8c | ||
|
|
41ad425d23 | ||
|
|
c075126ebd | ||
|
|
1ec9afe2ca | ||
|
|
ffa826c0d0 | ||
|
|
4c3dfec59d | ||
|
|
453601bde2 | ||
|
|
bf2c20f590 | ||
|
|
a03dd05465 | ||
|
|
b376e3e146 | ||
|
|
938abd0d84 | ||
|
|
749f04bcfb | ||
|
|
27e113780f | ||
|
|
19b05f689c | ||
|
|
d44915caba | ||
|
|
e2ee2d0f5d | ||
|
|
771fb68f99 | ||
|
|
c6892c83c9 | ||
|
|
5b53433348 | ||
|
|
7b26b82890 | ||
|
|
e28ab9acec | ||
|
|
cc604d354c | ||
|
|
7820d9ca60 | ||
|
|
aae539ac8c | ||
|
|
5f1ffe2b99 | ||
|
|
a162a02536 | ||
|
|
2e89bbe609 | ||
|
|
187a578842 | ||
|
|
61e20bb945 | ||
|
|
879270aa47 | ||
|
|
5bc179a978 | ||
|
|
8147294a7a | ||
|
|
002e55e269 | ||
|
|
52246bb610 | ||
|
|
99e2e2cee6 | ||
|
|
b640e6207c | ||
|
|
ea2ee76a88 | ||
|
|
9d0e5dd1db | ||
|
|
08bbadedb0 | ||
|
|
3c7a8f39a2 | ||
|
|
aa22867536 | ||
|
|
37a51ec6ad |
627
.zuul.yaml
627
.zuul.yaml
@@ -1,9 +1,16 @@
|
||||
# yamllint disable
|
||||
---
|
||||
# Keep this file 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.
|
||||
# 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-base
|
||||
parent: openstacksdk-functional-devstack
|
||||
@@ -29,11 +36,10 @@
|
||||
- .*\.rst
|
||||
- tools/run-ansible-sanity.sh
|
||||
- tests/sanity/.*
|
||||
- contrib/.*
|
||||
- .zuul.yaml
|
||||
vars:
|
||||
zuul_work_dir: src/opendev.org/openstack/ansible-collections-openstack
|
||||
tox_envlist: ansible
|
||||
tox_envlist: ansible_latest
|
||||
tox_install_siblings: true
|
||||
fetch_subunit: false
|
||||
devstack_plugins:
|
||||
@@ -41,6 +47,7 @@
|
||||
devstack_services:
|
||||
designate: true
|
||||
neutron-dns: true
|
||||
neutron-trunk: true
|
||||
zuul_copy_output:
|
||||
'{{ devstack_log_dir }}/test_output.log': 'logs'
|
||||
extensions_to_txt:
|
||||
@@ -54,6 +61,49 @@
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using master of openstacksdk with latest ansible release
|
||||
|
||||
- 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
|
||||
@@ -61,7 +111,6 @@
|
||||
# parent job variant during job freeze when child jobs are on other branches.
|
||||
description: |
|
||||
Run openstack collections functional tests against a devstack with Octavia plugin enabled
|
||||
pre-run: ci/playbooks/get_amphora_tarball.yaml
|
||||
# Do not set job.override-checkout or job.required-projects.override-checkout in base job because
|
||||
# else Zuul will use this branch when matching variants for parent jobs during job freeze
|
||||
required-projects:
|
||||
@@ -74,23 +123,25 @@
|
||||
- ^plugins/modules/lb_pool.py
|
||||
- ^plugins/modules/loadbalancer.py
|
||||
vars:
|
||||
configure_swap_size: 8192
|
||||
tox_install_siblings: false
|
||||
configure_swap_size: 4096
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$OCTAVIA_CONF:
|
||||
controller_worker:
|
||||
amphora_driver: amphora_noop_driver
|
||||
devstack_plugins:
|
||||
designate: https://opendev.org/openstack/designate
|
||||
octavia: https://opendev.org/openstack/octavia
|
||||
devstack_services:
|
||||
designate: true
|
||||
neutron-dns: true
|
||||
octavia: true
|
||||
o-api: true
|
||||
o-cw: true
|
||||
o-hk: true
|
||||
o-hm: true
|
||||
devstack_localrc:
|
||||
OCTAVIA_AMP_IMAGE_FILE: "/tmp/test-only-amphora-x64-haproxy-ubuntu-bionic.qcow2"
|
||||
OCTAVIA_AMP_IMAGE_SIZE: 3
|
||||
OCTAVIA_AMP_IMAGE_NAME: "test-only-amphora-x64-haproxy-ubuntu-bionic"
|
||||
o-hk: true
|
||||
neutron-dns: true
|
||||
tox_extra_args: -vv --skip-missing-interpreters=false -- loadbalancer
|
||||
tox_install_siblings: false
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-octavia
|
||||
@@ -101,24 +152,6 @@
|
||||
with Octavia plugin enabled, using latest releases of openstacksdk
|
||||
and latest ansible release. Run it only on Load Balancer changes.
|
||||
|
||||
- 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-base
|
||||
@@ -126,333 +159,41 @@
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using latest releases of openstacksdk and latest ansible release
|
||||
# OpenStack SDK 1.*.* has not been released to PyPI yet
|
||||
voting: false
|
||||
vars:
|
||||
# Uncomment once OpenStack SDK 1.*.* has been released to PyPI
|
||||
# tox_constraints_file: '{{ ansible_user_dir }}/{{ zuul.project.src_dir }}/tests/constraints-openstacksdk-1.x.x.txt'
|
||||
tox_constraints_file: '{{ ansible_user_dir }}/{{ zuul.project.src_dir }}/tests/constraints-openstacksdk-1.x.x.txt'
|
||||
tox_install_siblings: false
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-releases
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
branches: stable/1.0.0
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using 0.*.* releases of openstacksdk and latest ansible release
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.9
|
||||
- # Choose parent devstack job from master branch instead of non-existing stable/1.0.0 branch
|
||||
name: openstack/devstack
|
||||
override-checkout: master
|
||||
- # Choose parent devstack job from master branch instead of non-existing stable/1.0.0 branch
|
||||
name: openstack/openstacksdk
|
||||
override-checkout: master
|
||||
vars:
|
||||
tox_constraints_file: '{{ ansible_user_dir }}/{{ zuul.project.src_dir }}/tests/constraints-openstacksdk-0.x.x.txt'
|
||||
tox_install_siblings: false
|
||||
|
||||
# Job with Ansible 2.9 for checking backward compatibility
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-2.9
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-2.18
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
branches: master
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using master of openstacksdk and stable 2.9 branch of ansible
|
||||
voting: false
|
||||
using master of openstacksdk and stable 2.16 branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.9
|
||||
override-checkout: stable-2.18
|
||||
vars:
|
||||
tox_envlist: ansible-2.9
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-2.9
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
branches: stable/1.0.0
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using 0.*.* releases of openstacksdk and stable 2.9 branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.9
|
||||
- # Choose parent devstack job from master branch instead of non-existing stable/1.0.0 branch
|
||||
name: openstack/devstack
|
||||
override-checkout: master
|
||||
- name: openstack/openstacksdk
|
||||
# Yoga has the latest SDK release of the 0.*.* series atm
|
||||
override-checkout: stable/yoga
|
||||
vars:
|
||||
tox_envlist: ansible-2.9
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-2.11
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
branches: master
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using master of openstacksdk and stable 2.12 branch of ansible
|
||||
voting: false
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.11
|
||||
vars:
|
||||
tox_envlist: ansible-2.11
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-2.11
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
branches: stable/1.0.0
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using 0.*.* releases of openstacksdk and stable 2.12 branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.11
|
||||
- # Choose parent devstack job from master branch instead of non-existing stable/1.0.0 branch
|
||||
name: openstack/devstack
|
||||
override-checkout: master
|
||||
- name: openstack/openstacksdk
|
||||
# Yoga has the latest SDK release of the 0.*.* series atm
|
||||
override-checkout: stable/yoga
|
||||
vars:
|
||||
tox_envlist: ansible-2.11
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-2.12
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
branches: master
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using master of openstacksdk and stable 2.12 branch of ansible
|
||||
voting: false
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.12
|
||||
vars:
|
||||
tox_envlist: ansible-2.12
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-2.12
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
branches: stable/1.0.0
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using 0.*.* releases of openstacksdk and stable 2.12 branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.12
|
||||
- # Choose parent devstack job from master branch instead of non-existing stable/1.0.0 branch
|
||||
name: openstack/devstack
|
||||
override-checkout: master
|
||||
- name: openstack/openstacksdk
|
||||
# Yoga has the latest SDK release of the 0.*.* series atm
|
||||
override-checkout: stable/yoga
|
||||
vars:
|
||||
tox_envlist: ansible-2.12
|
||||
tox_envlist: ansible_2_18
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
nodeset: openstack-single-node-jammy
|
||||
branches: master
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using master of openstacksdk and devel branch of ansible
|
||||
# non-voting because we can't prevent ansible devel from breaking us
|
||||
voting: false
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: devel
|
||||
|
||||
# Stable branches tests
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-xena-ansible-2.12
|
||||
# Do not inherit from any parent job which does not run for branch stable/1.0.0 because Zuul would dismiss this job
|
||||
# when collecting parent job variants. For example, when job.branches is set to master in a parent job, then Zuul
|
||||
# will not match that job when it collects job variants.
|
||||
#
|
||||
# Do not inherit from any parent job which sets job.required-projects.override-checkout on openstack/devstack
|
||||
# because Zuul would use that git ref instead of stable branch defined below to checkout projects of parent devstack
|
||||
# jobs when collecting variants for parent jobs.
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
description: |
|
||||
Run openstack collections functional tests against a xena devstack
|
||||
using xena branch of openstacksdk and stable 2.12 branch of ansible
|
||||
branches: stable/1.0.0
|
||||
override-checkout: stable/xena
|
||||
# job.override-checkout will not override job.required-projects.override-checkout in parent jobs
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.12
|
||||
- # Choose parent devstack job from stable/1.0.0 branch instead of non-existing stable/xena branch
|
||||
name: openstack/ansible-collections-openstack
|
||||
override-checkout: stable/1.0.0
|
||||
- # Choose parent devstack job from stable/xena branch
|
||||
name: openstack/devstack
|
||||
override-checkout: stable/xena
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/xena
|
||||
vars:
|
||||
tox_envlist: ansible-2.12
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-wallaby-ansible-2.12
|
||||
# Do not inherit from any parent job which does not run for branch stable/1.0.0 because Zuul would dismiss this job
|
||||
# when collecting parent job variants. For example, when job.branches is set to master in a parent job, then Zuul
|
||||
# will not match that job when it collects job variants.
|
||||
#
|
||||
# Do not inherit from any parent job which sets job.required-projects.override-checkout on openstack/devstack
|
||||
# because Zuul would use that git ref instead of stable branch defined below to checkout projects of parent devstack
|
||||
# jobs when collecting variants for parent jobs.
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
description: |
|
||||
Run openstack collections functional tests against a wallaby devstack
|
||||
using wallaby branch of openstacksdk and stable 2.12 branch of ansible
|
||||
branches: stable/1.0.0
|
||||
override-checkout: stable/wallaby
|
||||
# job.override-checkout will not override job.required-projects.override-checkout in parent jobs
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.12
|
||||
- # Choose parent devstack job from stable/1.0.0 branch instead of non-existing stable/wallaby branch
|
||||
name: openstack/ansible-collections-openstack
|
||||
override-checkout: stable/1.0.0
|
||||
- # Choose parent devstack job from stable/wallaby branch
|
||||
name: openstack/devstack
|
||||
override-checkout: stable/wallaby
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/wallaby
|
||||
vars:
|
||||
tox_envlist: ansible-2.12
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-victoria-ansible-2.12
|
||||
# Do not inherit from any parent job which does not run for branch stable/1.0.0 because Zuul would dismiss this job
|
||||
# when collecting parent job variants. For example, when job.branches is set to master in a parent job, then Zuul
|
||||
# will not match that job when it collects job variants.
|
||||
#
|
||||
# Do not inherit from any parent job which sets job.required-projects.override-checkout on openstack/devstack
|
||||
# because Zuul would use that git ref instead of stable branch defined below to checkout projects of parent devstack
|
||||
# jobs when collecting variants for parent jobs.
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
description: |
|
||||
Run openstack collections functional tests against a victoria devstack
|
||||
using victoria branch of openstacksdk and stable 2.12 branch of ansible
|
||||
branches: stable/1.0.0
|
||||
override-checkout: stable/victoria
|
||||
# job.override-checkout will not override job.required-projects.override-checkout in parent jobs
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.12
|
||||
- # Choose parent devstack job from stable/1.0.0 branch instead of non-existing stable/victoria branch
|
||||
name: openstack/ansible-collections-openstack
|
||||
override-checkout: stable/1.0.0
|
||||
- # Choose parent devstack job from stable/victoria branch
|
||||
name: openstack/devstack
|
||||
override-checkout: stable/victoria
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/victoria
|
||||
vars:
|
||||
tox_envlist: ansible-2.12
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ussuri-ansible-2.11
|
||||
# Do not inherit from any parent job which does not run for branch stable/1.0.0 because Zuul would dismiss this job
|
||||
# when collecting parent job variants. For example, when job.branches is set to master in a parent job, then Zuul
|
||||
# will not match that job when it collects job variants.
|
||||
#
|
||||
# Do not inherit from any parent job which sets job.required-projects.override-checkout on openstack/devstack
|
||||
# because Zuul would use that git ref instead of stable branch defined below to checkout projects of parent devstack
|
||||
# jobs when collecting variants for parent jobs.
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
description: |
|
||||
Run openstack collections functional tests against a ussuri devstack
|
||||
using ussuri branch of openstacksdk and stable 2.11 branch of ansible
|
||||
branches: stable/1.0.0
|
||||
override-checkout: stable/ussuri
|
||||
# job.override-checkout will not override job.required-projects.override-checkout in parent jobs
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.11
|
||||
- # Choose parent devstack job from stable/1.0.0 branch instead of non-existing stable/ussuri branch
|
||||
name: openstack/ansible-collections-openstack
|
||||
override-checkout: stable/1.0.0
|
||||
- # Choose parent devstack job from stable/ussuri branch
|
||||
name: openstack/devstack
|
||||
override-checkout: stable/ussuri
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/ussuri
|
||||
vars:
|
||||
tox_envlist: ansible-2.11
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-train-ansible-2.11
|
||||
# Do not inherit from any parent job which does not run for branch stable/1.0.0 because Zuul would dismiss this job
|
||||
# when collecting parent job variants. For example, when job.branches is set to master in a parent job, then Zuul
|
||||
# will not match that job when it collects job variants.
|
||||
#
|
||||
# Do not inherit from any parent job which sets job.required-projects.override-checkout on openstack/devstack
|
||||
# because Zuul would use that git ref instead of stable branch defined below to checkout projects of parent devstack
|
||||
# jobs when collecting variants for parent jobs.
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
description: |
|
||||
Run openstack collections functional tests against a train devstack
|
||||
using train branch of openstacksdk and stable 2.11 branch of ansible
|
||||
branches: stable/1.0.0
|
||||
override-checkout: stable/train
|
||||
# job.override-checkout will not override job.required-projects.override-checkout in parent jobs
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.11
|
||||
- # Choose parent devstack job from stable/1.0.0 branch instead of non-existing stable/train branch
|
||||
name: openstack/ansible-collections-openstack
|
||||
override-checkout: stable/1.0.0
|
||||
- # Choose parent devstack job from stable/train branch
|
||||
name: openstack/devstack
|
||||
override-checkout: stable/train
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/train
|
||||
vars:
|
||||
tox_envlist: ansible-2.11
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-queens-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 queens devstack
|
||||
using train branch of openstacksdk and stable 2.11 branch of ansible
|
||||
branches: stable/1.0.0
|
||||
override-checkout: stable/queens
|
||||
# job.override-checkout will not override job.required-projects.override-checkout in parent jobs
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.11
|
||||
- # Choose parent devstack job from stable/1.0.0 branch instead of non-existing stable/queens branch
|
||||
name: openstack/ansible-collections-openstack
|
||||
override-checkout: stable/1.0.0
|
||||
- # Choose parent devstack job from stable/queens branch
|
||||
name: openstack/devstack
|
||||
override-checkout: stable/queens
|
||||
- name: openstack/openstacksdk
|
||||
# Run queens with highest possible py2 version of SDK
|
||||
override-checkout: stable/train
|
||||
vars:
|
||||
tox_envlist: ansible-2.11
|
||||
|
||||
# Linters
|
||||
- job:
|
||||
name: openstack-tox-linters-ansible
|
||||
parent: openstack-tox-linters
|
||||
nodeset: ubuntu-focal
|
||||
description: |
|
||||
Run openstack collections linter tests using the devel branch of ansible
|
||||
required-projects:
|
||||
@@ -461,144 +202,61 @@
|
||||
vars:
|
||||
# override tox_constraints_file from parent job
|
||||
tox_constraints_file: '{{ ansible_user_dir }}/{{ zuul.project.src_dir }}/tests/constraints-none.txt'
|
||||
tox_envlist: linters
|
||||
tox_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
|
||||
vars:
|
||||
python_version: 3.8
|
||||
bindep_profile: test py38
|
||||
python_version: '3.10'
|
||||
bindep_profile: test py310
|
||||
|
||||
- job:
|
||||
name: openstack-tox-linters-ansible-2.12
|
||||
name: openstack-tox-linters-ansible-2.18
|
||||
parent: openstack-tox-linters-ansible
|
||||
description: |
|
||||
Run openstack collections linter tests using the 2.12 branch of ansible
|
||||
Run openstack collections linter tests using the 2.18 branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.12
|
||||
override-checkout: stable-2.18
|
||||
vars:
|
||||
tox_envlist: linters-2.12
|
||||
python_version: 3.8
|
||||
bindep_profile: test py38
|
||||
|
||||
- job:
|
||||
name: openstack-tox-linters-ansible-2.9
|
||||
parent: openstack-tox-linters-ansible
|
||||
nodeset: ubuntu-bionic
|
||||
description: |
|
||||
Run openstack collections linter tests using the 2.9 branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.9
|
||||
vars:
|
||||
tox_envlist: linters-2.9
|
||||
tox_envlist: linters_2_18
|
||||
python_version: "3.12"
|
||||
bindep_profile: test py312
|
||||
|
||||
# Cross-checks with other projects
|
||||
- job:
|
||||
name: bifrost-collections-src
|
||||
parent: bifrost-integration-tinyipa-ubuntu-focal
|
||||
parent: bifrost-integration-tinyipa-ubuntu-jammy
|
||||
required-projects:
|
||||
- openstack/ansible-collections-openstack
|
||||
- # always use master branch when collecting parent job variants, refer to git blame for rationale.
|
||||
name: openstack/bifrost
|
||||
override-checkout: master
|
||||
- # always use master branch when collecting parent job variants
|
||||
name: openstack/openstacksdk
|
||||
override-checkout: master
|
||||
- job:
|
||||
name: bifrost-keystone-collections-src
|
||||
parent: bifrost-integration-tinyipa-keystone-ubuntu-focal
|
||||
parent: bifrost-integration-tinyipa-keystone-ubuntu-jammy
|
||||
required-projects:
|
||||
- openstack/ansible-collections-openstack
|
||||
- # always use master branch when collecting parent job variants, refer to git blame for rationale.
|
||||
name: openstack/bifrost
|
||||
override-checkout: master
|
||||
|
||||
# TripleO jobs
|
||||
- job:
|
||||
name: tripleo-ci-centos-8-standalone-osa
|
||||
parent: tripleo-ci-base-standalone-centos-8
|
||||
vars:
|
||||
featureset: '052'
|
||||
consumer_job: false
|
||||
build_container_images: true
|
||||
required-projects:
|
||||
- openstack/ansible-collections-openstack
|
||||
- # always use master branch when collecting parent job variants, refer to git blame for rationale.
|
||||
name: openstack/tripleo-ci
|
||||
- # always use master branch when collecting parent job variants
|
||||
name: openstack/openstacksdk
|
||||
override-checkout: master
|
||||
irrelevant-files: &irr_files
|
||||
- .*molecule.*
|
||||
- ^.*\.md$
|
||||
- ^.*\.rst$
|
||||
- ^docs/.*$
|
||||
- ^contrib/.*$
|
||||
- ^changelogs/.*$
|
||||
- ^meta/.*$
|
||||
- ^tests/.*$
|
||||
- ^tools/.*$
|
||||
- ^requirements.*$
|
||||
- ^setup.*$
|
||||
- tox.ini
|
||||
# Run only on files used in TripleO
|
||||
files: &ooo_files
|
||||
- ^plugins/modules/catalog_service.*$
|
||||
- ^plugins/modules/endpoint.*$
|
||||
- ^plugins/modules/identity_domain.*$
|
||||
- ^plugins/modules/identity_domain_info.*$
|
||||
- ^plugins/modules/identity_role.*$
|
||||
- ^plugins/modules/identity_user.*$
|
||||
- ^plugins/modules/keypair.*$
|
||||
- ^plugins/modules/project.*$
|
||||
- ^plugins/modules/role_assignment.*$
|
||||
- ^plugins/modules/stack.*$
|
||||
- ^plugins/module_utils/openstack.*$
|
||||
|
||||
- job:
|
||||
name: tripleo-ci-centos-9-standalone-osa
|
||||
parent: tripleo-ci-centos-8-standalone-osa
|
||||
nodeset: single-centos-9-node
|
||||
branches: ^(stable/1.0.0|master).*$
|
||||
override-checkout: master
|
||||
vars:
|
||||
containers_base_image: quay.io/centos/centos:stream9
|
||||
consumer_job: false
|
||||
build_container_images: true
|
||||
branch_override: master
|
||||
files: *ooo_files
|
||||
irrelevant-files: *irr_files
|
||||
|
||||
- job:
|
||||
name: tripleo-ci-centos-8-standalone-train-osa
|
||||
parent: tripleo-ci-centos-8-standalone-osa
|
||||
branches: stable/1.0.0
|
||||
override-checkout: stable/train
|
||||
vars:
|
||||
branch_override: stable/train
|
||||
|
||||
- job:
|
||||
name: tripleo-ci-centos-8-standalone-wallaby-osa
|
||||
parent: tripleo-ci-centos-8-standalone-osa
|
||||
branches: stable/1.0.0
|
||||
override-checkout: stable/wallaby
|
||||
vars:
|
||||
branch_override: stable/wallaby
|
||||
|
||||
- job:
|
||||
name: tripleo-ci-centos-9-standalone-wallaby-osa
|
||||
parent: tripleo-ci-centos-9-standalone-osa
|
||||
branches: stable/1.0.0
|
||||
override-checkout: stable/wallaby
|
||||
vars:
|
||||
branch_override: stable/wallaby
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-release
|
||||
parent: base
|
||||
parent: openstack-tox-linters-ansible
|
||||
run: ci/publish/publish_collection.yml
|
||||
secrets:
|
||||
- ansible_galaxy_info
|
||||
@@ -608,116 +266,57 @@
|
||||
data:
|
||||
url: https://galaxy.ansible.com
|
||||
token: !encrypted/pkcs1-oaep
|
||||
- lZFzfoCbuwqV1k6qRfl/VS7E+knUW7+zpg7BptrenK4n0g7UY0HtdVkYq0pV0Tj/LbhzG
|
||||
jHD0mehcV1iS6B7ORKg4criJkdDfEx09BD8z8yv0EleiIMmhlrCoMcY593OZMBtVbGi0D
|
||||
CwQtNO98QIsfZogChfLfvRNiBmUV98mEb/p6p3EtGx8J7qcAsqfWxc/CzB8GCleLAHHHT
|
||||
FuikMM03ZnV0ew7E+TPkHbzzPhBZOqS5HYF0HtgttHwIXdfIWp/XdTuEEk7uRRgYZ2Iao
|
||||
ifWRzoKaOQmhM++e1ydCqw9D4y9dZEFNMQLwSqcrvtb8cNwT1kl7SCFqYNE2lbutj4ne6
|
||||
PTBQRsKegMB4Y3ena14fNF6tCynvJLPhF/cjPH2Jhs+B19XQhWkL3TgiOY02W24YHwRcP
|
||||
+LdkM8inAvyVi3DEbEqdjBPO9OFJcBOKPlCdkGvuwdNCuEpEwctWs0gV3voflG2CDKzmJ
|
||||
wu9JJOAWnq/0l1WpuDqWreKeQ/BUGZC2Gb4xRAqofulgvhs4WuYoEccjH4EJFIZ90S1EP
|
||||
R/ZLadqZaEhmjwGM5sMWbBbjT23XsRgg0Tzt9m8DENYMuYDqkMdRbt2jYZa+32p4hyxVe
|
||||
Y6H/pqYq5b9uOzumnShaK4WlmkQyXcNPkoSlMC1h4OGvqX/WUixpI38jyMA5Tc=
|
||||
- QJ3c5LfmM4YmqwwLKv4wK5lroWDLGeMyPkmHXhvf0ry3vGjKZvZxVpbIhFXJHXevHov/r
|
||||
nvlqwmG8D5msynQKZDFg2ZwSMIQWRKfSbsSLe7A6NWI2wC+QtZSPiRiBcBcHY1QbNNW21
|
||||
84cssYa1oHOA0WXpomBz1qXuPV48aKLjMnWysgFhNSx3Oog+ZOSCczyyVVuXP1lIWIO26
|
||||
AtRTrEcr37K3JY9usE2PCbZKFOq/+IDPz9fbS7PtBOv7iXOHOf3AfBiJiaJe3q/ecoaaq
|
||||
ejk2WTKWfvq/3rY4pU1976kUcxgcd+jj9ReFyw8edCsc1ecL0qmZFbdHmC03jEcVo4p8I
|
||||
WJQ0D5wk4/u2Fu9texNuBvb62Yu3Y028Zhm5rz8Zl/ISsdaA3losn5S7C7iAH/yKlGQEI
|
||||
N/1X4M0tVPaMtsIhZyyz+JMbeNyVR9ZarqbtpzRtVhjxL7KOiAQbEzAmZcBbCJ2Z5iI+P
|
||||
bTp03f9Y/tZNtkohARvx1TKhv8CvsmyGkMm+r5Y8aWz3SNy8LL6bSwtGun/ifbnadHmw/
|
||||
TD5/UUXHHjBGkeAu9HTtwUZ5Qdkfg92PnPgruAAuOkF1Y4RyRS9qvwhtqyHO8TwU0INRY
|
||||
5MHEzeOQWemoQb/qdENp+J/Q9oMEbpFYv9TkrWkxVoKop6Str8e3FF5sxmN/SE=
|
||||
|
||||
- project:
|
||||
check:
|
||||
jobs:
|
||||
- tox-pep8
|
||||
- openstack-tox-linters-ansible-devel
|
||||
- openstack-tox-linters-ansible-2.12
|
||||
- openstack-tox-linters-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack:
|
||||
dependencies: &deps_unit_lint
|
||||
- tox-pep8
|
||||
- openstack-tox-linters-ansible-2.9
|
||||
- openstack-tox-linters-ansible-2.12
|
||||
voting: false
|
||||
|
||||
- ansible-collections-openstack-functional-devstack-releases:
|
||||
dependencies: *deps_unit_lint
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.9:
|
||||
dependencies: *deps_unit_lint
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.12:
|
||||
dependencies: *deps_unit_lint
|
||||
- ansible-collections-openstack-functional-devstack-ansible-devel:
|
||||
dependencies: *deps_unit_lint
|
||||
- ansible-collections-openstack-functional-devstack-xena-ansible-2.12:
|
||||
dependencies: *deps_unit_lint
|
||||
- ansible-collections-openstack-functional-devstack-wallaby-ansible-2.12:
|
||||
dependencies: *deps_unit_lint
|
||||
- ansible-collections-openstack-functional-devstack-train-ansible-2.11:
|
||||
dependencies: *deps_unit_lint
|
||||
- ansible-collections-openstack-functional-devstack-octavia:
|
||||
dependencies: *deps_unit_lint
|
||||
- openstack-tox-linters-ansible-2.18
|
||||
- ansible-collections-openstack-functional-devstack
|
||||
- ansible-collections-openstack-functional-devstack-releases
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.18
|
||||
- ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
- ansible-collections-openstack-functional-devstack-magnum
|
||||
- ansible-collections-openstack-functional-devstack-octavia
|
||||
|
||||
- bifrost-collections-src:
|
||||
voting: false
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- bifrost-keystone-collections-src:
|
||||
voting: false
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
|
||||
- tripleo-ci-centos-8-standalone-wallaby-osa:
|
||||
dependencies: *deps_unit_lint
|
||||
|
||||
- tripleo-ci-centos-8-standalone-train-osa:
|
||||
voting: false
|
||||
dependencies: *deps_unit_lint
|
||||
|
||||
- tripleo-ci-centos-9-standalone-osa:
|
||||
voting: false
|
||||
dependencies: *deps_unit_lint
|
||||
|
||||
- tripleo-ci-centos-9-standalone-wallaby-osa:
|
||||
voting: false
|
||||
dependencies: *deps_unit_lint
|
||||
|
||||
gate:
|
||||
jobs:
|
||||
- tox-pep8
|
||||
- openstack-tox-linters-ansible-2.12
|
||||
- openstack-tox-linters-ansible-2.9
|
||||
# - ansible-collections-openstack-functional-devstack
|
||||
- openstack-tox-linters-ansible-2.18
|
||||
- ansible-collections-openstack-functional-devstack-releases
|
||||
# - ansible-collections-openstack-functional-devstack-ansible-2.9
|
||||
# - ansible-collections-openstack-functional-devstack-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-wallaby-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-xena-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-train-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-magnum
|
||||
- ansible-collections-openstack-functional-devstack-octavia
|
||||
- tripleo-ci-centos-8-standalone-wallaby-osa
|
||||
|
||||
periodic:
|
||||
jobs:
|
||||
- openstack-tox-linters-ansible-devel
|
||||
- openstack-tox-linters-ansible-2.12
|
||||
- openstack-tox-linters-ansible-2.9
|
||||
- openstack-tox-linters-ansible-2.18
|
||||
- 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.12
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.18
|
||||
- ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
- ansible-collections-openstack-functional-devstack-xena-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-wallaby-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-victoria-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-train-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-queens-ansible-2.11
|
||||
- bifrost-collections-src
|
||||
- bifrost-keystone-collections-src
|
||||
- ansible-collections-openstack-functional-devstack-magnum
|
||||
- ansible-collections-openstack-functional-devstack-octavia
|
||||
- tripleo-ci-centos-9-standalone-wallaby-osa
|
||||
- tripleo-ci-centos-9-standalone-osa
|
||||
- tripleo-ci-centos-8-standalone-train-osa
|
||||
- tripleo-ci-centos-8-standalone-wallaby-osa
|
||||
|
||||
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
|
||||
- ansible-collections-openstack-functional-devstack-queens-ansible-2.11
|
||||
|
||||
tag:
|
||||
jobs:
|
||||
|
||||
303
CHANGELOG.rst
303
CHANGELOG.rst
@@ -1,51 +1,312 @@
|
||||
=============================================
|
||||
Openstack Cloud Ansilbe modules Release Notes
|
||||
=============================================
|
||||
==========================================
|
||||
Ansible OpenStack Collection Release Notes
|
||||
==========================================
|
||||
|
||||
.. contents:: Topics
|
||||
|
||||
|
||||
v1.8.0
|
||||
v2.4.1
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Subnet pool module and bugfixes
|
||||
Bugfixes and minor changes
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Update tags when changing server
|
||||
|
||||
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
|
||||
- Fix missed client_cert in OpenStackModule
|
||||
|
||||
v2.4.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
New trait module and minor changes
|
||||
|
||||
Major Changes
|
||||
-------------
|
||||
|
||||
- Add trait module
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add loadbalancer quota options
|
||||
- Allow create instance with tags
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.subnet_pool - Create or Delete subnet pools from OpenStack.
|
||||
- openstack.cloud.trait - Add or Delete a trait from OpenStack
|
||||
|
||||
v1.7.2
|
||||
v2.3.3
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfixes
|
||||
Bugfixes and minor changes
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add test to only_ipv4 in inventory
|
||||
- add an option to use only IPv4 only for ansible_host and ansible_ssh_host
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Fix collection guidelines
|
||||
- CI - Fix deprecated ANSIBLE_COLLECTIONS_PATHS variable
|
||||
|
||||
v2.3.2
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfixes and minor changes
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Drop compat implementations for tests
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Fix openstack.cloud.port module failure in check mode
|
||||
|
||||
v2.3.1
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Client TLS certificate support
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add ability to pass client tls certificate
|
||||
|
||||
v2.3.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfixes and new modules
|
||||
|
||||
Major Changes
|
||||
-------------
|
||||
|
||||
- Add Neutron trunk module
|
||||
- Add application_credential module
|
||||
- Add module to filter available volume services
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add inactive state for the images
|
||||
- Add insecure_registry property to coe_cluster_templates
|
||||
- Add support for creation of the default external networks
|
||||
- Add target_all_project option
|
||||
- Add vlan_tranparency for creation networks
|
||||
- Allow munch results in server_info module
|
||||
- Allow to specify multiple allocation pools when creating a subnet
|
||||
- CI - Disable auto-discovery for setuptools
|
||||
- CI - Don't create port with binding profile
|
||||
- CI - Fix CI in collection
|
||||
- CI - Fix linters-devel and devstack tests
|
||||
- CI - Fix regression in quota module
|
||||
- CI - Fix test for server shelve
|
||||
- CI - Migrate Bifrost jobs to Ubuntu Jammy
|
||||
- CI - Remove 2.9 jobs from Zuul config
|
||||
- CI - Run functional testing regardless of pep8/linter results
|
||||
- Enable glance-direct interop image import
|
||||
- Ensure coe_cluster_template compare labels properly
|
||||
- Wait for deleted server to disappear from results
|
||||
- router - Allow specifying external network name in a different project
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Allow wait false when auto_ip is false
|
||||
- Fix exception when creating object from file
|
||||
- Fix exception when updating container with metadata
|
||||
- Fix typo in openstack.cloud.lb_pool
|
||||
- Fix typo in parameter description
|
||||
- fix subnet module - allow cidr option with subnet_pool
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.application_credential - Manage OpenStack Identity (Keystone) application credentials
|
||||
- openstack.cloud.trunk - Add or delete trunks from an OpenStack cloud
|
||||
- openstack.cloud.volume_service_info - Fetch OpenStack Volume (Cinder) services
|
||||
|
||||
v2.2.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
New module for volume_type and bugfixes
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add volume_encryption_type modules
|
||||
- Add volume_type modules
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Fix image module filter
|
||||
- Fix port module idempotency
|
||||
- Fix router module idempotency
|
||||
|
||||
v2.1.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
New module for Ironic and bugfixes
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add baremetal_deploy_template module
|
||||
- Highlight our mode of operation more prominently
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Change security group rules only when instructed to do so
|
||||
- Fix for AttributeError: 'dict' object has no attribute 'status'
|
||||
- Fix issue with multiple records in recordset
|
||||
- Fix mistake in compute_flavor_access notes
|
||||
- Fixed private option in inventory plugin
|
||||
- Respect description option and delete security group rules first
|
||||
- Use true and false instead of yes and no for boolean values
|
||||
|
||||
v2.0.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Our new major release 2.0.0 of the Ansible collection for OpenStack clouds aka ``openstack.cloud`` is a complete overhaul of the code base and brings full compatibility with openstacksdk 1.0.0.
|
||||
|
||||
Highlights of this release are
|
||||
* three new modules which for example provide a generic and uniform API for interacting with OpenStack cloud resources,
|
||||
* a complete refactoring of all existing modules bringing dozens of bugfixes, new features as well as consistent
|
||||
and properly documented module results and options,
|
||||
* 100% compatibility with openstacksdk's first major release 1.0.0,
|
||||
* new guides for contributors from devstack setup over coding guidelines to our release process and
|
||||
* massively increased CI coverage with many new integration tests, now covering all modules and plugins.
|
||||
|
||||
Note, this ``2.0.0`` release *breaks backward compatibility* with previous ``1.x.x`` releases!
|
||||
* ``2.x.x`` releases of this collection are compatible with openstacksdk ``1.x.x`` and later *only*,
|
||||
* ``1.x.x`` releases of this collection are compatible with openstacksdk ``0.x.x`` prior to ``0.99.0`` *only*,
|
||||
* ``2.x.x`` releases of are not backward compatible with ``1.x.x`` releases,
|
||||
* ``1.x.x`` release series will be in maintenance mode now and receive bugfixes only.
|
||||
|
||||
However, this collection as well as openstacksdk continue to be backward compatible with clouds running on older OpenStack releases. For example, it is fine and a fully supported use case to use this 2.0.0 release with clouds based on OpenStack Train, Wallaby or Zed. Feel encouraged to always use the latest releases of this collection and openstacksdk regardless of which version of OpenStack is installed in your cloud.
|
||||
|
||||
This collection is compatible with and tested with Ansible 2.9 and later. However, support for old ``os_*`` short module names such as ``os_server`` have been dropped with this release. You have to call modules using their FQCN (Fully-Qualified Collection Name) such as ``openstack.cloud.server`` instead.
|
||||
|
||||
Many thanks to all contributors who made this release possible. Tens of thousands LOCs have been reviewed and changed and fixed and tested throughout last year. You rock!
|
||||
|
||||
Major Changes
|
||||
-------------
|
||||
|
||||
- Many modules gained support for Ansible's check mode or have been fixed to properly implement a no change policy during check mode runs.
|
||||
- Many modules gained support for updates. In the past, those modules allowed to create and delete OpenStack cloud resources but would ignore when module options had been changed.
|
||||
- Many modules such as ``openstack.cloud.server``, ``openstack.cloud.baremetal_node`` and all load-balancer related modules now properly implement the ``wait`` option. For example, when ``wait`` is set to ``true`` then modules will not return until resources have reached its ``active`` or ``deleted`` state.
|
||||
- Module ``openstack.cloud.resource`` has been added. It provides an generic and uniform interface to create, update and delete any OpenStack cloud resource which openstacksdk supports. This module unlocks a huge amount of functionality from OpenStack clouds to Ansible users which has been inaccessible with existing modules so far.
|
||||
- Module ``openstack.cloud.resources`` has been added. It provides an generic and uniform interface to list any type of OpenStack cloud resources which openstacksdk supports. This module fetch any OpenStack cloud resource without having to implement a new Ansible ``*_info`` module for this type of resource first.
|
||||
- Module ``openstack.cloud.subnet_pool`` has been added. It allows to create and delete subnet pools in OpenStack clouds.
|
||||
- Module examples have been improved and updated for most modules.
|
||||
- Module results have been properly documented for all modules.
|
||||
- Options in all modules have been renamed to match openstacksdk's attribute names (if applicable). The previous option names have been added as aliases to keep module options backward compatible.
|
||||
- Our CI integration tests have been massively expanded. Our test coverage spans across all modules and plugins now, including tests for our inventory plugin and our new ``openstack.cloud.resource`` and ``openstack.cloud.resources`` modules.
|
||||
- Our contributors documentation has been heavily extended. In directory ``docs`` you will find the rationale for our branching strategy, a developer's guide on how to contribute to the collection, a tutorial to set up a DevStack environment for hacking on and testing the collection, a step-by-step guide for publishing new releases and a list of questions to ask when doing reviews or submitting patches for review.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Added generic module options ``sdk_log_path`` and ``sdk_log_level`` which allow to track openstacksdk activity.
|
||||
- Many more options were added to modules but we stopped counting at one point...
|
||||
- Module ``openstack.cloud.coe_cluster`` gained support for option ``is_floating_ip_enabled``.
|
||||
- Module ``openstack.cloud.lb_listener`` gained options ``default_tls_container_ref`` and ``sni_container_refs`` which allow to specify TLS certificates when using the ``TERMINATED_HTTPS`` protocol.
|
||||
- Module ``openstack.cloud.network`` gained support for updates, i.e. existing networks will be properly updated now when module options such as ``mtu`` or ``admin_state_up`` have been changed.
|
||||
- Module ``openstack.cloud.port`` gained an ``description`` option.
|
||||
- Module ``openstack.cloud.role_assignment`` gained an ``system`` option.
|
||||
- Module ``openstack.cloud.security_group_rule`` gained an ``description`` option.
|
||||
- Module ``openstack.cloud.server_action`` gained an option ``all_projects`` which allows to execute actions on servers outside of the current auth-scoped project (if the user has permission to do so).
|
||||
- Module ``openstack.cloud.server_info`` gained an ``description`` option.
|
||||
- Module ``openstack.cloud.server`` gained an ``description`` option.
|
||||
- Module ``openstack.cloud.server`` gained support for updates. For example, options such as ``description`` and floating ip addresses can be updated now.
|
||||
- Module ``openstack.cloud.subnet`` gained an ``subnet_pool`` option.
|
||||
|
||||
Breaking Changes / Porting Guide
|
||||
--------------------------------
|
||||
|
||||
- 2.x.x releases of this collection are not backward compatible with 1.x.x releases. Backward compatibility is guaranteed within each release series only. Module options have been kept backward compatible across both release series, apart from a few exceptions noted below. However, module results have changed for most modules due to deep changes in openstacksdk. For easier porting and usage, we streamlined return values across modules and documented return values of all modules.
|
||||
- Default value for option ``security_groups`` in ``openstack.cloud.server`` has been changed from ``['default']`` to ``[]`` because the latter is the default in python-openstackclient and the former behavior causes issues with existing servers.
|
||||
- Dropped symbolic links with prefix ``os_`` and plugin routing for deprecated ``os_*`` module names. This means users have to call modules of the Ansible OpenStack collection using their FQCN (Fully Qualified Collection Name) such as ``openstack.cloud.server``. Short module names such as ``os_server`` will now raise an Ansible error.
|
||||
- Module ``openstack.cloud.project_access`` has been split into two separate modules ``openstack.cloud.compute_flavor_access`` and ``openstack.cloud.volume_type_access``.
|
||||
- Option ``availability_zone`` has been removed from the list of generic options available in all modules. Instead it has been inserted into the ``openstack.cloud.server`` and ``openstack.cloud.volume`` modules because it is relevant to those two modules only.
|
||||
- Option ``name`` of module ``openstack.cloud.port`` is required now because it is used to find, update and delete ports and idempotency would break otherwise.
|
||||
- Option ``policies`` has been replaced with option ``policy`` in module ``openstack.cloud.server_group``. The former is ancient and was superceded by ``policy`` a long time ago.
|
||||
- Release series 2.x.x of this collection is compatible with openstacksdk 1.0.0 and later only. For compatibility with openstacksdk < 0.99.0 use release series 1.x.x of this collection. Ansible will raise an error when modules and plugins in this collection are used with an incompatible release of openstacksdk.
|
||||
- Special value ``auto`` for option ``id`` in module ``openstack.cloud.compute_flavor`` has been deprecated to be consistent with our other modules and openstacksdk's behaviour.
|
||||
|
||||
Deprecated Features
|
||||
-------------------
|
||||
|
||||
- Option ``is_public`` in module ``openstack.cloud.image`` has been deprecated and replaced with option ``visibility``.
|
||||
- Option ``volume`` in module ``openstack.cloud.image`` has been deprecated and it should be replaced with module ``openstack.cloud.volume`` in user code.
|
||||
|
||||
Removed Features (previously deprecated)
|
||||
----------------------------------------
|
||||
|
||||
- Dropped deprecated ``skip_update_of_driver_password`` option from module ``openstack.cloud.baremetal_node``.
|
||||
- Dropped unmaintained, obsolete and broken inventory script ``scripts/inventory/openstack_inventory.py``. It had been replaced with a proper Ansible inventory plugin ``openstack.cloud.openstack`` during the 1.x.x life cycle.
|
||||
- Module ``openstack.cloud.object`` no longer allows to create and delete containers, its sole purpose is managing an object in a container now. Use module ``openstack.cloud.object_container`` to managing Swift containers instead.
|
||||
- Option ``listeners`` has been removed from module ``openstack.cloud.loadbalancer`` because it duplicates a subset of the functionality (and code) provided by our ``openstack.cloud.lb_{listener,member,pool}`` modules.
|
||||
- Our outdated, undocumented, untested and bloated code templates in ``contrib`` directory which could be used to generate and develop new Ansible modules for this collection have been removed.
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Ansible check mode has been fixed in module ``openstack.cloud.compute_flavor``, it will no longer apply changes when check mode is enabled.
|
||||
- Creating load-balancers with module ``openstack.cloud.loadbalancer`` properly handles situations where several provider networks exist. A floating ip address specified in option ``floating_ip_address`` will be allocated from Neutron external network specified in option ``floating_ip_network``.
|
||||
- Default values for options ``shared``, ``admin_state_up`` and ``external`` in module ``openstack.cloud.network`` have been dropped because they cause failures for clouds which do not have those optional extensions installed.
|
||||
- Dropped default values for options ``min_disk`` and ``min_ram`` in module ``openstack.cloud.image`` because it interferes with its update mechanism and Glance uses those values anyway. Fixed handling of options ``name``, ``id``, ``visibility`` and ``is_public``.
|
||||
- Module ``openstack.cloud.baremetal_node_info`` will now properly return machine details when iterating over all available baremetal nodes.
|
||||
- Module ``openstack.cloud.host_aggregate`` now correctly handles ``hosts`` not being set or being set to ``None``.
|
||||
- Module ``openstack.cloud.identity_user`` will no longer fail when no password is supplied since Keystone allows to create a user without an password.
|
||||
- Module ``openstack.cloud.keypair`` no longer removes trailing spaces when reading a public key because this broke idempotency when using openstackclient and this module at the same time.
|
||||
- Module ``openstack.cloud.quota`` no longer sends invalid attributes such as ``project_id`` to OpenStack API when updating Nova, Neutron and Cinder quotas.
|
||||
- Module ``openstack.cloud.server`` will no longer change security groups to ``['default']`` on existing servers when option ``security_groups`` has not been specified.
|
||||
- Module ``openstack.cloud.subnet`` now properly handles updates, thus idempotency has been fixed and restored.
|
||||
- Modules ``openstack.cloud.security_group`` and ``openstack.cloud.security_group_rule`` gained support for specifying string ``any`` as a valid protocol in security group rules.
|
||||
- Option ``interfaces`` in module ``openstack.cloud.router`` no longer requires option ``network`` to be set, it is ``external_fixed_ips`` what requires ``network``.
|
||||
- Option ``is_public`` in module ``openstack.cloud.image`` will now be handled as a boolean instead of a string to be compatible to Glance API and fix issues when interacting with Glance service.
|
||||
- Option ``network`` in module ``openstack.cloud.router`` is now propery marked as required by options ``enable_snat`` and ``external_fixed_ips``.
|
||||
- Option ``owner`` in module ``openstack.cloud.image`` is now respected when searching for and creating images.
|
||||
- Our OpenStack inventory plugin now properly supports Ansible's cache feature.
|
||||
|
||||
v1.7.1
|
||||
======
|
||||
|
||||
@@ -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
|
||||
228
README.md
228
README.md
@@ -1,61 +1,84 @@
|
||||
[](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.
|
||||
**NOTE:** We need and value your contributions! Maintaining this collection is a community effort. We are all both users
|
||||
and developers of this collection at the same time. If you find a bug, please report it. If you have fixed a bug, please
|
||||
submit a patch. If you need new functionality which is not covered by this collection yet, please extend an existing
|
||||
module or submit a new one. Our [Contributing](#contributing) section below has tons of docs to check out. Please get in
|
||||
touch!
|
||||
|
||||
The collection includes the Openstack modules and plugins supported by Openstack community to help the management of Openstack infrastructure.
|
||||
## Branches and Non Backward Compatibility ⚠️
|
||||
|
||||
## Installation and Usage
|
||||
Our codebase has been split into two separate release series, `2.x.x` and `1.x.x`:
|
||||
|
||||
### Installing dependencies
|
||||
* `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 ⚠️
|
||||
|
||||
For using the Openstack Cloud collection firstly you need to install `ansible` and `openstacksdk` Python modules on your Ansible controller.
|
||||
For example with pip:
|
||||
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!
|
||||
|
||||
```bash
|
||||
pip install "ansible>=2.9" "openstacksdk>=0.36"
|
||||
[openstacksdk]: https://opendev.org/openstack/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>=1.0.0"
|
||||
```
|
||||
|
||||
OpenStackSDK has to be available to Ansible and to the Python interpreter on the host, where Ansible executes the module (target host).
|
||||
Please note, that under some circumstances Ansible might invoke a non-standard Python interpreter on the target host.
|
||||
Using Python version 3 is highly recommended for OpenstackSDK and strongly required from OpenstackSDK version 0.39.0.
|
||||
[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 through `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 the Openstack Cloud collection, please reference the full namespace, collection name, and module name that you want to use:
|
||||
```sh
|
||||
ansible-galaxy collection install -r requirements.yml
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
To use a module from the Ansible OpenStack collection, call them by their Fully Qualified Collection Name (FQCN),
|
||||
composed of their namespace, collection name and module name:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Using Openstack Cloud collection
|
||||
hosts: localhost
|
||||
- hosts: localhost
|
||||
tasks:
|
||||
- openstack.cloud.server:
|
||||
- name: Create server in an OpenStack cloud
|
||||
openstack.cloud.server:
|
||||
name: vm
|
||||
state: present
|
||||
cloud: openstack
|
||||
@@ -70,12 +93,12 @@ Or you can add the full namespace and collection name in the `collections` eleme
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Using Openstack Cloud collection
|
||||
hosts: localhost
|
||||
- hosts: localhost
|
||||
collections:
|
||||
- openstack.cloud
|
||||
tasks:
|
||||
- server_volume:
|
||||
- name: Create server in an OpenStack cloud
|
||||
server_volume:
|
||||
state: present
|
||||
cloud: openstack
|
||||
server: Mysql-server
|
||||
@@ -83,49 +106,126 @@ Or you can add the full namespace and collection name in the `collections` eleme
|
||||
device: /dev/vdb
|
||||
```
|
||||
|
||||
### Usage
|
||||
For powerful generic [CRUD][crud]-style resource management use Ansible module
|
||||
[`openstack.cloud.resource`](plugins/modules/resource.py):
|
||||
|
||||
See the collection docs at Ansible site:
|
||||
```yaml
|
||||
---
|
||||
- hosts: localhost
|
||||
tasks:
|
||||
- name: Create security group
|
||||
openstack.cloud.resource:
|
||||
cloud: openstack
|
||||
service: network
|
||||
type: security_group
|
||||
attributes:
|
||||
name: ansible_security_group
|
||||
description: 'ansible security group'
|
||||
|
||||
* [openstack.cloud collection docs (version released in Ansible package)](https://docs.ansible.com/ansible/latest/collections/openstack/cloud/index.html)
|
||||
- name: Update security group description
|
||||
openstack.cloud.resource:
|
||||
cloud: openstack
|
||||
service: network
|
||||
type: security_group
|
||||
attributes:
|
||||
name: ansible_security_group
|
||||
description: 'ansible neutron security group'
|
||||
|
||||
* [openstack.cloud collection docs (devel version)](https://docs.ansible.com/ansible/devel/collections/openstack/cloud/index.html)
|
||||
- name: Delete security group
|
||||
openstack.cloud.resource:
|
||||
cloud: openstack
|
||||
service: network
|
||||
type: security_group
|
||||
attributes:
|
||||
name: ansible_security_group
|
||||
state: absent
|
||||
```
|
||||
|
||||
For generic resource listing use Ansible module [`openstack.cloud.resources`](plugins/modules/resources.py):
|
||||
|
||||
```yaml
|
||||
---
|
||||
- hosts: localhost
|
||||
tasks:
|
||||
- name: List images
|
||||
openstack.cloud.resources:
|
||||
cloud: openstack
|
||||
service: image
|
||||
type: image
|
||||
|
||||
- name: List compute flavors
|
||||
openstack.cloud.resources:
|
||||
cloud: openstack
|
||||
service: compute
|
||||
type: flavor
|
||||
|
||||
- name: List networks with name 'public'
|
||||
openstack.cloud.resources:
|
||||
cloud: openstack
|
||||
service: network
|
||||
type: network
|
||||
parameters:
|
||||
name: public
|
||||
```
|
||||
|
||||
[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
|
||||
[crud]: https://en.wikipedia.org/wiki/CRUD
|
||||
|
||||
## 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 [OFTC IRC](https://www.oftc.net/).
|
||||
We have a Special Interest Group for the Ansible OpenStack collection. Join us in `#openstack-ansible-sig` on
|
||||
[OFTC IRC](https://www.oftc.net/) 🍪
|
||||
|
||||
## 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.
|
||||
|
||||
@@ -313,31 +313,306 @@ releases:
|
||||
- lb_member - Add monitor_[address,port] parameter
|
||||
release_summary: Bugfixes
|
||||
release_date: '2022-03-08'
|
||||
1.7.2:
|
||||
2.0.0:
|
||||
changes:
|
||||
breaking_changes:
|
||||
- 2.x.x releases of this collection are not backward compatible with 1.x.x releases.
|
||||
Backward compatibility is guaranteed within each release series only. Module
|
||||
options have been kept backward compatible across both release series, apart
|
||||
from a few exceptions noted below. However, module results have changed for
|
||||
most modules due to deep changes in openstacksdk. For easier porting and usage,
|
||||
we streamlined return values across modules and documented return values of
|
||||
all modules.
|
||||
- Default value for option ``security_groups`` in ``openstack.cloud.server``
|
||||
has been changed from ``['default']`` to ``[]`` because the latter is the
|
||||
default in python-openstackclient and the former behavior causes issues with
|
||||
existing servers.
|
||||
- Dropped symbolic links with prefix ``os_`` and plugin routing for deprecated
|
||||
``os_*`` module names. This means users have to call modules of the Ansible
|
||||
OpenStack collection using their FQCN (Fully Qualified Collection Name) such
|
||||
as ``openstack.cloud.server``. Short module names such as ``os_server`` will
|
||||
now raise an Ansible error.
|
||||
- Module ``openstack.cloud.project_access`` has been split into two separate
|
||||
modules ``openstack.cloud.compute_flavor_access`` and ``openstack.cloud.volume_type_access``.
|
||||
- Option ``availability_zone`` has been removed from the list of generic options
|
||||
available in all modules. Instead it has been inserted into the ``openstack.cloud.server``
|
||||
and ``openstack.cloud.volume`` modules because it is relevant to those two
|
||||
modules only.
|
||||
- Option ``name`` of module ``openstack.cloud.port`` is required now because
|
||||
it is used to find, update and delete ports and idempotency would break otherwise.
|
||||
- Option ``policies`` has been replaced with option ``policy`` in module ``openstack.cloud.server_group``.
|
||||
The former is ancient and was superceded by ``policy`` a long time ago.
|
||||
- Release series 2.x.x of this collection is compatible with openstacksdk 1.0.0
|
||||
and later only. For compatibility with openstacksdk < 0.99.0 use release series
|
||||
1.x.x of this collection. Ansible will raise an error when modules and plugins
|
||||
in this collection are used with an incompatible release of openstacksdk.
|
||||
- Special value ``auto`` for option ``id`` in module ``openstack.cloud.compute_flavor``
|
||||
has been deprecated to be consistent with our other modules and openstacksdk's
|
||||
behaviour.
|
||||
bugfixes:
|
||||
- Ansible check mode has been fixed in module ``openstack.cloud.compute_flavor``,
|
||||
it will no longer apply changes when check mode is enabled.
|
||||
- Creating load-balancers with module ``openstack.cloud.loadbalancer`` properly
|
||||
handles situations where several provider networks exist. A floating ip address
|
||||
specified in option ``floating_ip_address`` will be allocated from Neutron
|
||||
external network specified in option ``floating_ip_network``.
|
||||
- Default values for options ``shared``, ``admin_state_up`` and ``external``
|
||||
in module ``openstack.cloud.network`` have been dropped because they cause
|
||||
failures for clouds which do not have those optional extensions installed.
|
||||
- Dropped default values for options ``min_disk`` and ``min_ram`` in module
|
||||
``openstack.cloud.image`` because it interferes with its update mechanism
|
||||
and Glance uses those values anyway. Fixed handling of options ``name``, ``id``,
|
||||
``visibility`` and ``is_public``.
|
||||
- Module ``openstack.cloud.baremetal_node_info`` will now properly return machine
|
||||
details when iterating over all available baremetal nodes.
|
||||
- Module ``openstack.cloud.host_aggregate`` now correctly handles ``hosts``
|
||||
not being set or being set to ``None``.
|
||||
- Module ``openstack.cloud.identity_user`` will no longer fail when no password
|
||||
is supplied since Keystone allows to create a user without an password.
|
||||
- Module ``openstack.cloud.keypair`` no longer removes trailing spaces when
|
||||
reading a public key because this broke idempotency when using openstackclient
|
||||
and this module at the same time.
|
||||
- Module ``openstack.cloud.quota`` no longer sends invalid attributes such as
|
||||
``project_id`` to OpenStack API when updating Nova, Neutron and Cinder quotas.
|
||||
- Module ``openstack.cloud.server`` will no longer change security groups to
|
||||
``['default']`` on existing servers when option ``security_groups`` has not
|
||||
been specified.
|
||||
- Module ``openstack.cloud.subnet`` now properly handles updates, thus idempotency
|
||||
has been fixed and restored.
|
||||
- Modules ``openstack.cloud.security_group`` and ``openstack.cloud.security_group_rule``
|
||||
gained support for specifying string ``any`` as a valid protocol in security
|
||||
group rules.
|
||||
- Option ``interfaces`` in module ``openstack.cloud.router`` no longer requires
|
||||
option ``network`` to be set, it is ``external_fixed_ips`` what requires ``network``.
|
||||
- Option ``is_public`` in module ``openstack.cloud.image`` will now be handled
|
||||
as a boolean instead of a string to be compatible to Glance API and fix issues
|
||||
when interacting with Glance service.
|
||||
- Option ``network`` in module ``openstack.cloud.router`` is now propery marked
|
||||
as required by options ``enable_snat`` and ``external_fixed_ips``.
|
||||
- Option ``owner`` in module ``openstack.cloud.image`` is now respected when
|
||||
searching for and creating images.
|
||||
- Our OpenStack inventory plugin now properly supports Ansible's cache feature.
|
||||
deprecated_features:
|
||||
- Option ``is_public`` in module ``openstack.cloud.image`` has been deprecated
|
||||
and replaced with option ``visibility``.
|
||||
- Option ``volume`` in module ``openstack.cloud.image`` has been deprecated
|
||||
and it should be replaced with module ``openstack.cloud.volume`` in user code.
|
||||
major_changes:
|
||||
- Many modules gained support for Ansible's check mode or have been fixed to
|
||||
properly implement a no change policy during check mode runs.
|
||||
- Many modules gained support for updates. In the past, those modules allowed
|
||||
to create and delete OpenStack cloud resources but would ignore when module
|
||||
options had been changed.
|
||||
- Many modules such as ``openstack.cloud.server``, ``openstack.cloud.baremetal_node``
|
||||
and all load-balancer related modules now properly implement the ``wait``
|
||||
option. For example, when ``wait`` is set to ``true`` then modules will not
|
||||
return until resources have reached its ``active`` or ``deleted`` state.
|
||||
- Module ``openstack.cloud.resource`` has been added. It provides an generic
|
||||
and uniform interface to create, update and delete any OpenStack cloud resource
|
||||
which openstacksdk supports. This module unlocks a huge amount of functionality
|
||||
from OpenStack clouds to Ansible users which has been inaccessible with existing
|
||||
modules so far.
|
||||
- Module ``openstack.cloud.resources`` has been added. It provides an generic
|
||||
and uniform interface to list any type of OpenStack cloud resources which
|
||||
openstacksdk supports. This module fetch any OpenStack cloud resource without
|
||||
having to implement a new Ansible ``*_info`` module for this type of resource
|
||||
first.
|
||||
- Module ``openstack.cloud.subnet_pool`` has been added. It allows to create
|
||||
and delete subnet pools in OpenStack clouds.
|
||||
- Module examples have been improved and updated for most modules.
|
||||
- Module results have been properly documented for all modules.
|
||||
- Options in all modules have been renamed to match openstacksdk's attribute
|
||||
names (if applicable). The previous option names have been added as aliases
|
||||
to keep module options backward compatible.
|
||||
- Our CI integration tests have been massively expanded. Our test coverage spans
|
||||
across all modules and plugins now, including tests for our inventory plugin
|
||||
and our new ``openstack.cloud.resource`` and ``openstack.cloud.resources``
|
||||
modules.
|
||||
- Our contributors documentation has been heavily extended. In directory ``docs``
|
||||
you will find the rationale for our branching strategy, a developer's guide
|
||||
on how to contribute to the collection, a tutorial to set up a DevStack environment
|
||||
for hacking on and testing the collection, a step-by-step guide for publishing
|
||||
new releases and a list of questions to ask when doing reviews or submitting
|
||||
patches for review.
|
||||
minor_changes:
|
||||
- Added generic module options ``sdk_log_path`` and ``sdk_log_level`` which
|
||||
allow to track openstacksdk activity.
|
||||
- Many more options were added to modules but we stopped counting at one point...
|
||||
- Module ``openstack.cloud.coe_cluster`` gained support for option ``is_floating_ip_enabled``.
|
||||
- Module ``openstack.cloud.lb_listener`` gained options ``default_tls_container_ref``
|
||||
and ``sni_container_refs`` which allow to specify TLS certificates when using
|
||||
the ``TERMINATED_HTTPS`` protocol.
|
||||
- Module ``openstack.cloud.network`` gained support for updates, i.e. existing
|
||||
networks will be properly updated now when module options such as ``mtu``
|
||||
or ``admin_state_up`` have been changed.
|
||||
- Module ``openstack.cloud.port`` gained an ``description`` option.
|
||||
- Module ``openstack.cloud.role_assignment`` gained an ``system`` option.
|
||||
- Module ``openstack.cloud.security_group_rule`` gained an ``description`` option.
|
||||
- Module ``openstack.cloud.server_action`` gained an option ``all_projects``
|
||||
which allows to execute actions on servers outside of the current auth-scoped
|
||||
project (if the user has permission to do so).
|
||||
- Module ``openstack.cloud.server_info`` gained an ``description`` option.
|
||||
- Module ``openstack.cloud.server`` gained an ``description`` option.
|
||||
- Module ``openstack.cloud.server`` gained support for updates. For example,
|
||||
options such as ``description`` and floating ip addresses can be updated now.
|
||||
- Module ``openstack.cloud.subnet`` gained an ``subnet_pool`` option.
|
||||
release_summary: "Our new major release 2.0.0 of the Ansible collection for
|
||||
OpenStack clouds aka ``openstack.cloud`` is a complete overhaul of the code
|
||||
base and brings full compatibility with openstacksdk 1.0.0.\n\nHighlights
|
||||
of this release are\n* three new modules which for example provide a generic
|
||||
and uniform API for interacting with OpenStack cloud resources,\n* a complete
|
||||
refactoring of all existing modules bringing dozens of bugfixes, new features
|
||||
as well as consistent\n and properly documented module results and options,\n*
|
||||
100% compatibility with openstacksdk's first major release 1.0.0,\n* new guides
|
||||
for contributors from devstack setup over coding guidelines to our release
|
||||
process and\n* massively increased CI coverage with many new integration tests,
|
||||
now covering all modules and plugins.\n\nNote, this ``2.0.0`` release *breaks
|
||||
backward compatibility* with previous ``1.x.x`` releases!\n* ``2.x.x`` releases
|
||||
of this collection are compatible with openstacksdk ``1.x.x`` and later *only*,\n*
|
||||
``1.x.x`` releases of this collection are compatible with openstacksdk ``0.x.x``
|
||||
prior to ``0.99.0`` *only*,\n* ``2.x.x`` releases of are not backward compatible
|
||||
with ``1.x.x`` releases,\n* ``1.x.x`` release series will be in maintenance
|
||||
mode now and receive bugfixes only.\n\nHowever, this collection as well as
|
||||
openstacksdk continue to be backward compatible with clouds running on older
|
||||
OpenStack releases. For example, it is fine and a fully supported use case
|
||||
to use this 2.0.0 release with clouds based on OpenStack Train, Wallaby or
|
||||
Zed. Feel encouraged to always use the latest releases of this collection
|
||||
and openstacksdk regardless of which version of OpenStack is installed in
|
||||
your cloud.\n\nThis collection is compatible with and tested with Ansible
|
||||
2.9 and later. However, support for old ``os_*`` short module names such as
|
||||
``os_server`` have been dropped with this release. You have to call modules
|
||||
using their FQCN (Fully-Qualified Collection Name) such as ``openstack.cloud.server``
|
||||
instead.\n\nMany thanks to all contributors who made this release possible.
|
||||
Tens of thousands LOCs have been reviewed and changed and fixed and tested
|
||||
throughout last year. You rock!"
|
||||
removed_features:
|
||||
- Dropped deprecated ``skip_update_of_driver_password`` option from module ``openstack.cloud.baremetal_node``.
|
||||
- Dropped unmaintained, obsolete and broken inventory script ``scripts/inventory/openstack_inventory.py``.
|
||||
It had been replaced with a proper Ansible inventory plugin ``openstack.cloud.openstack``
|
||||
during the 1.x.x life cycle.
|
||||
- Module ``openstack.cloud.object`` no longer allows to create and delete containers,
|
||||
its sole purpose is managing an object in a container now. Use module ``openstack.cloud.object_container``
|
||||
to managing Swift containers instead.
|
||||
- Option ``listeners`` has been removed from module ``openstack.cloud.loadbalancer``
|
||||
because it duplicates a subset of the functionality (and code) provided by
|
||||
our ``openstack.cloud.lb_{listener,member,pool}`` modules.
|
||||
- Our outdated, undocumented, untested and bloated code templates in ``contrib``
|
||||
directory which could be used to generate and develop new Ansible modules
|
||||
for this collection have been removed.
|
||||
release_date: '2023-01-31'
|
||||
2.1.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Fix collection guidelines
|
||||
release_summary: Bugfixes
|
||||
release_date: '2022-03-10'
|
||||
1.8.0:
|
||||
- Change security group rules only when instructed to do so
|
||||
- 'Fix for AttributeError: ''dict'' object has no attribute ''status'''
|
||||
- Fix issue with multiple records in recordset
|
||||
- Fix mistake in compute_flavor_access notes
|
||||
- Fixed private option in inventory plugin
|
||||
- Respect description option and delete security group rules first
|
||||
- Use true and false instead of yes and no for boolean values
|
||||
minor_changes:
|
||||
- Add baremetal_deploy_template module
|
||||
- Highlight our mode of operation more prominently
|
||||
release_summary: New module for Ironic and bugfixes
|
||||
release_date: '2023-04-19'
|
||||
2.2.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
|
||||
- Fix image module filter
|
||||
- Fix port module idempotency
|
||||
- Fix router module idempotency
|
||||
minor_changes:
|
||||
- Add volume_encryption_type modules
|
||||
- Add volume_type modules
|
||||
release_summary: New module for volume_type and bugfixes
|
||||
release_date: '2023-12-01'
|
||||
2.3.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Allow wait false when auto_ip is false
|
||||
- Fix exception when creating object from file
|
||||
- Fix exception when updating container with metadata
|
||||
- Fix typo in openstack.cloud.lb_pool
|
||||
- Fix typo in parameter description
|
||||
- fix subnet module - allow cidr option with subnet_pool
|
||||
major_changes:
|
||||
- Add Neutron trunk module
|
||||
- Add application_credential module
|
||||
- Add module to filter available volume services
|
||||
minor_changes:
|
||||
- Add inactive state for the images
|
||||
- Add insecure_registry property to coe_cluster_templates
|
||||
- Add support for creation of the default external networks
|
||||
- Add target_all_project option
|
||||
- Add vlan_tranparency for creation networks
|
||||
- Allow munch results in server_info module
|
||||
- Allow to specify multiple allocation pools when creating a subnet
|
||||
- CI - Disable auto-discovery for setuptools
|
||||
- CI - Don't create port with binding profile
|
||||
- CI - Fix CI in collection
|
||||
- CI - Fix linters-devel and devstack tests
|
||||
- CI - Fix regression in quota module
|
||||
- CI - Fix test for server shelve
|
||||
- CI - Migrate Bifrost jobs to Ubuntu Jammy
|
||||
- CI - Remove 2.9 jobs from Zuul config
|
||||
- CI - Run functional testing regardless of pep8/linter results
|
||||
- Enable glance-direct interop image import
|
||||
- Ensure coe_cluster_template compare labels properly
|
||||
- Wait for deleted server to disappear from results
|
||||
- router - Allow specifying external network name in a different project
|
||||
release_summary: Bugfixes and new modules
|
||||
modules:
|
||||
- description: Create or Delete subnet pools from OpenStack.
|
||||
name: subnet_pool
|
||||
- description: Manage OpenStack Identity (Keystone) application credentials
|
||||
name: application_credential
|
||||
namespace: ''
|
||||
release_date: '2022-04-08'
|
||||
- description: Add or delete trunks from an OpenStack cloud
|
||||
name: trunk
|
||||
namespace: ''
|
||||
- description: Fetch OpenStack Volume (Cinder) services
|
||||
name: volume_service_info
|
||||
namespace: ''
|
||||
release_date: '2024-11-28'
|
||||
2.3.1:
|
||||
changes:
|
||||
minor_changes:
|
||||
- Add ability to pass client tls certificate
|
||||
release_summary: Client TLS certificate support
|
||||
release_date: '2024-12-18'
|
||||
2.3.2:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Fix openstack.cloud.port module failure in check mode
|
||||
minor_changes:
|
||||
- Drop compat implementations for tests
|
||||
release_summary: Bugfixes and minor changes
|
||||
release_date: '2024-12-20'
|
||||
2.3.3:
|
||||
changes:
|
||||
bugfixes:
|
||||
- CI - Fix deprecated ANSIBLE_COLLECTIONS_PATHS variable
|
||||
minor_changes:
|
||||
- Add test to only_ipv4 in inventory
|
||||
- add an option to use only IPv4 only for ansible_host and ansible_ssh_host
|
||||
release_summary: Bugfixes and minor changes
|
||||
release_date: '2024-12-22'
|
||||
2.4.0:
|
||||
changes:
|
||||
major_changes:
|
||||
- Add trait module
|
||||
minor_changes:
|
||||
- Add loadbalancer quota options
|
||||
- Allow create instance with tags
|
||||
release_summary: New trait module and minor changes
|
||||
modules:
|
||||
- description: Add or Delete a trait from OpenStack
|
||||
name: trait
|
||||
namespace: ''
|
||||
release_date: '2025-01-15'
|
||||
2.4.1:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Fix missed client_cert in OpenStackModule
|
||||
minor_changes:
|
||||
- Update tags when changing server
|
||||
release_summary: Bugfixes and minor changes
|
||||
release_date: '2024-01-20'
|
||||
|
||||
@@ -6,9 +6,9 @@ ignore_other_fragment_extensions: true
|
||||
keep_fragments: false
|
||||
mention_ancestor: true
|
||||
new_plugins_after_name: removed_features
|
||||
notesdir: fragments
|
||||
prelude_section_name: release_summary
|
||||
prelude_section_title: Release Summary
|
||||
notes_dir: fragments
|
||||
prelude_name: release_summary
|
||||
prelude_title: Release Summary
|
||||
sections:
|
||||
- - major_changes
|
||||
- Major Changes
|
||||
@@ -26,6 +26,6 @@ sections:
|
||||
- Bugfixes
|
||||
- - known_issues
|
||||
- Known Issues
|
||||
title: Openstack Cloud Ansilbe modules
|
||||
title: Ansible OpenStack Collection
|
||||
trivial_section_name: trivial
|
||||
use_fqcn: true
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
- hosts: all
|
||||
tasks:
|
||||
- name: Download amphora tarball
|
||||
get_url:
|
||||
url: "https://tarballs.openstack.org/octavia/test-images/test-only-amphora-x64-haproxy-ubuntu-bionic.qcow2"
|
||||
dest: /tmp/test-only-amphora-x64-haproxy-ubuntu-bionic.qcow2
|
||||
@@ -1,9 +1,10 @@
|
||||
---
|
||||
- hosts: all
|
||||
vars:
|
||||
collection_path: "{{ ansible_user_dir }}/{{ zuul.projects['opendev.org/openstack/ansible-collections-openstack'].src_dir }}"
|
||||
collection_path: "{{ ansible_user_dir }}/{{ zuul.project.src_dir }}"
|
||||
build_collection_path: /tmp/collection_built/
|
||||
ansible_galaxy_path: "~/.local/bin/ansible-galaxy"
|
||||
ansible_virtualenv_path: /tmp/ansible_venv
|
||||
ansible_galaxy_path: "{{ ansible_virtualenv_path }}/bin/ansible-galaxy"
|
||||
|
||||
tasks:
|
||||
|
||||
@@ -11,9 +12,15 @@
|
||||
include_role:
|
||||
name: ensure-pip
|
||||
|
||||
- name: Install ansible
|
||||
- name: Install Ansible in virtualenv
|
||||
pip:
|
||||
name: ansible-core<2.12
|
||||
name: ansible-core<2.19
|
||||
virtualenv: "{{ ansible_virtualenv_path }}"
|
||||
virtualenv_command: "{{ ensure_pip_virtualenv_command }}"
|
||||
|
||||
- name: Detect ansible version
|
||||
command: "{{ ansible_virtualenv_path }}/bin/ansible --version"
|
||||
register: ansible_version
|
||||
|
||||
- name: Discover tag version
|
||||
set_fact:
|
||||
@@ -63,12 +70,21 @@
|
||||
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 }}/openstack-cloud-{{ version_tag }}.tar.gz
|
||||
{{ build_collection_path }}/{{ galaxy_yaml.namespace }}-{{ galaxy_yaml.name }}-{{ version_tag }}.tar.gz
|
||||
|
||||
always:
|
||||
- name: Shred ansible-galaxy credentials
|
||||
|
||||
8
ci/requirements.yml
Normal file
8
ci/requirements.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
collections:
|
||||
- ansible.posix
|
||||
- ansible.utils
|
||||
- name: community.general
|
||||
version: 4.8.8
|
||||
# 5.0.0 dropped compatibility with ansible 2.9 and ansible-base 2.10
|
||||
# Ref.: https://github.com/ansible-collections/community.general/commit/1a9b3214fdf1eaccba5cc9ee210cbc5b5070fe4b
|
||||
@@ -1 +1,8 @@
|
||||
address_scope_name: "adrdess_scope"
|
||||
address_scope_name: "address_scope"
|
||||
expected_fields:
|
||||
- id
|
||||
- ip_version
|
||||
- is_shared
|
||||
- name
|
||||
- project_id
|
||||
- tenant_id
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
ip_version: "4"
|
||||
register: create_address_scope
|
||||
|
||||
- name: Verify returned values
|
||||
assert:
|
||||
that:
|
||||
- item in create_address_scope.address_scope
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- name: Verify address scope
|
||||
assert:
|
||||
that:
|
||||
@@ -37,4 +43,4 @@
|
||||
openstack.cloud.address_scope:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ address_scope_name }}"
|
||||
state: absent
|
||||
state: absent
|
||||
|
||||
9
ci/roles/application_credential/defaults/main.yml
Normal file
9
ci/roles/application_credential/defaults/main.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
expected_fields:
|
||||
- description
|
||||
- expires_at
|
||||
- id
|
||||
- name
|
||||
- project_id
|
||||
- roles
|
||||
- secret
|
||||
- unrestricted
|
||||
61
ci/roles/application_credential/tasks/main.yml
Normal file
61
ci/roles/application_credential/tasks/main.yml
Normal file
@@ -0,0 +1,61 @@
|
||||
---
|
||||
|
||||
- name: Create application credentials
|
||||
openstack.cloud.application_credential:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_creds
|
||||
description: dummy description
|
||||
register: appcred
|
||||
|
||||
- name: Assert return values of application_credential module
|
||||
assert:
|
||||
that:
|
||||
- appcred is changed
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(appcred.application_credential.keys())|length == 0
|
||||
|
||||
- name: Create the application credential again
|
||||
openstack.cloud.application_credential:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_creds
|
||||
description: dummy description
|
||||
register: appcred
|
||||
|
||||
- name: Assert return values of ansible_credential module
|
||||
assert:
|
||||
that:
|
||||
# credentials are immutable so creating twice will cause delete and create
|
||||
- appcred is changed
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(appcred.application_credential.keys())|length == 0
|
||||
|
||||
- name: Update the application credential again
|
||||
openstack.cloud.application_credential:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_creds
|
||||
description: new description
|
||||
register: appcred
|
||||
|
||||
- name: Assert application credential changed
|
||||
assert:
|
||||
that:
|
||||
- appcred is changed
|
||||
- appcred.application_credential.description == 'new description'
|
||||
|
||||
- name: Get list of all keypairs using application credential
|
||||
openstack.cloud.keypair_info:
|
||||
cloud: "{{ appcred.cloud }}"
|
||||
|
||||
- name: Delete application credential
|
||||
openstack.cloud.application_credential:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_creds
|
||||
register: appcred
|
||||
|
||||
- name: Assert application credential changed
|
||||
assert:
|
||||
that: appcred is changed
|
||||
2
ci/roles/auth/defaults/main.yml
Normal file
2
ci/roles/auth/defaults/main.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
expected_fields:
|
||||
- auth_token
|
||||
@@ -2,5 +2,10 @@
|
||||
- name: Authenticate to the cloud
|
||||
openstack.cloud.auth:
|
||||
cloud={{ cloud }}
|
||||
register: auth
|
||||
|
||||
- debug: var=service_catalog
|
||||
- name: Assert return values of auth module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(auth.keys())|length == 0
|
||||
|
||||
7
ci/roles/baremetal_deploy_template/defaults/main.yml
Normal file
7
ci/roles/baremetal_deploy_template/defaults/main.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
expected_fields:
|
||||
- created_at
|
||||
- extra
|
||||
- id
|
||||
- name
|
||||
- steps
|
||||
- updated_at
|
||||
58
ci/roles/baremetal_deploy_template/tasks/main.yml
Normal file
58
ci/roles/baremetal_deploy_template/tasks/main.yml
Normal file
@@ -0,0 +1,58 @@
|
||||
---
|
||||
# TODO: Actually run this role in CI. Atm we do not have DevStack's ironic plugin enabled.
|
||||
- name: Create baremetal deploy template
|
||||
openstack.cloud.baremetal_deploy_template:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: CUSTOM_ANSIBLE_DEPLOY_TEMPLATE
|
||||
steps:
|
||||
- interface: bios
|
||||
step: apply_configuration
|
||||
args:
|
||||
settings:
|
||||
- name: some-setting
|
||||
value: some-value
|
||||
priority: 110
|
||||
register: template
|
||||
|
||||
- debug: var=template
|
||||
|
||||
- name: Assert return values of baremetal_deploy_template module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(template.template.keys())|length == 0
|
||||
|
||||
- name: Update baremetal deploy template
|
||||
openstack.cloud.baremetal_deploy_template:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
id: "{{ template.template.id }}"
|
||||
extra:
|
||||
foo: bar
|
||||
register: updated_template
|
||||
|
||||
- name: Assert return values of updated baremetal deploy template
|
||||
assert:
|
||||
that:
|
||||
- updated_template is changed
|
||||
- updated_template.template.id == template.template.id
|
||||
|
||||
- name: Update baremetal deploy template again
|
||||
openstack.cloud.baremetal_deploy_template:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
id: "{{ template.template.id }}"
|
||||
register: updated_template
|
||||
|
||||
- name: Assert return values of updated baremetal deploy template
|
||||
assert:
|
||||
that:
|
||||
- updated_template is not changed
|
||||
- updated_template.template.id == template.template.id
|
||||
|
||||
- name: Delete Bare Metal deploy template
|
||||
openstack.cloud.baremetal_deploy_template:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
id: "{{ template.template.id }}"
|
||||
56
ci/roles/baremetal_inspect/defaults/main.yml
Normal file
56
ci/roles/baremetal_inspect/defaults/main.yml
Normal file
@@ -0,0 +1,56 @@
|
||||
expected_fields:
|
||||
- allocation_id
|
||||
- bios_interface
|
||||
- boot_interface
|
||||
- boot_mode
|
||||
- chassis_id
|
||||
- clean_step
|
||||
- conductor
|
||||
- conductor_group
|
||||
- console_interface
|
||||
- created_at
|
||||
- deploy_interface
|
||||
- deploy_step
|
||||
- driver
|
||||
- driver_info
|
||||
- driver_internal_info
|
||||
- extra
|
||||
- fault
|
||||
- id
|
||||
- inspect_interface
|
||||
- instance_id
|
||||
- instance_info
|
||||
- is_automated_clean_enabled
|
||||
- is_console_enabled
|
||||
- is_maintenance
|
||||
- is_protected
|
||||
- is_retired
|
||||
- is_secure_boot
|
||||
- last_error
|
||||
- links
|
||||
- maintenance_reason
|
||||
- management_interface
|
||||
- name
|
||||
- network_interface
|
||||
- owner
|
||||
- port_groups
|
||||
- ports
|
||||
- power_interface
|
||||
- power_state
|
||||
- properties
|
||||
- protected_reason
|
||||
- provision_state
|
||||
- raid_config
|
||||
- raid_interface
|
||||
- rescue_interface
|
||||
- reservation
|
||||
- resource_class
|
||||
- retired_reason
|
||||
- states
|
||||
- storage_interface
|
||||
- target_power_state
|
||||
- target_provision_state
|
||||
- target_raid_config
|
||||
- traits
|
||||
- updated_at
|
||||
- vendor_interface
|
||||
15
ci/roles/baremetal_inspect/tasks/main.yml
Normal file
15
ci/roles/baremetal_inspect/tasks/main.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
# TODO: Actually run this role in CI. Atm we do not have DevStack's ironic plugin enabled.
|
||||
- name: Introspect node
|
||||
openstack.cloud.baremetal_inspect:
|
||||
cloud: "{{ cloud }}"
|
||||
name: node-1
|
||||
register: inspect
|
||||
|
||||
- debug: var=inspect
|
||||
|
||||
- name: assert return values of baremetal_inspect module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(inspect.node.keys())|length == 0
|
||||
56
ci/roles/baremetal_node/defaults/main.yml
Normal file
56
ci/roles/baremetal_node/defaults/main.yml
Normal file
@@ -0,0 +1,56 @@
|
||||
expected_fields:
|
||||
- allocation_id
|
||||
- bios_interface
|
||||
- boot_interface
|
||||
- boot_mode
|
||||
- chassis_id
|
||||
- clean_step
|
||||
- conductor
|
||||
- conductor_group
|
||||
- console_interface
|
||||
- created_at
|
||||
- deploy_interface
|
||||
- deploy_step
|
||||
- driver
|
||||
- driver_info
|
||||
- driver_internal_info
|
||||
- extra
|
||||
- fault
|
||||
- id
|
||||
- inspect_interface
|
||||
- instance_id
|
||||
- instance_info
|
||||
- is_automated_clean_enabled
|
||||
- is_console_enabled
|
||||
- is_maintenance
|
||||
- is_protected
|
||||
- is_retired
|
||||
- is_secure_boot
|
||||
- last_error
|
||||
- links
|
||||
- maintenance_reason
|
||||
- management_interface
|
||||
- name
|
||||
- network_interface
|
||||
- owner
|
||||
- port_groups
|
||||
- ports
|
||||
- power_interface
|
||||
- power_state
|
||||
- properties
|
||||
- protected_reason
|
||||
- provision_state
|
||||
- raid_config
|
||||
- raid_interface
|
||||
- rescue_interface
|
||||
- reservation
|
||||
- resource_class
|
||||
- retired_reason
|
||||
- states
|
||||
- storage_interface
|
||||
- target_power_state
|
||||
- target_provision_state
|
||||
- target_raid_config
|
||||
- traits
|
||||
- updated_at
|
||||
- vendor_interface
|
||||
74
ci/roles/baremetal_node/tasks/main.yml
Normal file
74
ci/roles/baremetal_node/tasks/main.yml
Normal file
@@ -0,0 +1,74 @@
|
||||
---
|
||||
# TODO: Actually run this role in CI. Atm we do not have DevStack's ironic plugin enabled.
|
||||
- name: Create baremetal node
|
||||
openstack.cloud.baremetal_node:
|
||||
cloud: "{{ cloud }}"
|
||||
driver_info:
|
||||
ipmi_address: "1.2.3.4"
|
||||
ipmi_username: "admin"
|
||||
ipmi_password: "secret"
|
||||
name: ansible_baremetal_node
|
||||
nics:
|
||||
- mac: "aa:bb:cc:aa:bb:cc"
|
||||
state: present
|
||||
register: node
|
||||
|
||||
- debug: var=node
|
||||
|
||||
- name: assert return values of baremetal_node module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(node.node.keys())|length == 0
|
||||
|
||||
- name: Fetch baremetal nodes
|
||||
openstack.cloud.baremetal_node_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: nodes
|
||||
|
||||
- name: assert module results of baremetal_node_info module
|
||||
assert:
|
||||
that:
|
||||
- nodes.nodes|list|length > 0
|
||||
|
||||
- name: assert return values of baremetal_node_info module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(nodes.nodes.0.keys())|length == 0
|
||||
|
||||
- name: Fetch baremetal node by name
|
||||
openstack.cloud.baremetal_node_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_baremetal_node
|
||||
register: nodes
|
||||
|
||||
- name: assert module results of baremetal_node_info module
|
||||
assert:
|
||||
that:
|
||||
- nodes.nodes|list|length == 1
|
||||
- nodes.nodes.0.id == node.node.id
|
||||
- nodes.nodes.0.name == "ansible_baremetal_node"
|
||||
|
||||
- name: Delete baremetal node
|
||||
openstack.cloud.baremetal_node:
|
||||
cloud: "{{ cloud }}"
|
||||
driver_info:
|
||||
ipmi_address: "1.2.3.4"
|
||||
ipmi_username: "admin"
|
||||
ipmi_password: "secret"
|
||||
name: ansible_baremetal_node
|
||||
nics:
|
||||
- mac: "aa:bb:cc:aa:bb:cc"
|
||||
state: absent
|
||||
|
||||
- name: Fetch baremetal node by name
|
||||
openstack.cloud.baremetal_node_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_baremetal_node
|
||||
register: nodes
|
||||
|
||||
- name: Assert that baremetal node has been deleted
|
||||
assert:
|
||||
that:
|
||||
- nodes.nodes|list|length == 0
|
||||
14
ci/roles/baremetal_port/defaults/main.yml
Normal file
14
ci/roles/baremetal_port/defaults/main.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
expected_fields:
|
||||
- address
|
||||
- created_at
|
||||
- extra
|
||||
- id
|
||||
- internal_info
|
||||
- is_pxe_enabled
|
||||
- links
|
||||
- local_link_connection
|
||||
- name
|
||||
- node_id
|
||||
- physical_network
|
||||
- port_group_id
|
||||
- updated_at
|
||||
112
ci/roles/baremetal_port/tasks/main.yml
Normal file
112
ci/roles/baremetal_port/tasks/main.yml
Normal file
@@ -0,0 +1,112 @@
|
||||
---
|
||||
# TODO: Actually run this role in CI. Atm we do not have DevStack's ironic plugin enabled.
|
||||
- name: Create baremetal node
|
||||
openstack.cloud.baremetal_node:
|
||||
cloud: "{{ cloud }}"
|
||||
driver_info:
|
||||
ipmi_address: "1.2.3.4"
|
||||
ipmi_username: "admin"
|
||||
ipmi_password: "secret"
|
||||
name: ansible_baremetal_node
|
||||
nics:
|
||||
- mac: "aa:bb:cc:aa:bb:cc"
|
||||
state: present
|
||||
register: node
|
||||
|
||||
- name: Create baremetal port
|
||||
openstack.cloud.baremetal_port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
node: ansible_baremetal_node
|
||||
address: fa:16:3e:aa:aa:aa
|
||||
is_pxe_enabled: False
|
||||
register: port
|
||||
|
||||
- debug: var=port
|
||||
|
||||
- name: Assert return values of baremetal_port module
|
||||
assert:
|
||||
that:
|
||||
- not port.port.is_pxe_enabled
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(port.port.keys())|length == 0
|
||||
|
||||
- name: Fetch baremetal ports
|
||||
openstack.cloud.baremetal_port_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: ports
|
||||
|
||||
- name: Assert module results of baremetal_port_info module
|
||||
assert:
|
||||
that:
|
||||
- ports.ports|list|length > 0
|
||||
|
||||
- name: assert return values of baremetal_port_info module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(ports.ports.0.keys())|length == 0
|
||||
|
||||
- name: Fetch baremetal port by id
|
||||
openstack.cloud.baremetal_port_info:
|
||||
cloud: "{{ cloud }}"
|
||||
id: "{{ port.port.id }}"
|
||||
register: ports
|
||||
|
||||
- name: assert module results of baremetal_port_info module
|
||||
assert:
|
||||
that:
|
||||
- ports.ports|list|length == 1
|
||||
- ports.ports.0.id == port.port.id
|
||||
|
||||
- name: Update baremetal port
|
||||
openstack.cloud.baremetal_port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
id: "{{ port.port.id }}"
|
||||
is_pxe_enabled: True
|
||||
register: updated_port
|
||||
|
||||
- name: Assert return values of updated baremetal port
|
||||
assert:
|
||||
that:
|
||||
- update_port is changed
|
||||
- update_port.port.id == port.port.id
|
||||
- update_port.port.address == port.port.address
|
||||
- update_port.port.is_pxe_enabled
|
||||
|
||||
- name: Update baremetal port again
|
||||
openstack.cloud.baremetal_port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
id: "{{ port.port.id }}"
|
||||
is_pxe_enabled: True
|
||||
register: updated_port
|
||||
|
||||
- name: Assert return values of updated baremetal port
|
||||
assert:
|
||||
that:
|
||||
- update_port is not changed
|
||||
- update_port.port.id == port.port.id
|
||||
|
||||
- name: Delete Bare Metal port
|
||||
openstack.cloud.baremetal_port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
id: "{{ port.port.id }}"
|
||||
|
||||
- name: Fetch baremetal ports
|
||||
openstack.cloud.baremetal_port_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: ports
|
||||
|
||||
- name: Assert no baremetal port is left
|
||||
assert:
|
||||
that:
|
||||
- ports.ports|list|length == 0
|
||||
|
||||
- name: Delete baremetal node
|
||||
openstack.cloud.baremetal_node:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_baremetal_node
|
||||
state: absent
|
||||
7
ci/roles/catalog_service/defaults/main.yml
Normal file
7
ci/roles/catalog_service/defaults/main.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
expected_fields:
|
||||
- description
|
||||
- id
|
||||
- is_enabled
|
||||
- links
|
||||
- name
|
||||
- type
|
||||
103
ci/roles/catalog_service/tasks/main.yml
Normal file
103
ci/roles/catalog_service/tasks/main.yml
Normal file
@@ -0,0 +1,103 @@
|
||||
---
|
||||
- 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: "{{ expected_fields }}"
|
||||
|
||||
- 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: "{{ expected_fields }}"
|
||||
|
||||
- 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 is_enabled were updated
|
||||
assert:
|
||||
that:
|
||||
- service_test.service.description == "A new description"
|
||||
- not (service_test.service.is_enabled|bool)
|
||||
|
||||
- name: Get all services
|
||||
openstack.cloud.catalog_service_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: services
|
||||
|
||||
- name: Assert return values of catalog_service_info module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(services.services[0].keys())|length == 0
|
||||
|
||||
- name: Get service by name
|
||||
openstack.cloud.catalog_service_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: test
|
||||
register: services
|
||||
|
||||
- name: Assert services returned by catalog_service_info module
|
||||
assert:
|
||||
that:
|
||||
- services.services|length == 1
|
||||
- services.services[0].id == service_test.service.id
|
||||
|
||||
- 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
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
- name: List all profiles
|
||||
openstack.cloud.config:
|
||||
register: list
|
||||
|
||||
# WARNING: This will output sensitive authentication information!!!!
|
||||
- debug: var=list
|
||||
26
ci/roles/coe_cluster/defaults/main.yml
Normal file
26
ci/roles/coe_cluster/defaults/main.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
expected_fields:
|
||||
- api_address
|
||||
- cluster_template_id
|
||||
- coe_version
|
||||
- create_timeout
|
||||
- created_at
|
||||
- discovery_url
|
||||
- fixed_network
|
||||
- fixed_subnet
|
||||
- flavor_id
|
||||
- id
|
||||
- is_floating_ip_enabled
|
||||
- is_master_lb_enabled
|
||||
- keypair
|
||||
- labels
|
||||
- master_addresses
|
||||
- master_count
|
||||
- master_flavor_id
|
||||
- name
|
||||
- node_addresses
|
||||
- node_count
|
||||
- stack_id
|
||||
- status
|
||||
- status_reason
|
||||
- updated_at
|
||||
- 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
|
||||
image_id: '{{ image_id }}'
|
||||
is_floating_ip_enabled: true
|
||||
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:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|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
|
||||
33
ci/roles/coe_cluster_template/defaults/main.yml
Normal file
33
ci/roles/coe_cluster_template/defaults/main.yml
Normal file
@@ -0,0 +1,33 @@
|
||||
expected_fields:
|
||||
- apiserver_port
|
||||
- cluster_distro
|
||||
- coe
|
||||
- created_at
|
||||
- dns_nameserver
|
||||
- docker_storage_driver
|
||||
- docker_volume_size
|
||||
- external_network_id
|
||||
- fixed_network
|
||||
- fixed_subnet
|
||||
- flavor_id
|
||||
- http_proxy
|
||||
- https_proxy
|
||||
- id
|
||||
- image_id
|
||||
- insecure_registry
|
||||
- is_floating_ip_enabled
|
||||
- is_hidden
|
||||
- is_master_lb_enabled
|
||||
- is_public
|
||||
- is_registry_enabled
|
||||
- is_tls_disabled
|
||||
- keypair_id
|
||||
- labels
|
||||
- master_flavor_id
|
||||
- name
|
||||
- network_driver
|
||||
- no_proxy
|
||||
- server_type
|
||||
- updated_at
|
||||
- uuid
|
||||
- volume_driver
|
||||
87
ci/roles/coe_cluster_template/tasks/main.yml
Normal file
87
ci/roles/coe_cluster_template/tasks/main.yml
Normal file
@@ -0,0 +1,87 @@
|
||||
---
|
||||
- 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
|
||||
is_floating_ip_enabled: false
|
||||
image_id: '{{ image_id }}'
|
||||
keypair_id: '{{ keypair.keypair.id }}'
|
||||
name: k8s
|
||||
state: present
|
||||
labels:
|
||||
docker_volume_size: 10
|
||||
cloud_provider_tag: v1.23.1
|
||||
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
|
||||
is_floating_ip_enabled: false
|
||||
image_id: '{{ image_id }}'
|
||||
keypair_id: '{{ keypair.keypair.id }}'
|
||||
name: k8s
|
||||
state: present
|
||||
labels:
|
||||
docker_volume_size: 10
|
||||
cloud_provider_tag: v1.23.1
|
||||
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
|
||||
14
ci/roles/compute_flavor/defaults/main.yml
Normal file
14
ci/roles/compute_flavor/defaults/main.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
expected_fields:
|
||||
- description
|
||||
- disk
|
||||
- ephemeral
|
||||
- extra_specs
|
||||
- id
|
||||
- is_disabled
|
||||
- is_public
|
||||
- name
|
||||
- original_name
|
||||
- ram
|
||||
- rxtx_factor
|
||||
- swap
|
||||
- vcpus
|
||||
254
ci/roles/compute_flavor/tasks/main.yml
Normal file
254
ci/roles/compute_flavor/tasks/main.yml
Normal file
@@ -0,0 +1,254 @@
|
||||
---
|
||||
- name: Delete resources before tests
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ item }}"
|
||||
loop:
|
||||
- ansible_public_flavor
|
||||
- ansible_private_flavor
|
||||
- ansible_extra_specs_flavor
|
||||
- ansible_defaults_flavor
|
||||
|
||||
- name: Create public flavor
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_public_flavor
|
||||
is_public: True
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
ephemeral: 10
|
||||
swap: 1
|
||||
id: 12345
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that: item in result.flavor
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that: result is changed
|
||||
|
||||
- name: Create public flavor again
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_public_flavor
|
||||
is_public: True
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
ephemeral: 10
|
||||
swap: 1
|
||||
id: 12345
|
||||
register: result
|
||||
|
||||
- name: Assert not changed
|
||||
assert:
|
||||
that: result is not changed
|
||||
|
||||
- name: Delete public flavor
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_public_flavor
|
||||
register: result
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that: result is changed
|
||||
|
||||
- name: Delete public flavor again
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_public_flavor
|
||||
register: result
|
||||
|
||||
- name: Assert not changed
|
||||
assert:
|
||||
that: result is not changed
|
||||
|
||||
- name: Create private flavor
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_private_flavor
|
||||
is_public: False
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
ephemeral: 10
|
||||
swap: 1
|
||||
id: 12345
|
||||
|
||||
- name: Delete private flavor
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_private_flavor
|
||||
|
||||
- name: Create flavor (defaults)
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_defaults_flavor
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
register: result
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that: result is changed
|
||||
|
||||
- name: Create flavor (defaults) again
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_defaults_flavor
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
register: result
|
||||
|
||||
- name: Assert not changed
|
||||
assert:
|
||||
that: result is not changed
|
||||
|
||||
- name: Delete flavor (defaults)
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_defaults_flavor
|
||||
|
||||
- name: Create flavor (extra_specs)
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_extra_specs_flavor
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
extra_specs:
|
||||
"os:secure_boot": "required"
|
||||
register: result
|
||||
|
||||
- name: Assert returned value
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.flavor.extra_specs['os:secure_boot'] == 'required'
|
||||
|
||||
- name: Create flavor (extra_specs) again
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_extra_specs_flavor
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
extra_specs:
|
||||
"os:secure_boot": "required"
|
||||
register: result
|
||||
|
||||
- name: Assert not changed
|
||||
assert:
|
||||
that: result is not changed
|
||||
|
||||
- name: Change extra_specs value
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_extra_specs_flavor
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
extra_specs:
|
||||
"os:secure_boot": "disabled"
|
||||
register: result
|
||||
|
||||
- name: Assert returned value
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.flavor.extra_specs['os:secure_boot'] == 'disabled'
|
||||
|
||||
- name: Append extra_specs value
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_extra_specs_flavor
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
extra_specs:
|
||||
"os:secure_boot": "disabled"
|
||||
"hw_video:ram_max_mb": 200
|
||||
register: result
|
||||
|
||||
- name: Assert returned value
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.flavor.extra_specs | length == 2
|
||||
- "'os:secure_boot' in result.flavor.extra_specs"
|
||||
- "'hw_video:ram_max_mb' in result.flavor.extra_specs"
|
||||
|
||||
- name: Drop extra_specs value
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_extra_specs_flavor
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
extra_specs:
|
||||
"hw_video:ram_max_mb": 200
|
||||
register: result
|
||||
|
||||
- name: Assert returned value
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.flavor.extra_specs | length == 1
|
||||
- "'hw_video:ram_max_mb' in result.flavor.extra_specs"
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that: result is changed
|
||||
|
||||
- name: Clean up
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ item }}"
|
||||
loop:
|
||||
- ansible_public_flavor
|
||||
- ansible_private_flavor
|
||||
- ansible_extra_specs_flavor
|
||||
- ansible_defaults_flavor
|
||||
|
||||
- name: List flavors
|
||||
openstack.cloud.compute_flavor_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: flavor_info
|
||||
|
||||
- assert:
|
||||
that: item in flavor_info.flavors[0]
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- 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.flavors | length == 1
|
||||
- flavor.flavors.0.name == "m1.tiny"
|
||||
96
ci/roles/compute_flavor_access/tasks/main.yml
Normal file
96
ci/roles/compute_flavor_access/tasks/main.yml
Normal file
@@ -0,0 +1,96 @@
|
||||
---
|
||||
- name: Create flavor
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: devstack-admin
|
||||
state: present
|
||||
name: ansible_flavor
|
||||
is_public: False
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
ephemeral: 10
|
||||
swap: 1
|
||||
register: flavor
|
||||
|
||||
- name: Fetch demo project
|
||||
openstack.cloud.project_info:
|
||||
cloud: devstack-admin
|
||||
name: demo
|
||||
register: projects
|
||||
|
||||
- name: Verify demo project
|
||||
assert:
|
||||
that:
|
||||
- projects.projects|length == 1
|
||||
- projects.projects.0.name == "demo"
|
||||
|
||||
- name: Grant access to flavor
|
||||
openstack.cloud.compute_flavor_access:
|
||||
cloud: devstack-admin
|
||||
name: ansible_flavor
|
||||
project: demo
|
||||
state: present
|
||||
register: access
|
||||
|
||||
- name: Verify access
|
||||
assert:
|
||||
that:
|
||||
- access is changed
|
||||
- access.flavor.id == flavor.flavor.id
|
||||
|
||||
# TODO: Replace with appropriate Ansible module once available
|
||||
- name: Get compute flavor
|
||||
command: openstack --os-cloud=devstack-admin flavor show ansible_flavor -f json
|
||||
register: flavor_show
|
||||
|
||||
- name: Verify volume type access
|
||||
assert:
|
||||
that:
|
||||
- (flavor_show.stdout | from_json).name == 'ansible_flavor'
|
||||
- projects.projects.0.id in (flavor_show.stdout | from_json).access_project_ids
|
||||
|
||||
- name: Grant access to flavor again
|
||||
openstack.cloud.compute_flavor_access:
|
||||
cloud: devstack-admin
|
||||
name: ansible_flavor
|
||||
project: demo
|
||||
state: present
|
||||
register: access
|
||||
|
||||
- name: Verify access did not change
|
||||
assert:
|
||||
that:
|
||||
- access is not changed
|
||||
|
||||
- name: Revoke access to flavor
|
||||
openstack.cloud.compute_flavor_access:
|
||||
cloud: devstack-admin
|
||||
name: ansible_flavor
|
||||
project: demo
|
||||
state: absent
|
||||
register: access
|
||||
|
||||
- name: Verify revoked access
|
||||
assert:
|
||||
that:
|
||||
- access is changed
|
||||
- access.flavor.id == flavor.flavor.id
|
||||
|
||||
- name: Revoke access to flavor again
|
||||
openstack.cloud.compute_flavor_access:
|
||||
cloud: devstack-admin
|
||||
name: ansible_flavor
|
||||
project: demo
|
||||
state: absent
|
||||
register: access
|
||||
|
||||
- name: Verify access did not change
|
||||
assert:
|
||||
that:
|
||||
- access is not changed
|
||||
|
||||
- name: Delete flavor
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: devstack-admin
|
||||
state: absent
|
||||
name: ansible_flavor
|
||||
@@ -1,33 +0,0 @@
|
||||
---
|
||||
- name: List flavors
|
||||
openstack.cloud.compute_flavor_info:
|
||||
cloud: "{{ cloud }}"
|
||||
|
||||
- name: List flavors with filter
|
||||
openstack.cloud.compute_flavor_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "m1.tiny"
|
||||
register: flavor_name
|
||||
|
||||
- name: Check output of list flavors with filter
|
||||
assert:
|
||||
that:
|
||||
- flavor_name.openstack_flavors | length == 1
|
||||
|
||||
- name: Assert fields on SDK 0.*
|
||||
when: sdk_version is version(1.0, '<')
|
||||
assert:
|
||||
that:
|
||||
- '["name", "description", "disk", "is_public", "ram",
|
||||
"vcpus", "swap", "ephemeral", "is_disabled", "rxtx_factor", "id",
|
||||
"extra_specs"] | difference(flavor_name.openstack_flavors.0.keys())
|
||||
| length == 0'
|
||||
|
||||
- name: Assert fields on SDK 1.*
|
||||
when: sdk_version is version(1.0, '>=')
|
||||
assert:
|
||||
that:
|
||||
- '["name", "original_name", "description", "disk", "is_public", "ram",
|
||||
"vcpus", "swap", "ephemeral", "is_disabled", "rxtx_factor", "id",
|
||||
"extra_specs"] | difference(flavor_name.openstack_flavors.0.keys())
|
||||
| length == 0'
|
||||
11
ci/roles/compute_service/defaults/main.yml
Normal file
11
ci/roles/compute_service/defaults/main.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
expected_fields:
|
||||
- availability_zone
|
||||
- binary
|
||||
- disabled_reason
|
||||
- host
|
||||
- id
|
||||
- is_forced_down
|
||||
- name
|
||||
- state
|
||||
- status
|
||||
- updated_at
|
||||
23
ci/roles/compute_service/tasks/main.yml
Normal file
23
ci/roles/compute_service/tasks/main.yml
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
- name: Fetch compute services
|
||||
openstack.cloud.compute_service_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: compute_services
|
||||
|
||||
- name: Assert return values of compute_service_info module
|
||||
assert:
|
||||
that:
|
||||
- compute_services.compute_services | length > 0
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(compute_services.compute_services[0].keys())|length == 0
|
||||
|
||||
- name: Fetch compute services with filters
|
||||
openstack.cloud.compute_service_info:
|
||||
cloud: "{{ cloud }}"
|
||||
binary: "nova-compute"
|
||||
register: compute_services
|
||||
|
||||
- name: Assert return values of compute_service_info module
|
||||
assert:
|
||||
that:
|
||||
- compute_services.compute_services | length > 0
|
||||
10
ci/roles/config/tasks/main.yml
Normal file
10
ci/roles/config/tasks/main.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
- name: List all cloud profiles
|
||||
openstack.cloud.config:
|
||||
register: config
|
||||
# WARNING: This will output sensitive authentication information!!!!
|
||||
|
||||
- name: Assert config module
|
||||
assert:
|
||||
that:
|
||||
- cloud in (config.clouds | map(attribute='name') | list)
|
||||
@@ -1,4 +0,0 @@
|
||||
dns_zone_name: test.dns.zone.
|
||||
recordset_name: testrecordset.test.dns.zone.
|
||||
records: ['10.0.0.0']
|
||||
updated_records: ['10.1.1.1']
|
||||
@@ -1,79 +0,0 @@
|
||||
---
|
||||
- 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: Create a recordset
|
||||
openstack.cloud.recordset:
|
||||
cloud: "{{ cloud }}"
|
||||
zone: "{{ updated_dns_zone.zone.name }}"
|
||||
name: "{{ recordset_name }}"
|
||||
recordset_type: "a"
|
||||
records: "{{ records }}"
|
||||
register: recordset
|
||||
|
||||
- name: Verify recordset info
|
||||
assert:
|
||||
that:
|
||||
- recordset["recordset"].name == recordset_name
|
||||
- recordset["recordset"].zone_name == dns_zone.zone.name
|
||||
- recordset["recordset"].records == records
|
||||
|
||||
- name: Update a recordset
|
||||
openstack.cloud.recordset:
|
||||
cloud: "{{ cloud }}"
|
||||
zone: "{{ updated_dns_zone.zone.name }}"
|
||||
name: "{{ recordset_name }}"
|
||||
recordset_type: "a"
|
||||
records: "{{ updated_records }}"
|
||||
description: "new test recordset"
|
||||
register: updated_recordset
|
||||
|
||||
- name: Verify recordset info
|
||||
assert:
|
||||
that:
|
||||
- updated_recordset["recordset"].zone_name == dns_zone.zone.name
|
||||
- updated_recordset["recordset"].name == recordset_name
|
||||
- updated_recordset["recordset"].records == updated_records
|
||||
|
||||
- name: Delete recordset
|
||||
openstack.cloud.recordset:
|
||||
cloud: "{{ cloud }}"
|
||||
zone: "{{ updated_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 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
|
||||
17
ci/roles/dns_zone/defaults/main.yml
Normal file
17
ci/roles/dns_zone/defaults/main.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
expected_fields:
|
||||
- action
|
||||
- attributes
|
||||
- created_at
|
||||
- description
|
||||
- email
|
||||
- id
|
||||
- links
|
||||
- masters
|
||||
- name
|
||||
- pool_id
|
||||
- project_id
|
||||
- serial
|
||||
- status
|
||||
- ttl
|
||||
- type
|
||||
- updated_at
|
||||
67
ci/roles/dns_zone/tasks/main.yml
Normal file
67
ci/roles/dns_zone/tasks/main.yml
Normal file
@@ -0,0 +1,67 @@
|
||||
---
|
||||
- name: Create dns zone
|
||||
openstack.cloud.dns_zone:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible.test.zone.
|
||||
type: primary
|
||||
email: test@example.net
|
||||
register: dns_zone
|
||||
|
||||
- name: Assert return values of dns_zone module
|
||||
assert:
|
||||
that:
|
||||
- dns_zone.zone.name == "ansible.test.zone."
|
||||
- dns_zone.zone.type|lower == "primary"
|
||||
- dns_zone.zone.email == "test@example.net"
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(dns_zone.zone.keys())|length == 0
|
||||
|
||||
- name: Update dns zone
|
||||
openstack.cloud.dns_zone:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible.test.zone.
|
||||
description: "Another description"
|
||||
register: dns_zone
|
||||
|
||||
- name: Assert return values of dns_zone module
|
||||
assert:
|
||||
that:
|
||||
- dns_zone.zone.description == "Another description"
|
||||
|
||||
- name: Fetch all dns zones
|
||||
openstack.cloud.dns_zone_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: dns_zones
|
||||
|
||||
- name: Assert return values of dns_zone_info module
|
||||
assert:
|
||||
that:
|
||||
- dns_zones is not changed
|
||||
- dns_zones | length > 0
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(dns_zones.zones[0].keys())|length == 0
|
||||
|
||||
- name: Fetch a dns zone by name
|
||||
openstack.cloud.dns_zone_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible.test.zone.
|
||||
register: dns_zones
|
||||
|
||||
- name: Assert return values of dns_zone_info module
|
||||
assert:
|
||||
that:
|
||||
- dns_zones is not changed
|
||||
- dns_zones.zones | length == 1
|
||||
- dns_zones.zones[0].id == dns_zone.zone.id
|
||||
|
||||
- name: Delete dns zone
|
||||
openstack.cloud.dns_zone:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible.test.zone.
|
||||
state: absent
|
||||
register: dns_zone
|
||||
|
||||
- name: Verify dns zone
|
||||
assert:
|
||||
that:
|
||||
- dns_zone is changed
|
||||
@@ -1,41 +0,0 @@
|
||||
---
|
||||
- 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: Drop created dns zone
|
||||
openstack.cloud.dns_zone:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ (prefix + '.test.zone.') }}"
|
||||
state: absent
|
||||
9
ci/roles/endpoint/defaults/main.yaml
Normal file
9
ci/roles/endpoint/defaults/main.yaml
Normal file
@@ -0,0 +1,9 @@
|
||||
expected_fields:
|
||||
- id
|
||||
- interface
|
||||
- is_enabled
|
||||
- links
|
||||
- name
|
||||
- region_id
|
||||
- service_id
|
||||
- url
|
||||
68
ci/roles/endpoint/tasks/main.yml
Normal file
68
ci/roles/endpoint/tasks/main.yml
Normal file
@@ -0,0 +1,68 @@
|
||||
---
|
||||
- name: Create a service endpoint for compute
|
||||
openstack.cloud.endpoint:
|
||||
cloud: "{{ cloud }}"
|
||||
service: nova
|
||||
endpoint_interface: internal
|
||||
url: http://controller:9292
|
||||
region: RegionOne
|
||||
state: present
|
||||
register: endpoint_test
|
||||
|
||||
- debug: var=endpoint_test
|
||||
|
||||
- name: Assert return values of endpoint module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(endpoint_test.endpoint.keys())|length == 0
|
||||
|
||||
- name: Ensure service have the proper endpoint
|
||||
assert:
|
||||
that:
|
||||
- endpoint_test.endpoint.url == "http://controller:9292"
|
||||
|
||||
- name: Create service endpoint 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 service 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 service endpoint was updated
|
||||
assert:
|
||||
that:
|
||||
- endpoint_updated.endpoint.url == "http://controller:9393"
|
||||
|
||||
- name: Delete service endpoint
|
||||
openstack.cloud.endpoint:
|
||||
cloud: "{{ cloud }}"
|
||||
service: nova
|
||||
endpoint_interface: internal
|
||||
url: http://controller:9393
|
||||
region: RegionOne
|
||||
state: absent
|
||||
register: endpoint_deleted
|
||||
|
||||
- name: Ensure service endpoint was deleted
|
||||
assert:
|
||||
that:
|
||||
- endpoint_deleted.changed
|
||||
@@ -1,3 +1,7 @@
|
||||
expected_fields:
|
||||
- id
|
||||
- name
|
||||
- rules
|
||||
mapping_name: 'ansible-test-mapping'
|
||||
mapping_name_2: 'ansible-test-mapping-2'
|
||||
mapping_rules_1:
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
- module_defaults:
|
||||
# meta/action_groups.yml glue seems to be missing
|
||||
# group/os:
|
||||
# cloud: "{{ cloud }}"
|
||||
group/openstack.cloud.openstack:
|
||||
cloud: "{{ cloud }}"
|
||||
# Backward compatibility with Ansible 2.9
|
||||
openstack.cloud.federation_mapping:
|
||||
cloud: "{{ cloud }}"
|
||||
openstack.cloud.federation_mapping_info:
|
||||
@@ -12,10 +12,6 @@
|
||||
openstack.cloud.federation_mapping:
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name }}'
|
||||
register: delete_mapping
|
||||
- assert:
|
||||
that:
|
||||
- delete_mapping is successful
|
||||
|
||||
- name: 'Create mapping - CHECK_MODE'
|
||||
openstack.cloud.federation_mapping:
|
||||
@@ -23,20 +19,20 @@
|
||||
name: '{{ mapping_name }}'
|
||||
rules: '{{ mapping_rules_1 }}'
|
||||
register: create_mapping
|
||||
check_mode: yes
|
||||
check_mode: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- create_mapping is successful
|
||||
- create_mapping is changed
|
||||
|
||||
- name: 'Fetch mapping info (mapping should be absent)'
|
||||
openstack.cloud.federation_mapping_info:
|
||||
name: '{{ mapping_name }}'
|
||||
register: mapping_info
|
||||
ignore_errors: yes
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- mapping_info is failed
|
||||
- mapping_info.mappings | length == 0
|
||||
|
||||
- name: 'Create mapping'
|
||||
openstack.cloud.federation_mapping:
|
||||
@@ -44,52 +40,50 @@
|
||||
name: '{{ mapping_name }}'
|
||||
rules: '{{ mapping_rules_1 }}'
|
||||
register: create_mapping
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- create_mapping is successful
|
||||
- create_mapping is changed
|
||||
- '"id" in create_mapping.mapping'
|
||||
- '"name" in create_mapping.mapping'
|
||||
- '"rules" in create_mapping.mapping'
|
||||
- create_mapping.mapping.id == mapping_name
|
||||
- create_mapping.mapping.name == mapping_name
|
||||
- create_mapping.mapping.rules | length == 1
|
||||
|
||||
- name: assert return values of federation_mapping module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(create_mapping.mapping.keys())|length == 0
|
||||
|
||||
- name: 'Fetch mapping info - with name'
|
||||
openstack.cloud.federation_mapping_info:
|
||||
name: '{{ mapping_name }}'
|
||||
register: mapping_info
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- mapping_info is successful
|
||||
- '"mappings" in mapping_info'
|
||||
- mapping_info.mappings | length == 1
|
||||
- '"id" in mapping_0'
|
||||
- '"name" in mapping_0'
|
||||
- '"rules" in mapping_0'
|
||||
- mapping_0.id == mapping_name
|
||||
- mapping_0.name == mapping_name
|
||||
- mapping_0.rules | length == 1
|
||||
vars:
|
||||
mapping_0: '{{ mapping_info.mappings[0] }}'
|
||||
- mapping_info.mappings[0].id == mapping_name
|
||||
- mapping_info.mappings[0].name == mapping_name
|
||||
- mapping_info.mappings[0].rules | length == 1
|
||||
|
||||
- name: Check info about mappings
|
||||
assert:
|
||||
that:
|
||||
- mapping_info.mappings|length > 0
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(mapping_info.mappings[0].keys())|length == 0
|
||||
|
||||
- name: 'Fetch mapping info - without name'
|
||||
openstack.cloud.federation_mapping_info: {}
|
||||
register: mapping_info
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- mapping_info is successful
|
||||
- '"mappings" in mapping_info'
|
||||
# In CI we generally have a clean slate, but this might
|
||||
# not be true for everyone...
|
||||
- mapping_info.mappings | length >= 1
|
||||
- '"id" in mapping_0'
|
||||
- '"name" in mapping_0'
|
||||
- '"rules" in mapping_0'
|
||||
- mapping_name in (mapping_info.mappings | map(attribute='id'))
|
||||
- mapping_name in (mapping_info.mappings | map(attribute='name'))
|
||||
vars:
|
||||
mapping_0: '{{ mapping_info.mappings[0] }}'
|
||||
|
||||
- name: 'Create mapping (retry - no change) - CHECK_MODE'
|
||||
openstack.cloud.federation_mapping:
|
||||
@@ -97,10 +91,10 @@
|
||||
name: '{{ mapping_name }}'
|
||||
rules: '{{ mapping_rules_1 }}'
|
||||
register: create_mapping
|
||||
check_mode: yes
|
||||
check_mode: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- create_mapping is successful
|
||||
- create_mapping is not changed
|
||||
|
||||
- name: 'Create mapping (retry - no change)'
|
||||
@@ -109,13 +103,10 @@
|
||||
name: '{{ mapping_name }}'
|
||||
rules: '{{ mapping_rules_1 }}'
|
||||
register: create_mapping
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- create_mapping is successful
|
||||
- create_mapping is not changed
|
||||
- '"id" in create_mapping.mapping'
|
||||
- '"name" in create_mapping.mapping'
|
||||
- '"rules" in create_mapping.mapping'
|
||||
- create_mapping.mapping.id == mapping_name
|
||||
- create_mapping.mapping.name == mapping_name
|
||||
- create_mapping.mapping.rules | length == 1
|
||||
@@ -126,10 +117,10 @@
|
||||
name: '{{ mapping_name }}'
|
||||
rules: '{{ mapping_rules_2 }}'
|
||||
register: update_mapping
|
||||
check_mode: yes
|
||||
check_mode: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- update_mapping is successful
|
||||
- update_mapping is changed
|
||||
|
||||
- name: 'Update mapping'
|
||||
@@ -138,13 +129,10 @@
|
||||
name: '{{ mapping_name }}'
|
||||
rules: '{{ mapping_rules_2 }}'
|
||||
register: update_mapping
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- update_mapping is successful
|
||||
- update_mapping is changed
|
||||
- '"id" in update_mapping.mapping'
|
||||
- '"name" in update_mapping.mapping'
|
||||
- '"rules" in update_mapping.mapping'
|
||||
- update_mapping.mapping.id == mapping_name
|
||||
- update_mapping.mapping.name == mapping_name
|
||||
- update_mapping.mapping.rules | length == 1
|
||||
@@ -155,13 +143,10 @@
|
||||
name: '{{ mapping_name }}'
|
||||
rules: '{{ mapping_rules_2 }}'
|
||||
register: update_mapping
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- update_mapping is successful
|
||||
- update_mapping is not changed
|
||||
- '"id" in update_mapping.mapping'
|
||||
- '"name" in update_mapping.mapping'
|
||||
- '"rules" in update_mapping.mapping'
|
||||
- update_mapping.mapping.id == mapping_name
|
||||
- update_mapping.mapping.name == mapping_name
|
||||
- update_mapping.mapping.rules | length == 1
|
||||
@@ -172,13 +157,10 @@
|
||||
name: '{{ mapping_name_2 }}'
|
||||
rules: '{{ mapping_rules_1 }}'
|
||||
register: create_mapping
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- create_mapping is successful
|
||||
- create_mapping is changed
|
||||
- '"id" in create_mapping.mapping'
|
||||
- '"name" in create_mapping.mapping'
|
||||
- '"rules" in create_mapping.mapping'
|
||||
- create_mapping.mapping.id == mapping_name_2
|
||||
- create_mapping.mapping.name == mapping_name_2
|
||||
- create_mapping.mapping.rules | length == 1
|
||||
@@ -187,53 +169,37 @@
|
||||
openstack.cloud.federation_mapping_info:
|
||||
name: '{{ mapping_name_2 }}'
|
||||
register: mapping_info
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- mapping_info is successful
|
||||
- '"mappings" in mapping_info'
|
||||
- mapping_info.mappings | length == 1
|
||||
- '"id" in mapping_0'
|
||||
- '"name" in mapping_0'
|
||||
- '"rules" in mapping_0'
|
||||
- mapping_0.id == mapping_name_2
|
||||
- mapping_0.name == mapping_name_2
|
||||
- mapping_0.rules | length == 1
|
||||
vars:
|
||||
mapping_0: '{{ mapping_info.mappings[0] }}'
|
||||
- mapping_info.mappings[0].id == mapping_name_2
|
||||
- mapping_info.mappings[0].name == mapping_name_2
|
||||
- mapping_info.mappings[0].rules | length == 1
|
||||
|
||||
- name: 'Fetch mapping info - without name'
|
||||
openstack.cloud.federation_mapping_info: {}
|
||||
register: mapping_info
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- mapping_info is successful
|
||||
- '"mappings" in mapping_info'
|
||||
# In CI we generally have a clean slate, but this might
|
||||
# not be true for everyone...
|
||||
- mapping_info.mappings | length >= 2
|
||||
- '"id" in mapping_0'
|
||||
- '"name" in mapping_0'
|
||||
- '"rules" in mapping_0'
|
||||
- '"id" in mapping_1'
|
||||
- '"name" in mapping_1'
|
||||
- '"rules" in mapping_1'
|
||||
- mapping_name in (mapping_info.mappings | map(attribute='id'))
|
||||
- mapping_name in (mapping_info.mappings | map(attribute='name'))
|
||||
- mapping_name_2 in (mapping_info.mappings | map(attribute='id'))
|
||||
- mapping_name_2 in (mapping_info.mappings | map(attribute='name'))
|
||||
vars:
|
||||
mapping_0: '{{ mapping_info.mappings[0] }}'
|
||||
mapping_1: '{{ mapping_info.mappings[1] }}'
|
||||
|
||||
- name: 'Delete mapping - CHECK_MODE'
|
||||
openstack.cloud.federation_mapping:
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name }}'
|
||||
register: delete_mapping
|
||||
check_mode: yes
|
||||
check_mode: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- delete_mapping is successful
|
||||
- delete_mapping is changed
|
||||
|
||||
- name: 'Delete mapping'
|
||||
@@ -241,9 +207,9 @@
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name }}'
|
||||
register: delete_mapping
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- delete_mapping is successful
|
||||
- delete_mapping is changed
|
||||
|
||||
- name: 'Delete mapping (retry - no change) - CHECK_MODE'
|
||||
@@ -251,10 +217,10 @@
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name }}'
|
||||
register: delete_mapping
|
||||
check_mode: yes
|
||||
check_mode: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- delete_mapping is successful
|
||||
- delete_mapping is not changed
|
||||
|
||||
- name: 'Delete mapping (retry - no change) '
|
||||
@@ -262,28 +228,28 @@
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name }}'
|
||||
register: delete_mapping
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- delete_mapping is successful
|
||||
- delete_mapping is not changed
|
||||
|
||||
- name: 'Fetch mapping info after deletion'
|
||||
openstack.cloud.federation_mapping_info:
|
||||
name: '{{ mapping_name }}'
|
||||
register: mapping_info
|
||||
ignore_errors: True
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- mapping_info is failed
|
||||
- mapping_info.mappings | length == 0
|
||||
|
||||
- name: 'Delete second mapping'
|
||||
openstack.cloud.federation_mapping:
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name_2 }}'
|
||||
register: delete_mapping
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- delete_mapping is successful
|
||||
- delete_mapping is changed
|
||||
|
||||
always:
|
||||
@@ -291,10 +257,10 @@
|
||||
openstack.cloud.federation_mapping:
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name }}'
|
||||
ignore_errors: yes
|
||||
ignore_errors: true
|
||||
|
||||
- name: 'Delete second mapping'
|
||||
openstack.cloud.federation_mapping:
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name_2 }}'
|
||||
ignore_errors: yes
|
||||
ignore_errors: true
|
||||
21
ci/roles/floating_ip/defaults/main.yml
Normal file
21
ci/roles/floating_ip/defaults/main.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
expected_fields:
|
||||
- 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
|
||||
@@ -1,5 +1,15 @@
|
||||
---
|
||||
# Prepare environment
|
||||
- name: List all images
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: images
|
||||
|
||||
- name: Identify CirrOS image name
|
||||
set_fact:
|
||||
image_name: "{{ images.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 }}"
|
||||
@@ -8,119 +18,122 @@
|
||||
|
||||
- name: Assert that public network exists
|
||||
assert:
|
||||
that: public_network.openstack_networks|length == 1
|
||||
that: public_network.networks|length == 1
|
||||
|
||||
- name: Create external network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_external
|
||||
external: true
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_internal_port1
|
||||
network: ansible_internal
|
||||
fixed_ips:
|
||||
- ip_address: 10.7.7.100
|
||||
register: port1
|
||||
|
||||
- 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
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_internal_port2
|
||||
network: ansible_internal
|
||||
fixed_ips:
|
||||
- ip_address: 10.7.7.101
|
||||
register: port2
|
||||
|
||||
- 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
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_internal_port3
|
||||
network: ansible_internal
|
||||
fixed_ips:
|
||||
- ip_address: 10.7.7.102
|
||||
register: port3
|
||||
|
||||
- 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
|
||||
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
|
||||
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 }}"
|
||||
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)|
|
||||
selectattr('floating_network_id', '==', public_network.networks.0.id)|
|
||||
list|length > 0 }}"
|
||||
|
||||
# TODO: Replace with appropriate Ansible module once available
|
||||
@@ -138,232 +151,286 @@
|
||||
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
|
||||
- name: Create server 1 with one nic
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_server1
|
||||
image: "{{ image }}"
|
||||
flavor: m1.tiny
|
||||
nics:
|
||||
# one nic only else simple, first floating ip test does not work
|
||||
- port-name: ansible_internal_port1
|
||||
auto_ip: false
|
||||
wait: true
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: ansible_server1
|
||||
register: info
|
||||
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
|
||||
register: server1
|
||||
|
||||
- name: Assert one internal port and no floating ips on server 1
|
||||
- name: Get server 1 ports
|
||||
openstack.cloud.port_info:
|
||||
cloud: "{{ cloud }}"
|
||||
filters:
|
||||
device_id: "{{ server1.server.id }}"
|
||||
register: server1_ports
|
||||
|
||||
- name: Assert one fixed ip 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"]
|
||||
- server1_ports.ports|length == 1
|
||||
- server1_ports.ports|sum(attribute='fixed_ips', start=[])|map(attribute='ip_address')|sort|list ==
|
||||
["10.7.7.100"]
|
||||
|
||||
- name: Create server with two nics
|
||||
- name: Create server 2 with two nics
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_server2
|
||||
image: "{{ image }}"
|
||||
flavor: m1.tiny
|
||||
nics:
|
||||
- port-name: ansible_internal_port2
|
||||
- port-name: ansible_internal_port3
|
||||
auto_ip: false
|
||||
wait: true
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: ansible_server2
|
||||
register: info
|
||||
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
|
||||
register: server2
|
||||
|
||||
- name: Assert two internal ports and no floating ips on server 2
|
||||
- name: Get server 2 ports
|
||||
openstack.cloud.port_info:
|
||||
cloud: "{{ cloud }}"
|
||||
filters:
|
||||
device_id: "{{ server2.server.id }}"
|
||||
register: server2_ports
|
||||
|
||||
- name: Assert two fixed 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 ==
|
||||
- server2_ports.ports|length == 2
|
||||
- server2_ports.ports|sum(attribute='fixed_ips', start=[])|map(attribute='ip_address')|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 }}"
|
||||
state: present
|
||||
server: ansible_server1
|
||||
register: info
|
||||
wait: true
|
||||
|
||||
- name: Assert one internal port and one floating ip on server 1
|
||||
- name: Get floating ip attached to server 1
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
port: "{{ port1.port.id }}"
|
||||
register: server1_fips
|
||||
# openstacksdk has issues with waiting hence we simply retry
|
||||
retries: 10
|
||||
delay: 3
|
||||
until: server1_fips.floating_ips|length == 1
|
||||
|
||||
- name: Assert fixed ip and floating ip attached to 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"]
|
||||
- server1_ports.ports|length == 1
|
||||
- server1_ports.ports|sum(attribute='fixed_ips', start=[])|map(attribute='ip_address')|sort|list ==
|
||||
["10.7.7.100"]
|
||||
- server1_fips.floating_ips|length == 1
|
||||
- server1_fips.floating_ips|map(attribute='fixed_ip_address')|sort|list ==
|
||||
["10.7.7.100"]
|
||||
|
||||
- name: Detach floating IP from server
|
||||
- name: Assert return values of floating_ip_info module
|
||||
assert:
|
||||
that:
|
||||
- server1_fips is success
|
||||
- server1_fips is not changed
|
||||
- server1_fips.floating_ips
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(server1_fips.floating_ips[0].keys())|length == 0
|
||||
|
||||
- name: Assign floating ip to server 1 again
|
||||
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 }}"
|
||||
state: present
|
||||
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.
|
||||
wait: true
|
||||
register: floating_ip
|
||||
|
||||
- name: Assert floating ip on server 1 has not changed
|
||||
assert:
|
||||
that: floating_ip is not changed
|
||||
|
||||
- name: Assert return values of floating_ip module
|
||||
assert:
|
||||
that:
|
||||
- floating_ip.floating_ip
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(floating_ip.floating_ip.keys())|length == 0
|
||||
|
||||
- name: Detach floating ip from server 1
|
||||
openstack.cloud.floating_ip:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
server: ansible_server1
|
||||
network: public
|
||||
floating_ip_address: "{{ server1_fips.floating_ips.0.floating_ip_address }}"
|
||||
|
||||
- name: Wait until floating ip is detached from server 1
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
port: "{{ port1.port.id }}"
|
||||
register: server1_fips
|
||||
# When detaching a floating ip from an instance there might be a delay until it is not listed anymore
|
||||
retries: 10
|
||||
delay: 3
|
||||
until: info.openstack_servers.0.addresses.ansible_internal|length == 1
|
||||
until: server1_fips.floating_ips|length == 0
|
||||
|
||||
- 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: Find all floating ips for debugging
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: fips
|
||||
|
||||
- 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: Print all floating ips for debugging
|
||||
debug: var=fips
|
||||
|
||||
- name: Get info about server
|
||||
- name: Find all servers for debugging
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: ansible_server2
|
||||
register: info
|
||||
register: servers
|
||||
|
||||
- name: Assert two internal ports and one floating ip on server 2
|
||||
- name: Print all servers for debugging
|
||||
debug: var=servers
|
||||
|
||||
- name: Assign floating ip to server 2
|
||||
openstack.cloud.floating_ip:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
reuse: false # else fixed_address will be ignored
|
||||
server: ansible_server2
|
||||
network: public
|
||||
fixed_address: "{{ port2.port.fixed_ips[0].ip_address }}"
|
||||
wait: true
|
||||
register: server2_fip
|
||||
|
||||
- name: Assert floating ip attached to 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"]
|
||||
- server2_fip.floating_ip
|
||||
|
||||
- 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"
|
||||
- name: Find all floating ips for debugging
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: fips
|
||||
|
||||
# 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: Print all floating ips for debugging
|
||||
debug: var=fips
|
||||
|
||||
- name: Get info about server
|
||||
- name: Find all servers for debugging
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: servers
|
||||
|
||||
- name: Print all servers for debugging
|
||||
debug: var=servers
|
||||
|
||||
- name: Get floating ip attached to server 2
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
port: "{{ port2.port.id }}"
|
||||
register: server2_fips
|
||||
|
||||
- name: Assert floating ip attached to server 2
|
||||
assert:
|
||||
that:
|
||||
- server2_fips.floating_ips|length == 1
|
||||
- server2_fips.floating_ips|map(attribute='fixed_ip_address')|sort|list ==
|
||||
["10.7.7.101"]
|
||||
|
||||
- name: Assign a second, specific floating ip to server 2
|
||||
openstack.cloud.floating_ip:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
reuse: false # else fixed_address will be ignored
|
||||
server: ansible_server2
|
||||
register: info
|
||||
# retry because we cannot wait for second floating ip
|
||||
network: ansible_external
|
||||
fixed_address: "{{ port3.port.fixed_ips[0].ip_address }}"
|
||||
floating_ip_address: "10.6.6.150"
|
||||
wait: false # does not work anyway and causes issues in local testing
|
||||
|
||||
- name: Get floating ip attached to server 2
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
port: "{{ port3.port.id }}"
|
||||
register: server2_fips
|
||||
# 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
|
||||
retries: 10
|
||||
delay: 3
|
||||
until: info.openstack_servers.0.addresses.ansible_internal|length == 4
|
||||
until: server2_fips.floating_ips|length == 1
|
||||
|
||||
- name: Assert two internal ports and two floating ips on server 2
|
||||
- name: Assert second floating ip attached to 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)
|
||||
- server2_fips.floating_ips|length == 1
|
||||
- server2_fips.floating_ips|map(attribute='fixed_ip_address')|sort|list ==
|
||||
["10.7.7.102"]
|
||||
|
||||
- name: Detach second floating IP from server
|
||||
- name: Detach second floating ip from server 2
|
||||
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 }}"
|
||||
state: absent
|
||||
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.
|
||||
network: ansible_external
|
||||
floating_ip_address: "10.6.6.150"
|
||||
|
||||
- name: Wait until second floating ip is detached from server 2
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
port: "{{ port3.port.id }}"
|
||||
register: server2_fips
|
||||
# When detaching a floating ip from an instance there might be a delay until it is not listed anymore
|
||||
retries: 10
|
||||
delay: 3
|
||||
until: info.openstack_servers.0.addresses.ansible_internal|length == 3
|
||||
until: server2_fips.floating_ips|length == 0
|
||||
|
||||
- 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:
|
||||
- name: Get first floating ip attached to server 2
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
port: "{{ port2.port.id }}"
|
||||
register: server2_fips
|
||||
|
||||
- name: Detach remaining floating ip from server 2
|
||||
openstack.cloud.floating_ip:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
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.
|
||||
network: public
|
||||
floating_ip_address: "{{ server2_fips.floating_ips.0.floating_ip_address }}"
|
||||
|
||||
- name: Wait until first floating ip is detached from server 2
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
port: "{{ port2.port.id }}"
|
||||
register: server2_fips
|
||||
# When detaching a floating ip from an instance there might be a delay until it is not listed anymore
|
||||
retries: 10
|
||||
delay: 3
|
||||
until: info.openstack_servers.0.addresses.ansible_internal|length == 2
|
||||
until: server2_fips.floating_ips|length == 0
|
||||
|
||||
- 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
|
||||
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
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_server1
|
||||
wait: true
|
||||
|
||||
- name: Get all floating ips
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
cloud: "{{ cloud }}"
|
||||
register: fips
|
||||
|
||||
# TODO: Replace with appropriate Ansible module once available
|
||||
@@ -371,7 +438,7 @@
|
||||
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)|
|
||||
{{ fips.floating_ips|selectattr('floating_network_id', '==', public_network.networks.0.id)|
|
||||
map(attribute="floating_ip_address")|list|join(' ') }}
|
||||
|
||||
# TODO: Replace with appropriate Ansible module once available
|
||||
@@ -381,8 +448,8 @@
|
||||
|
||||
- name: Get remaining floating ips on external network
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
floating_network: ansible_external
|
||||
cloud: "{{ cloud }}"
|
||||
floating_network: ansible_external
|
||||
register: fips
|
||||
|
||||
# TODO: Replace with appropriate Ansible module once available
|
||||
@@ -396,71 +463,71 @@
|
||||
|
||||
# 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,
|
||||
# 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
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_router2
|
||||
|
||||
- name: Delete router 1
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_router1
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_router1
|
||||
|
||||
- name: Delete internal port 3
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_internal_port3
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_internal_port3
|
||||
|
||||
- name: Delete internal port 2
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_internal_port2
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_internal_port2
|
||||
|
||||
- name: Delete internal port 1
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_internal_port1
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_internal_port1
|
||||
|
||||
- name: Delete internal subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_internal_subnet
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_internal_subnet
|
||||
|
||||
- name: Delete internal network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_internal
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_internal
|
||||
|
||||
- name: Delete external port 2
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_external_port2
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_external_port2
|
||||
|
||||
- name: Delete external port 1
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_external_port1
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_external_port1
|
||||
|
||||
- name: Delete external subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_external_subnet
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_external_subnet
|
||||
|
||||
- name: Delete external network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_external
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_external
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
---
|
||||
- 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'
|
||||
@@ -1 +0,0 @@
|
||||
group_name: ansible_group
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
- name: Create group
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ group_name }}"
|
||||
|
||||
- name: Update group
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ group_name }}"
|
||||
description: "updated description"
|
||||
|
||||
- name: Delete group
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ group_name }}"
|
||||
68
ci/roles/group_assignment/tasks/main.yml
Normal file
68
ci/roles/group_assignment/tasks/main.yml
Normal file
@@ -0,0 +1,68 @@
|
||||
---
|
||||
- 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
|
||||
|
||||
- name: Assign user to nonadmins group
|
||||
openstack.cloud.group_assignment:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
user: ansible_user
|
||||
group: nonadmins
|
||||
register: group_assignment
|
||||
|
||||
- name: Assert group assignment
|
||||
assert:
|
||||
that:
|
||||
- group_assignment is changed
|
||||
|
||||
- name: Assign user to nonadmins group again
|
||||
openstack.cloud.group_assignment:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
user: ansible_user
|
||||
group: nonadmins
|
||||
register: group_assignment
|
||||
|
||||
- name: Assert group assignment
|
||||
assert:
|
||||
that:
|
||||
- group_assignment is not changed
|
||||
|
||||
- name: Remove user from nonadmins group
|
||||
openstack.cloud.group_assignment:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
user: ansible_user
|
||||
group: nonadmins
|
||||
register: group_assignment
|
||||
|
||||
- name: Assert group assignment
|
||||
assert:
|
||||
that:
|
||||
- group_assignment is changed
|
||||
|
||||
- name: Remove user from nonadmins group again
|
||||
openstack.cloud.group_assignment:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
user: ansible_user
|
||||
group: nonadmins
|
||||
register: group_assignment
|
||||
|
||||
- name: Assert group assignment
|
||||
assert:
|
||||
that:
|
||||
- group_assignment is not changed
|
||||
|
||||
- name: Delete user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_user
|
||||
11
ci/roles/host_aggregate/defaults/main.yml
Normal file
11
ci/roles/host_aggregate/defaults/main.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
expected_fields:
|
||||
- availability_zone
|
||||
- created_at
|
||||
- deleted_at
|
||||
- hosts
|
||||
- id
|
||||
- is_deleted
|
||||
- metadata
|
||||
- name
|
||||
- updated_at
|
||||
- uuid
|
||||
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
|
||||
6
ci/roles/identity_domain/defaults/main.yml
Normal file
6
ci/roles/identity_domain/defaults/main.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
expected_fields:
|
||||
- description
|
||||
- id
|
||||
- is_enabled
|
||||
- name
|
||||
- links
|
||||
123
ci/roles/identity_domain/tasks/main.yml
Normal file
123
ci/roles/identity_domain/tasks/main.yml
Normal file
@@ -0,0 +1,123 @@
|
||||
---
|
||||
- name: Create keystone domain
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_domain
|
||||
description: "test description"
|
||||
register: domain
|
||||
|
||||
- name: Assert return values of identity_domain module
|
||||
assert:
|
||||
that:
|
||||
- domain.domain.name == 'ansible_domain'
|
||||
- domain.domain.description == "test description"
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(domain.domain.keys())|length == 0
|
||||
|
||||
- name: Update keystone domain
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_domain
|
||||
description: "updated description"
|
||||
register: domain
|
||||
|
||||
- name: Assert updated domain
|
||||
assert:
|
||||
that:
|
||||
- domain.domain.description == "updated description"
|
||||
|
||||
- name: Fetch domains
|
||||
openstack.cloud.identity_domain_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: domains
|
||||
|
||||
- name: Assert return values of identity_domain_info module
|
||||
assert:
|
||||
that:
|
||||
- domains.domains | length > 0
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(domains.domains.0.keys())|length == 0
|
||||
|
||||
- name: Fetch domain by name
|
||||
openstack.cloud.identity_domain_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_domain
|
||||
register: domains
|
||||
|
||||
- name: Assert named domain
|
||||
assert:
|
||||
that:
|
||||
- domains.domains | length == 1
|
||||
|
||||
- name: Create disabled domain
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_domain_disabled
|
||||
is_enabled: false
|
||||
description: "test description"
|
||||
register: domain
|
||||
|
||||
- name: Fetch all domains
|
||||
openstack.cloud.identity_domain_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: domains
|
||||
|
||||
- name: Assert both ansible domains exist
|
||||
assert:
|
||||
that:
|
||||
- domains.domains | length >= 2
|
||||
|
||||
- name: Fetch disabled domains
|
||||
openstack.cloud.identity_domain_info:
|
||||
cloud: "{{ cloud }}"
|
||||
filters:
|
||||
is_enabled: false
|
||||
register: domains
|
||||
|
||||
- name: Assert at least one disabled domain exists
|
||||
assert:
|
||||
that:
|
||||
- domains.domains | length >= 1
|
||||
|
||||
- name: Fetch enabled domains
|
||||
openstack.cloud.identity_domain_info:
|
||||
cloud: "{{ cloud }}"
|
||||
filters:
|
||||
is_enabled: true
|
||||
register: domains
|
||||
|
||||
- name: Assert returned value
|
||||
assert:
|
||||
that:
|
||||
- item.is_enabled
|
||||
loop: "{{ domains.domains }}"
|
||||
|
||||
- name: Delete disabled domain
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_domain_disabled
|
||||
|
||||
- name: Assert domain is disabled
|
||||
assert:
|
||||
that:
|
||||
- not domain.domain.is_enabled
|
||||
|
||||
- name: Delete domain
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_domain
|
||||
|
||||
- name: Get non-existing domain
|
||||
openstack.cloud.identity_domain_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_domain
|
||||
register: domains
|
||||
|
||||
- name: Assert no results returned
|
||||
assert:
|
||||
that:
|
||||
- domains.domains | length == 0
|
||||
5
ci/roles/identity_group/defaults/main.yml
Normal file
5
ci/roles/identity_group/defaults/main.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
expected_fields:
|
||||
- description
|
||||
- domain_id
|
||||
- id
|
||||
- name
|
||||
220
ci/roles/identity_group/tasks/main.yml
Normal file
220
ci/roles/identity_group/tasks/main.yml
Normal file
@@ -0,0 +1,220 @@
|
||||
---
|
||||
- name: Create group
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
description: "ansible group"
|
||||
name: ansible_group
|
||||
register: group
|
||||
|
||||
- name: Assert return values of identity_group module
|
||||
assert:
|
||||
that:
|
||||
- group.group.name == 'ansible_group'
|
||||
- group.group.description == "ansible group"
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(group.group.keys())|length == 0
|
||||
|
||||
- name: Create group again
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
description: "ansible group"
|
||||
name: ansible_group
|
||||
register: group
|
||||
|
||||
- name: Assert group did not change
|
||||
assert:
|
||||
that:
|
||||
- group is not changed
|
||||
|
||||
- name: Update group
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_group
|
||||
description: "updated description"
|
||||
register: group
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- group is changed
|
||||
- group.group.description == "updated description"
|
||||
|
||||
- name: Fetch all groups
|
||||
openstack.cloud.identity_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: _groups
|
||||
|
||||
- name: Assert return values of identity_group_info module
|
||||
assert:
|
||||
that:
|
||||
- _groups.groups | length > 0
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(_groups.groups.0.keys())|length == 0
|
||||
|
||||
- name: List group with filters
|
||||
openstack.cloud.identity_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
domain: default
|
||||
filters:
|
||||
name: ansible_group
|
||||
register: _groups
|
||||
|
||||
- name: Assert group with filters
|
||||
assert:
|
||||
that:
|
||||
- _groups.groups | length == 1
|
||||
- _groups.groups.0.id == group.group.id
|
||||
|
||||
- name: Create domain
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_domain
|
||||
register: domain
|
||||
|
||||
- name: Create group in specific domain
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_group
|
||||
domain_id: "{{ domain.domain.id }}"
|
||||
register: group
|
||||
|
||||
- name: Assert results
|
||||
assert:
|
||||
that:
|
||||
- group is changed
|
||||
- group.group.domain_id == domain.domain.id
|
||||
|
||||
- name: List group by group name
|
||||
openstack.cloud.identity_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_group
|
||||
register: _groups
|
||||
|
||||
- name: Assert groups by group name
|
||||
assert:
|
||||
that:
|
||||
- _groups.groups | length == 2
|
||||
|
||||
- name: List group by domain_id
|
||||
openstack.cloud.identity_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
domain: ansible_domain
|
||||
register: _groups
|
||||
|
||||
- name: Assert groups by domain_id
|
||||
assert:
|
||||
that:
|
||||
- _groups.groups | length == 1
|
||||
- _groups.groups.0.id == group.group.id
|
||||
- _groups.groups.0.domain_id == domain.domain.id
|
||||
|
||||
- name: List group by domain_id and group name
|
||||
openstack.cloud.identity_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
domain: ansible_domain
|
||||
name: ansible_group
|
||||
register: _groups
|
||||
|
||||
- name: Assert groups by domain_id and group name
|
||||
assert:
|
||||
that:
|
||||
- _groups.groups | length == 1
|
||||
- _groups.groups.0.id == group.group.id
|
||||
|
||||
- name: Create group in specific domain again
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_group
|
||||
domain_id: "{{ domain.domain.id }}"
|
||||
register: group
|
||||
|
||||
- name: Assert not changed
|
||||
assert:
|
||||
that:
|
||||
- group is not changed
|
||||
|
||||
- name: Delete ambiguous group
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_group
|
||||
ignore_errors: true
|
||||
register: group
|
||||
|
||||
- name: Assert failed
|
||||
assert:
|
||||
that:
|
||||
- group is failed
|
||||
|
||||
- name: Delete group in specific domain
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_group
|
||||
domain_id: "{{ domain.domain.id }}"
|
||||
register: group
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- group is changed
|
||||
|
||||
- name: Delete group in specific domain again
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_group
|
||||
domain_id: "{{ domain.domain.id }}"
|
||||
register: group
|
||||
|
||||
- name: Assert not changed
|
||||
assert:
|
||||
that:
|
||||
- group is not changed
|
||||
|
||||
- name: Delete domain
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_domain
|
||||
|
||||
- name: Delete group
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_group
|
||||
register: group
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- group is changed
|
||||
|
||||
- name: Delete group again
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_group
|
||||
register: group
|
||||
|
||||
- name: Assert not changed
|
||||
assert:
|
||||
that:
|
||||
- group is not changed
|
||||
|
||||
- name: List group
|
||||
openstack.cloud.identity_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_group
|
||||
register: _groups
|
||||
|
||||
- name: Assert group does not exist
|
||||
assert:
|
||||
that:
|
||||
- _groups.groups | length == 0
|
||||
6
ci/roles/identity_role/defaults/main.yml
Normal file
6
ci/roles/identity_role/defaults/main.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
expected_fields:
|
||||
- description
|
||||
- domain_id
|
||||
- id
|
||||
- links
|
||||
- name
|
||||
88
ci/roles/identity_role/tasks/main.yml
Normal file
88
ci/roles/identity_role/tasks/main.yml
Normal file
@@ -0,0 +1,88 @@
|
||||
---
|
||||
- name: Create identity role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_role
|
||||
description: "ansible role"
|
||||
register: role
|
||||
|
||||
- name: Assert return values of identity_role module
|
||||
assert:
|
||||
that:
|
||||
- role.role.name == 'ansible_role'
|
||||
- role.role.description == "ansible role"
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(role.role.keys())|length == 0
|
||||
|
||||
- name: Try to get role
|
||||
openstack.cloud.identity_role_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_role
|
||||
register: roles
|
||||
|
||||
- name: Assert role found
|
||||
assert:
|
||||
that:
|
||||
- roles.roles | length == 1
|
||||
- roles.roles.0.name == 'ansible_role'
|
||||
|
||||
- name: Fetch all roles
|
||||
openstack.cloud.identity_role_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: roles
|
||||
|
||||
- name: Assert return values of identity_role_info module
|
||||
assert:
|
||||
that:
|
||||
- roles.roles | length > 0
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(roles.roles.0.keys())|length == 0
|
||||
|
||||
- name: Create identity role again
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_role
|
||||
description: "ansible role"
|
||||
register: role
|
||||
|
||||
- name: Assert role did not change
|
||||
assert:
|
||||
that:
|
||||
- role is not changed
|
||||
|
||||
- name: Delete identity role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_role
|
||||
register: role
|
||||
|
||||
- name: Assert role changed
|
||||
assert:
|
||||
that:
|
||||
- role is changed
|
||||
|
||||
- name: Try to get role
|
||||
openstack.cloud.identity_role_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_role
|
||||
register: roles
|
||||
|
||||
- name: Assert no role found
|
||||
assert:
|
||||
that:
|
||||
- roles.roles | length == 0
|
||||
|
||||
- name: Delete role again
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_role
|
||||
register: role
|
||||
|
||||
- name: Assert role did not change
|
||||
assert:
|
||||
that:
|
||||
- role is not changed
|
||||
11
ci/roles/identity_user/defaults/main.yml
Normal file
11
ci/roles/identity_user/defaults/main.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
expected_fields:
|
||||
- default_project_id
|
||||
- description
|
||||
- domain_id
|
||||
- email
|
||||
- id
|
||||
- is_enabled
|
||||
- links
|
||||
- name
|
||||
- password
|
||||
- password_expires_at
|
||||
218
ci/roles/identity_user/tasks/main.yml
Normal file
218
ci/roles/identity_user/tasks/main.yml
Normal file
@@ -0,0 +1,218 @@
|
||||
---
|
||||
- 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
|
||||
description: "ansible user"
|
||||
default_project: demo
|
||||
register: user
|
||||
|
||||
- name: Assert return values of identity_user module
|
||||
assert:
|
||||
that:
|
||||
- user.user.name == 'ansible_user'
|
||||
- user.user.description == 'ansible user'
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(user.user.keys())|length == 0
|
||||
|
||||
- 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: true
|
||||
|
||||
- name: Assert that update failed
|
||||
assert:
|
||||
that:
|
||||
- user is failed
|
||||
- user.msg == "update_password is 'always' but password is missing"
|
||||
|
||||
- name: Delete user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_user
|
||||
|
||||
|
||||
- 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
|
||||
|
||||
- name: Create user with a password again
|
||||
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: 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: Update user without password and update_password set to always
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
update_password: always
|
||||
email: updated.ansible.user@nowhere.net
|
||||
register: user
|
||||
ignore_errors: true
|
||||
|
||||
- name: Assert user update failed
|
||||
assert:
|
||||
that:
|
||||
- user is failed
|
||||
- user.msg == "update_password is 'always' but password is missing"
|
||||
|
||||
- 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
|
||||
|
||||
- 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
|
||||
|
||||
- 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: Fetch users
|
||||
openstack.cloud.identity_user_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: users
|
||||
|
||||
- name: Assert return values of identity_user_info module
|
||||
assert:
|
||||
that:
|
||||
- users.users | length > 0
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(users.users.0.keys())|length == 0
|
||||
|
||||
- name: Fetch user by name
|
||||
openstack.cloud.identity_user_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_user
|
||||
register: users
|
||||
|
||||
- name: Assert named user
|
||||
assert:
|
||||
that:
|
||||
- users.users | length == 1
|
||||
|
||||
- name: Delete user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_user2
|
||||
|
||||
- name: Delete user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_user
|
||||
|
||||
- name: Ensure user was changed
|
||||
assert:
|
||||
that:
|
||||
- user is changed
|
||||
|
||||
- name: Delete user again
|
||||
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
|
||||
|
||||
- name: Fetch ansible_user
|
||||
openstack.cloud.identity_user_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_user
|
||||
register: users
|
||||
|
||||
- name: Assert ansible_user does not exist
|
||||
assert:
|
||||
that:
|
||||
- users.users | length == 0
|
||||
|
||||
- name: Fetch ansible_user2
|
||||
openstack.cloud.identity_user_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_user2
|
||||
register: users
|
||||
|
||||
- name: Assert ansible_user2 does not exist
|
||||
assert:
|
||||
that:
|
||||
- users.users | length == 0
|
||||
@@ -1,4 +1,65 @@
|
||||
image_name: ansible_image
|
||||
image_tags:
|
||||
- test
|
||||
- ansible
|
||||
expected_fields:
|
||||
- architecture
|
||||
- checksum
|
||||
- container_format
|
||||
- created_at
|
||||
- direct_url
|
||||
- disk_format
|
||||
- file
|
||||
- has_auto_disk_config
|
||||
- hash_algo
|
||||
- hash_value
|
||||
- hw_cpu_cores
|
||||
- hw_cpu_policy
|
||||
- hw_cpu_sockets
|
||||
- hw_cpu_thread_policy
|
||||
- hw_cpu_threads
|
||||
- hw_disk_bus
|
||||
- hw_machine_type
|
||||
- hw_qemu_guest_agent
|
||||
- hw_rng_model
|
||||
- hw_scsi_model
|
||||
- hw_serial_port_count
|
||||
- hw_video_model
|
||||
- hw_video_ram
|
||||
- hw_vif_model
|
||||
- hw_watchdog_action
|
||||
- hypervisor_type
|
||||
- id
|
||||
- instance_type_rxtx_factor
|
||||
- instance_uuid
|
||||
- is_hidden
|
||||
- is_hw_boot_menu_enabled
|
||||
- is_hw_vif_multiqueue_enabled
|
||||
- is_protected
|
||||
- kernel_id
|
||||
- locations
|
||||
- metadata
|
||||
- min_disk
|
||||
- min_ram
|
||||
- name
|
||||
- needs_config_drive
|
||||
- needs_secure_boot
|
||||
- os_admin_user
|
||||
- os_command_line
|
||||
- os_distro
|
||||
- os_require_quiesce
|
||||
- os_shutdown_timeout
|
||||
- os_type
|
||||
- os_version
|
||||
- owner
|
||||
- owner_id
|
||||
- properties
|
||||
- ramdisk_id
|
||||
- schema
|
||||
- size
|
||||
- status
|
||||
- store
|
||||
- tags
|
||||
- updated_at
|
||||
- url
|
||||
- virtual_size
|
||||
- visibility
|
||||
- vm_mode
|
||||
- vmware_adaptertype
|
||||
- vmware_ostype
|
||||
|
||||
@@ -1,74 +1,376 @@
|
||||
---
|
||||
- name: Create a test image file
|
||||
shell: mktemp
|
||||
register: tmp_file
|
||||
- name: Test images
|
||||
block:
|
||||
- name: List all images
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: images
|
||||
|
||||
- name: Fill test image file to 1MB
|
||||
shell: truncate -s 1048576 {{ tmp_file.stdout }}
|
||||
- name: Assert existence of CirrOS image
|
||||
assert:
|
||||
that:
|
||||
- images.images | length > 0
|
||||
|
||||
- name: Create raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ image_name }}"
|
||||
filename: "{{ tmp_file.stdout }}"
|
||||
disk_format: raw
|
||||
tags: "{{ image_tags }}"
|
||||
register: image
|
||||
- name: Ensure clean environment
|
||||
ansible.builtin.set_fact:
|
||||
tmp_file: !!null
|
||||
|
||||
- name: Get details of created image
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: "{{ image_name }}"
|
||||
register: image_info_result
|
||||
- name: Create a test image file
|
||||
ansible.builtin.tempfile:
|
||||
register: tmp_file
|
||||
|
||||
- name: Verify image info
|
||||
assert:
|
||||
that:
|
||||
- "image_info_result.openstack_image.name == image_name"
|
||||
- "image_info_result.openstack_image.tags | sort == image_tags | sort"
|
||||
- name: Fill test image file to 1MB
|
||||
community.general.filesize:
|
||||
path: '{{ tmp_file.path }}'
|
||||
size: 1M
|
||||
|
||||
- name: Delete raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ image_name }}"
|
||||
- name: Calculating file checksum
|
||||
ansible.builtin.stat:
|
||||
path: "{{ tmp_file.path }}"
|
||||
checksum_algorithm: sha512
|
||||
get_checksum: true
|
||||
register: image_details
|
||||
|
||||
- name: Create raw image (complex)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ image_name }}"
|
||||
filename: "{{ tmp_file.stdout }}"
|
||||
disk_format: raw
|
||||
is_public: True
|
||||
min_disk: 10
|
||||
min_ram: 1024
|
||||
kernel: cirros-vmlinuz
|
||||
ramdisk: cirros-initrd
|
||||
properties:
|
||||
cpu_arch: x86_64
|
||||
distro: ubuntu
|
||||
register: image
|
||||
- name: Ensure mock kernel and ramdisk images (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ item }}"
|
||||
filename: "{{ tmp_file.path }}"
|
||||
disk_format: raw
|
||||
loop:
|
||||
- cirros-vmlinuz
|
||||
- cirros-initrd
|
||||
|
||||
- name: Delete raw image (complex)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ image_name }}"
|
||||
- name: Create raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
filename: "{{ tmp_file.path }}"
|
||||
is_protected: true
|
||||
checksum: "{{ image_details.stat.checksum }}"
|
||||
disk_format: raw
|
||||
tags:
|
||||
- test
|
||||
- ansible
|
||||
register: image
|
||||
|
||||
- name: Delete test image file
|
||||
file:
|
||||
name: "{{ tmp_file.stdout }}"
|
||||
state: absent
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
|
||||
- name: Try to get details of deleted image
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: "{{ image_name }}"
|
||||
register: deleted_image_info_result
|
||||
- name: Assert return values of image module
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
- image.image.name == 'ansible_image'
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(image.image.keys())|length == 0
|
||||
|
||||
- name: Verify image is deleted
|
||||
assert:
|
||||
that:
|
||||
- not deleted_image_info_result.openstack_image
|
||||
- name: Get details of created image
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: ansible_image
|
||||
register: images
|
||||
|
||||
- name: Assert return values of image_info module
|
||||
assert:
|
||||
that:
|
||||
- images.images | length > 0
|
||||
- images.images.0.name == "ansible_image"
|
||||
- images.images.0.tags | sort == ['test', 'ansible'] | sort
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(images.images.0.keys())|length == 0
|
||||
|
||||
- name: Create raw image again (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
filename: "{{ tmp_file.path }}"
|
||||
is_protected: true
|
||||
disk_format: raw
|
||||
tags:
|
||||
- test
|
||||
- ansible
|
||||
register: image
|
||||
|
||||
- name: Assert not changed
|
||||
assert:
|
||||
that:
|
||||
- image is not changed
|
||||
|
||||
- name: Update is_protected on raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
is_protected: false
|
||||
register: image
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
- image.image.is_protected == false
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
|
||||
- name: Update visibility on raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
is_public: false
|
||||
register: image
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image.image.visibility == 'private'
|
||||
|
||||
- name: Update again visibility on raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
is_public: true
|
||||
register: image
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
- image.image.visibility == 'public'
|
||||
|
||||
- name: Define visibility on raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
visibility: shared
|
||||
register: image
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
- image.image.visibility == 'shared'
|
||||
|
||||
- name: Rename raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
id: "{{ image.image.id }}"
|
||||
name: 'ansible_image-changed'
|
||||
register: image
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
- image.image.name == 'ansible_image-changed'
|
||||
|
||||
- name: Deactivate raw image
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: inactive
|
||||
id: "{{ image.image.id }}"
|
||||
name: 'ansible_image-changed'
|
||||
register: image
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
- image.image.status == 'deactivated'
|
||||
|
||||
- name: Reactivate raw image
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
id: "{{ image.image.id }}"
|
||||
name: 'ansible_image-changed'
|
||||
register: image
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
- image.image.status == 'active'
|
||||
|
||||
- name: Rename back raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
id: "{{ image.image.id }}"
|
||||
name: ansible_image
|
||||
register: image
|
||||
|
||||
- name: Delete raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_image
|
||||
register: image
|
||||
|
||||
- name: assert image changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
|
||||
- name: Delete raw image again (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_image
|
||||
register: image
|
||||
|
||||
- name: assert image not changed
|
||||
assert:
|
||||
that:
|
||||
- image is not changed
|
||||
|
||||
- name: Create raw image (complex)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
filename: "{{ tmp_file.path }}"
|
||||
disk_format: raw
|
||||
is_public: True
|
||||
min_disk: 10
|
||||
min_ram: 1024
|
||||
# TODO(rcastillo): upload cirros-vmlinuz, cirros-initrd in test setup
|
||||
kernel: cirros-vmlinuz
|
||||
ramdisk: cirros-initrd
|
||||
properties:
|
||||
cpu_arch: x86_64
|
||||
distro: ubuntu
|
||||
register: image
|
||||
|
||||
- name: Assert visibility
|
||||
assert:
|
||||
that:
|
||||
- image.image.visibility == 'public'
|
||||
|
||||
- name: Delete raw image (complex)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_image
|
||||
|
||||
- name: Try to get details of deleted image
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: ansible_image
|
||||
register: images
|
||||
|
||||
- name: Verify image is deleted
|
||||
assert:
|
||||
that:
|
||||
- images.images | length == 0
|
||||
|
||||
- name: Create owner project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: Project owning test image
|
||||
domain: default
|
||||
is_enabled: True
|
||||
register: project
|
||||
|
||||
- name: Create raw image (owner by project name)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
filename: "{{ tmp_file.path }}"
|
||||
disk_format: raw
|
||||
tags:
|
||||
- test
|
||||
- ansible
|
||||
project: ansible_project
|
||||
register: image
|
||||
|
||||
- name: Get details of created image (owner by project name)
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: ansible_image
|
||||
register: images
|
||||
|
||||
- name: Verify image owner (owner by project name)
|
||||
assert:
|
||||
that:
|
||||
- images.images.0.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.path }}"
|
||||
disk_format: raw
|
||||
tags:
|
||||
- test
|
||||
- ansible
|
||||
project: ansible_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: images
|
||||
|
||||
- name: Verify image owner (owner by project name and domain name)
|
||||
assert:
|
||||
that:
|
||||
- images.images.0.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: ansible_project
|
||||
domain: default
|
||||
|
||||
- name: Delete mock kernel and ramdisk images
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ item }}"
|
||||
loop:
|
||||
- cirros-vmlinuz
|
||||
- cirros-initrd
|
||||
|
||||
- name: Delete test image file
|
||||
file:
|
||||
name: "{{ tmp_file.path }}"
|
||||
state: absent
|
||||
|
||||
always:
|
||||
- name: Remove temporary image file
|
||||
ansible.builtin.file:
|
||||
path: "{{ tmp_file.path }}"
|
||||
state: absent
|
||||
when: tmp_file is defined and 'path' in tmp_file
|
||||
|
||||
2
ci/roles/inventory/files/ansible.cfg
Normal file
2
ci/roles/inventory/files/ansible.cfg
Normal file
@@ -0,0 +1,2 @@
|
||||
[inventory]
|
||||
enable_plugins=openstack.cloud.openstack
|
||||
425
ci/roles/inventory/tasks/main.yml
Normal file
425
ci/roles/inventory/tasks/main.yml
Normal file
@@ -0,0 +1,425 @@
|
||||
---
|
||||
- module_defaults:
|
||||
group/openstack.cloud.openstack:
|
||||
cloud: "{{ cloud }}"
|
||||
# Listing modules individually is required for
|
||||
# backward compatibility with Ansible 2.9 only
|
||||
openstack.cloud.resource:
|
||||
cloud: "{{ cloud }}"
|
||||
openstack.cloud.resources:
|
||||
cloud: "{{ cloud }}"
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
block:
|
||||
- name: Create external network
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: network
|
||||
attributes:
|
||||
name: ansible_network_external
|
||||
is_router_external: true
|
||||
wait: true
|
||||
register: network_external
|
||||
|
||||
- name: Create external subnet
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: subnet
|
||||
attributes:
|
||||
cidr: 10.6.6.0/24
|
||||
ip_version: 4
|
||||
name: ansible_external_subnet
|
||||
network_id: "{{ network_external.resource.id }}"
|
||||
register: subnet_external
|
||||
|
||||
- name: Create external port
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: port
|
||||
attributes:
|
||||
name: ansible_port_external
|
||||
network_id: "{{ network_external.resource.id }}"
|
||||
fixed_ips:
|
||||
- ip_address: 10.6.6.50
|
||||
non_updateable_attributes:
|
||||
- fixed_ips
|
||||
register: port_external
|
||||
|
||||
- name: Create internal network
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: network
|
||||
attributes:
|
||||
name: ansible_network_internal
|
||||
is_router_external: false
|
||||
wait: true
|
||||
register: network_internal
|
||||
|
||||
- name: Create internal subnet
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: subnet
|
||||
attributes:
|
||||
cidr: 10.7.7.0/24
|
||||
ip_version: 4
|
||||
name: ansible_internal_subnet
|
||||
network_id: "{{ network_internal.resource.id }}"
|
||||
register: subnet_internal
|
||||
|
||||
- name: Create internal port 1
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: port
|
||||
attributes:
|
||||
name: ansible_port_internal1
|
||||
network_id: "{{ network_internal.resource.id }}"
|
||||
fixed_ips:
|
||||
- ip_address: 10.7.7.100
|
||||
subnet_id: "{{ subnet_internal.resource.id }}"
|
||||
register: port_internal1
|
||||
|
||||
- name: Create internal port 2
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: port
|
||||
attributes:
|
||||
name: ansible_port_internal2
|
||||
network_id: "{{ network_internal.resource.id }}"
|
||||
fixed_ips:
|
||||
- ip_address: 10.7.7.101
|
||||
subnet_id: "{{ subnet_internal.resource.id }}"
|
||||
register: port_internal2
|
||||
|
||||
- name: Create router
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: router
|
||||
attributes:
|
||||
name: ansible_router
|
||||
external_gateway_info:
|
||||
enable_snat: true
|
||||
external_fixed_ips:
|
||||
- ip_address: 10.6.6.10
|
||||
subnet_id: "{{ subnet_external.resource.id }}"
|
||||
network_id: "{{ network_external.resource.id }}"
|
||||
wait: true
|
||||
register: router
|
||||
|
||||
- name: Attach router to internal subnet
|
||||
openstack.cloud.router:
|
||||
name: ansible_router
|
||||
network: "{{ network_external.resource.id }}"
|
||||
external_fixed_ips:
|
||||
- ip: 10.6.6.10
|
||||
subnet: "{{ subnet_external.resource.id }}"
|
||||
interfaces:
|
||||
- net: "{{ network_internal.resource.id }}"
|
||||
subnet: "{{ subnet_internal.resource.id }}"
|
||||
portip: 10.7.7.1
|
||||
|
||||
- name: Create floating ip address 1
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: ip
|
||||
attributes:
|
||||
name: 10.6.6.150
|
||||
floating_ip_address: 10.6.6.150
|
||||
floating_network_id: "{{ network_external.resource.id }}"
|
||||
port_id: "{{ port_internal1.resource.id }}"
|
||||
register: ip1
|
||||
|
||||
- name: List images
|
||||
openstack.cloud.resources:
|
||||
service: image
|
||||
type: image
|
||||
register: images
|
||||
|
||||
- name: Identify CirrOS image id
|
||||
set_fact:
|
||||
image_id: "{{ images.resources|community.general.json_query(query)|first }}"
|
||||
vars:
|
||||
query: "[?starts_with(name, 'cirros')].id"
|
||||
|
||||
- name: List compute flavors
|
||||
openstack.cloud.resources:
|
||||
service: compute
|
||||
type: flavor
|
||||
register: flavors
|
||||
|
||||
- name: Identify m1.tiny flavor id
|
||||
set_fact:
|
||||
flavor_id: "{{ flavors.resources|community.general.json_query(query)|first }}"
|
||||
vars:
|
||||
query: "[?name == 'm1.tiny'].id"
|
||||
|
||||
- name: Create server 1
|
||||
openstack.cloud.resource:
|
||||
service: compute
|
||||
type: server
|
||||
attributes:
|
||||
name: ansible_server1
|
||||
image_id: "{{ image_id }}"
|
||||
flavor_id: "{{ flavor_id }}"
|
||||
networks:
|
||||
- uuid: "{{ network_internal.resource.id }}"
|
||||
port: "{{ port_internal1.resource.id }}"
|
||||
- uuid: "{{ network_internal.resource.id }}"
|
||||
port: "{{ port_internal2.resource.id }}"
|
||||
non_updateable_attributes:
|
||||
- name
|
||||
- image_id
|
||||
- flavor_id
|
||||
- networks
|
||||
wait: true
|
||||
register: server1
|
||||
|
||||
- name: Create server 2
|
||||
openstack.cloud.resource:
|
||||
service: compute
|
||||
type: server
|
||||
attributes:
|
||||
name: ansible_server2
|
||||
image_id: "{{ image_id }}"
|
||||
flavor_id: "{{ flavor_id }}"
|
||||
networks:
|
||||
- uuid: "{{ network_internal.resource.id }}"
|
||||
non_updateable_attributes:
|
||||
- name
|
||||
- image_id
|
||||
- flavor_id
|
||||
- networks
|
||||
wait: true
|
||||
register: server2
|
||||
|
||||
- name: Run inventory plugin tests
|
||||
always:
|
||||
- name: Remove temporary inventory directory after block execution
|
||||
ansible.builtin.file:
|
||||
path: "{{ tmp_dir.path }}"
|
||||
state: absent
|
||||
when: tmp_dir is defined and 'path' in tmp_dir
|
||||
|
||||
block:
|
||||
- name: Ensure clean environment
|
||||
ansible.builtin.set_fact:
|
||||
tmp_dir: !!null
|
||||
|
||||
- name: Create temporary inventory directory
|
||||
ansible.builtin.tempfile:
|
||||
state: directory
|
||||
register: tmp_dir
|
||||
|
||||
- name: Copy ansible.cfg file
|
||||
ansible.builtin.copy:
|
||||
src: ansible.cfg
|
||||
dest: '{{ tmp_dir.path }}/'
|
||||
mode: '0644'
|
||||
|
||||
- name: Create inventory config file
|
||||
ansible.builtin.template:
|
||||
src: openstack.yaml.j2
|
||||
dest: '{{ tmp_dir.path }}/openstack.yaml'
|
||||
mode: '0644'
|
||||
|
||||
- name: List servers with inventory plugin
|
||||
ansible.builtin.command:
|
||||
cmd: ansible-inventory --list --yaml --inventory-file openstack.yaml
|
||||
chdir: "{{ tmp_dir.path }}"
|
||||
environment:
|
||||
ANSIBLE_INVENTORY_CACHE: "True"
|
||||
ANSIBLE_INVENTORY_CACHE_PLUGIN: "jsonfile"
|
||||
ANSIBLE_CACHE_PLUGIN_CONNECTION: "{{ tmp_dir.path }}/.cache/"
|
||||
register: inventory
|
||||
|
||||
- name: Read YAML output from inventory plugin
|
||||
ansible.builtin.set_fact:
|
||||
inventory: "{{ inventory.stdout | from_yaml }}"
|
||||
|
||||
- name: Check YAML output from inventory plugin
|
||||
assert:
|
||||
that:
|
||||
- inventory.all.children.RegionOne.hosts.keys() | sort == ['ansible_server1', 'ansible_server2'] | sort
|
||||
- ansible_server1.ansible_host == '10.6.6.150'
|
||||
- "'10.7.7.' in ansible_server2.ansible_host"
|
||||
- ansible_server1.ci_compose_id == ansible_server1.openstack.id
|
||||
- ansible_server1.ci_compose_project_id == ansible_server1.openstack.project_id
|
||||
vars:
|
||||
ansible_server1: "{{
|
||||
(inventory.all.children.values()
|
||||
| map(attribute='hosts', default={})
|
||||
| map(attribute='ansible_server1', default={})
|
||||
| reject('equalto', {})
|
||||
| list
|
||||
)[0] }}"
|
||||
ansible_server2: "{{
|
||||
(inventory.all.children.values()
|
||||
| map(attribute='hosts', default={})
|
||||
| map(attribute='ansible_server2', default={})
|
||||
| reject('equalto', {})
|
||||
| list
|
||||
)[0] }}"
|
||||
|
||||
- name: Find Ansible's cache file
|
||||
ansible.builtin.find:
|
||||
paths: "{{ tmp_dir.path }}/.cache/"
|
||||
patterns: 'ansible_inventory_*'
|
||||
register: files
|
||||
|
||||
- name: Assert a single cache file only
|
||||
assert:
|
||||
that:
|
||||
- files.files | length == 1
|
||||
|
||||
- name: Read Ansible's cache file
|
||||
ansible.builtin.slurp:
|
||||
src: "{{ files.files.0.path }}"
|
||||
register: cache
|
||||
|
||||
- name: Process Ansible cache
|
||||
ansible.builtin.set_fact:
|
||||
cache: "{{ cache.content | b64decode | from_yaml }}"
|
||||
|
||||
- name: Check Ansible's cache
|
||||
assert:
|
||||
that:
|
||||
- cache | map(attribute='name') | list | sort == ['ansible_server1', 'ansible_server2'] | sort
|
||||
|
||||
- name: List servers with inventory plugin again
|
||||
ansible.builtin.command:
|
||||
cmd: ansible-inventory --list --yaml --inventory-file openstack.yaml
|
||||
chdir: "{{ tmp_dir.path }}"
|
||||
environment:
|
||||
ANSIBLE_INVENTORY_CACHE: "True"
|
||||
ANSIBLE_INVENTORY_CACHE_PLUGIN: "jsonfile"
|
||||
ANSIBLE_CACHE_PLUGIN_CONNECTION: "{{ tmp_dir.path }}/.cache/"
|
||||
register: inventory
|
||||
|
||||
- name: Read YAML output from inventory plugin again
|
||||
ansible.builtin.set_fact:
|
||||
inventory: "{{ inventory.stdout | from_yaml }}"
|
||||
|
||||
- name: Check YAML output from inventory plugin again
|
||||
assert:
|
||||
that:
|
||||
- inventory.all.children.RegionOne.hosts.keys() | sort == ['ansible_server1', 'ansible_server2'] | sort
|
||||
|
||||
- name: List servers with inventory plugin with IPv4 only
|
||||
ansible.builtin.command:
|
||||
cmd: ansible-inventory --list --yaml --extra-vars only_ipv4=true --inventory-file openstack.yaml
|
||||
chdir: "{{ tmp_dir.path }}"
|
||||
environment:
|
||||
ANSIBLE_INVENTORY_CACHE: "True"
|
||||
ANSIBLE_INVENTORY_CACHE_PLUGIN: "jsonfile"
|
||||
ANSIBLE_CACHE_PLUGIN_CONNECTION: "{{ tmp_dir.path }}/.cache/"
|
||||
register: inventory
|
||||
|
||||
- name: Read YAML output from inventory plugin again
|
||||
ansible.builtin.set_fact:
|
||||
inventory: "{{ inventory.stdout | from_yaml }}"
|
||||
|
||||
- name: Check YAML output from inventory plugin again
|
||||
assert:
|
||||
that:
|
||||
- inventory.all.children.RegionOne.hosts.keys() | sort == ['ansible_server1', 'ansible_server2'] | sort
|
||||
|
||||
- name: Delete server 2
|
||||
openstack.cloud.resource:
|
||||
service: compute
|
||||
type: server
|
||||
attributes:
|
||||
name: ansible_server2
|
||||
state: absent
|
||||
wait: true
|
||||
|
||||
- name: Delete server 1
|
||||
openstack.cloud.resource:
|
||||
service: compute
|
||||
type: server
|
||||
attributes:
|
||||
name: ansible_server1
|
||||
state: absent
|
||||
wait: true
|
||||
|
||||
- name: Delete floating ip address 1
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: ip
|
||||
attributes:
|
||||
floating_ip_address: 10.6.6.150
|
||||
state: absent
|
||||
|
||||
- name: Detach router from internal subnet
|
||||
openstack.cloud.router:
|
||||
name: ansible_router
|
||||
network: "{{ network_external.resource.id }}"
|
||||
external_fixed_ips:
|
||||
- ip: 10.6.6.10
|
||||
subnet: "{{ subnet_external.resource.id }}"
|
||||
interfaces: []
|
||||
|
||||
- name: Delete router
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: router
|
||||
attributes:
|
||||
name: ansible_router
|
||||
state: absent
|
||||
wait: true
|
||||
|
||||
- name: Delete internal port 2
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: port
|
||||
attributes:
|
||||
name: ansible_port_internal2
|
||||
state: absent
|
||||
|
||||
- name: Delete internal port 1
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: port
|
||||
attributes:
|
||||
name: ansible_port_internal1
|
||||
state: absent
|
||||
|
||||
- name: Delete internal subnet
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: subnet
|
||||
attributes:
|
||||
name: ansible_internal_subnet
|
||||
state: absent
|
||||
|
||||
- name: Delete internal network
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: network
|
||||
attributes:
|
||||
name: ansible_network_internal
|
||||
state: absent
|
||||
wait: true
|
||||
|
||||
- name: Delete external port
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: port
|
||||
attributes:
|
||||
name: ansible_port_external
|
||||
state: absent
|
||||
|
||||
- name: Delete external subnet
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: subnet
|
||||
attributes:
|
||||
name: ansible_external_subnet
|
||||
state: absent
|
||||
|
||||
- name: Delete external network
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: network
|
||||
attributes:
|
||||
name: ansible_network_external
|
||||
state: absent
|
||||
wait: true
|
||||
11
ci/roles/inventory/templates/openstack.yaml.j2
Normal file
11
ci/roles/inventory/templates/openstack.yaml.j2
Normal file
@@ -0,0 +1,11 @@
|
||||
plugin: openstack.cloud.openstack
|
||||
|
||||
all_projects: true
|
||||
compose:
|
||||
ci_compose_id: openstack.id
|
||||
ci_compose_project_id: openstack.project_id
|
||||
expand_hostvars: true
|
||||
fail_on_errors: true
|
||||
only_clouds:
|
||||
- "{{ cloud }}"
|
||||
strict: true
|
||||
@@ -1 +1,11 @@
|
||||
keypair_name: shade_keypair
|
||||
expected_fields:
|
||||
- created_at
|
||||
- fingerprint
|
||||
- id
|
||||
- is_deleted
|
||||
- name
|
||||
- private_key
|
||||
- public_key
|
||||
- type
|
||||
- user_id
|
||||
|
||||
@@ -1,13 +1,23 @@
|
||||
---
|
||||
- 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 keypairs
|
||||
- name: Assert fields
|
||||
assert:
|
||||
that:
|
||||
- item in keypair.keypair
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- 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 }}"
|
||||
@@ -16,19 +26,37 @@
|
||||
- name: Ensure that list of keypairs contains single element
|
||||
assert:
|
||||
that:
|
||||
- keypairs['openstack_keypairs']|length == 1
|
||||
- keypairs['keypairs']|length == 1
|
||||
|
||||
# This assert verifies that Ansible is capable serializing data returned by SDK
|
||||
- name: Ensure private key is returned
|
||||
- name: Assert fields
|
||||
assert:
|
||||
that:
|
||||
- keypair.key.public_key is defined and keypair.key.public_key
|
||||
- item in keypairs.keypairs.0.keys()
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
# This assert verifies that Ansible is capable serializing data returned by SDK
|
||||
- name: Ensure public key is returned
|
||||
assert:
|
||||
that:
|
||||
- keypair.keypair.public_key is defined and keypair.keypair.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:
|
||||
@@ -39,20 +67,26 @@
|
||||
- name: Ensure that list of keypairs is empty
|
||||
assert:
|
||||
that:
|
||||
- keypairs['openstack_keypairs']|length == 0
|
||||
- keypairs['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: true
|
||||
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:
|
||||
@@ -63,13 +97,13 @@
|
||||
- name: Ensure that list of keypairs contains single element
|
||||
assert:
|
||||
that:
|
||||
- keypairs['openstack_keypairs']|length == 1
|
||||
- keypairs['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:
|
||||
@@ -80,14 +114,14 @@
|
||||
- name: Ensure that list of keypairs is empty
|
||||
assert:
|
||||
that:
|
||||
- keypairs['openstack_keypairs']|length == 0
|
||||
- keypairs['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:
|
||||
@@ -98,13 +132,13 @@
|
||||
- name: Ensure that list of keypairs contains single element
|
||||
assert:
|
||||
that:
|
||||
- keypairs['openstack_keypairs']|length == 1
|
||||
- keypairs['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:
|
||||
@@ -115,14 +149,14 @@
|
||||
- name: Ensure that list of keypairs is empty
|
||||
assert:
|
||||
that:
|
||||
- keypairs['openstack_keypairs']|length == 0
|
||||
- keypairs['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 +0,0 @@
|
||||
domain_name: ansible_domain
|
||||
@@ -1,36 +0,0 @@
|
||||
---
|
||||
- name: Create keystone domain
|
||||
openstack.cloud.identity_domain:
|
||||
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"
|
||||
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 }}"
|
||||
@@ -1,35 +1,4 @@
|
||||
protocol_name: 'test-protocol'
|
||||
protocol_name_2: 'test-protocol-2'
|
||||
|
||||
# Minimal IDP definition
|
||||
idp_name: 'test-idp'
|
||||
idp_remote_ids:
|
||||
- 'https://auth.example.com/auth/realms/ExampleRealm'
|
||||
|
||||
# Minimal Domain definition
|
||||
domain_name: 'test-domain'
|
||||
|
||||
# Minimal Mapping definition
|
||||
mapping_name_1: 'ansible-test-mapping-1'
|
||||
mapping_name_2: 'ansible-test-mapping-2'
|
||||
mapping_rules_1:
|
||||
- local:
|
||||
- group:
|
||||
domain:
|
||||
name: example_domain
|
||||
name: example-group
|
||||
remote:
|
||||
- type: HTTP_OIDC_GROUPS
|
||||
any_one_of:
|
||||
- group1
|
||||
- group2
|
||||
mapping_rules_2:
|
||||
- local:
|
||||
- group:
|
||||
domain:
|
||||
name: example_domain
|
||||
name: example_group
|
||||
remote:
|
||||
- type: HTTP_OIDC_GROUPS
|
||||
any_one_of:
|
||||
- group1
|
||||
expected_fields:
|
||||
- id
|
||||
- mapping_id
|
||||
- name
|
||||
|
||||
@@ -6,388 +6,336 @@
|
||||
# - Retry change (noop)
|
||||
#
|
||||
- module_defaults:
|
||||
# meta/action_groups.yml glue seems to be missing
|
||||
# group/os:
|
||||
# cloud: "{{ cloud }}"
|
||||
group/openstack.cloud.openstack:
|
||||
cloud: "{{ cloud }}"
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
cloud: "{{ cloud }}" # Backward compatibility with Ansible 2.9
|
||||
idp_id: ansible_idp
|
||||
openstack.cloud.keystone_federation_protocol_info:
|
||||
cloud: "{{ cloud }}" # Backward compatibility with Ansible 2.9
|
||||
idp_id: ansible_idp
|
||||
# Backward compatibility with Ansible 2.9
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
openstack.cloud.federation_idp:
|
||||
cloud: "{{ cloud }}"
|
||||
openstack.cloud.federation_mapping:
|
||||
cloud: "{{ cloud }}"
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
cloud: "{{ cloud }}"
|
||||
idp_id: "{{ idp_name }}"
|
||||
openstack.cloud.keystone_federation_protocol_info:
|
||||
cloud: "{{ cloud }}"
|
||||
idp_id: "{{ idp_name }}"
|
||||
block:
|
||||
# ========================================================================
|
||||
# Initial setup
|
||||
- name: 'Create test Domain'
|
||||
- name: Create test Domain
|
||||
openstack.cloud.identity_domain:
|
||||
name: '{{ domain_name }}'
|
||||
register: create_domain
|
||||
- assert:
|
||||
that:
|
||||
- create_domain is successful
|
||||
- '"id" in create_domain'
|
||||
- name: 'Store domain ID as fact'
|
||||
set_fact:
|
||||
domain_id: '{{ create_domain.id }}'
|
||||
name: ansible_domain
|
||||
register: domain
|
||||
|
||||
- name: 'Create test Identity Provider'
|
||||
- name: Create test Identity Provider
|
||||
openstack.cloud.federation_idp:
|
||||
state: 'present'
|
||||
name: '{{ idp_name }}'
|
||||
domain_id: '{{ domain_id }}'
|
||||
register: create_idp
|
||||
- assert:
|
||||
that:
|
||||
- create_idp is successful
|
||||
state: present
|
||||
name: ansible_idp
|
||||
domain_id: '{{ domain.domain.id }}'
|
||||
|
||||
- name: 'Create test mapping (1)'
|
||||
- name: Create test mapping (1)
|
||||
openstack.cloud.federation_mapping:
|
||||
state: 'present'
|
||||
name: '{{ mapping_name_1 }}'
|
||||
rules: '{{ mapping_rules_1 }}'
|
||||
register: create_mapping
|
||||
- assert:
|
||||
that:
|
||||
- create_mapping is successful
|
||||
- name: 'Create test mapping (2)'
|
||||
state: present
|
||||
name: ansible_mapping1
|
||||
rules:
|
||||
- local:
|
||||
- group:
|
||||
domain:
|
||||
name: example_domain
|
||||
name: example-group
|
||||
remote:
|
||||
- type: HTTP_OIDC_GROUPS
|
||||
any_one_of:
|
||||
- group1
|
||||
- group2
|
||||
|
||||
- name: Create test mapping (2)
|
||||
openstack.cloud.federation_mapping:
|
||||
state: 'present'
|
||||
name: '{{ mapping_name_2 }}'
|
||||
rules: '{{ mapping_rules_2 }}'
|
||||
register: create_mapping
|
||||
- assert:
|
||||
that:
|
||||
- create_mapping is successful
|
||||
state: present
|
||||
name: ansible_mapping2
|
||||
rules:
|
||||
- local:
|
||||
- group:
|
||||
domain:
|
||||
name: example_domain
|
||||
name: example_group
|
||||
remote:
|
||||
- type: HTTP_OIDC_GROUPS
|
||||
any_one_of:
|
||||
- group1
|
||||
|
||||
|
||||
# We *should* have a blank slate to start with, but we also shouldn't
|
||||
# explode if I(state=absent) and the IDP doesn't exist
|
||||
- name: "Ensure Protocol doesn't exist to start"
|
||||
- name: Ensure Protocol does not exist to start
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'absent'
|
||||
name: '{{ protocol_name }}'
|
||||
register: delete_protocol
|
||||
- assert:
|
||||
that:
|
||||
- delete_protocol is successful
|
||||
state: absent
|
||||
name: ansible_protocol1
|
||||
|
||||
# ========================================================================
|
||||
# Creation
|
||||
|
||||
- name: 'Create protocol - CHECK MODE'
|
||||
check_mode: yes
|
||||
- name: Create protocol - CHECK MODE
|
||||
check_mode: true
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'present'
|
||||
name: '{{ protocol_name }}'
|
||||
mapping_id: '{{ mapping_name_1 }}'
|
||||
register: create_protocol
|
||||
state: present
|
||||
name: ansible_protocol1
|
||||
mapping_id: ansible_mapping1
|
||||
register: protocol
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- create_protocol is successful
|
||||
- create_protocol is changed
|
||||
- protocol is changed
|
||||
|
||||
- name: 'Fetch Protocol info (should be absent)'
|
||||
- name: Fetch Protocol info (should be absent)
|
||||
openstack.cloud.keystone_federation_protocol_info:
|
||||
name: '{{ protocol_name }}'
|
||||
register: protocol_info
|
||||
ignore_errors: yes
|
||||
- assert:
|
||||
that:
|
||||
- protocol_info is failed
|
||||
name: ansible_protocol1
|
||||
register: protocols
|
||||
|
||||
- name: 'Create protocol'
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'present'
|
||||
name: '{{ protocol_name }}'
|
||||
mapping_id: '{{ mapping_name_1 }}'
|
||||
register: create_protocol
|
||||
- assert:
|
||||
that:
|
||||
- create_protocol is successful
|
||||
- create_protocol is changed
|
||||
- '"protocol" in create_protocol'
|
||||
- '"id" in protocol'
|
||||
- '"name" in protocol'
|
||||
- '"idp_id" in protocol'
|
||||
- '"mapping_id" in protocol'
|
||||
- protocol.id == protocol_name
|
||||
- protocol.name == protocol_name
|
||||
- protocol.idp_id == idp_name
|
||||
- protocol.mapping_id == mapping_name_1
|
||||
vars:
|
||||
protocol: '{{ create_protocol.protocol }}'
|
||||
- protocols.protocols | length == 0
|
||||
|
||||
- name: 'Create protocol (retry - no change) - CHECK MODE'
|
||||
check_mode: yes
|
||||
- name: Create protocol
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'present'
|
||||
name: '{{ protocol_name }}'
|
||||
mapping_id: '{{ mapping_name_1 }}'
|
||||
register: create_protocol
|
||||
- assert:
|
||||
that:
|
||||
- create_protocol is successful
|
||||
- create_protocol is not changed
|
||||
state: present
|
||||
name: ansible_protocol1
|
||||
mapping_id: ansible_mapping1
|
||||
register: protocol
|
||||
|
||||
- name: 'Create protocol (retry - no change)'
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'present'
|
||||
name: '{{ protocol_name }}'
|
||||
mapping_id: '{{ mapping_name_1 }}'
|
||||
register: create_protocol
|
||||
- assert:
|
||||
that:
|
||||
- create_protocol is successful
|
||||
- create_protocol is not changed
|
||||
- '"protocol" in create_protocol'
|
||||
- '"id" in protocol'
|
||||
- '"name" in protocol'
|
||||
- '"idp_id" in protocol'
|
||||
- '"mapping_id" in protocol'
|
||||
- protocol.id == protocol_name
|
||||
- protocol.name == protocol_name
|
||||
- protocol.idp_id == idp_name
|
||||
- protocol.mapping_id == mapping_name_1
|
||||
vars:
|
||||
protocol: '{{ create_protocol.protocol }}'
|
||||
- protocol is changed
|
||||
- protocol.protocol.id == 'ansible_protocol1'
|
||||
- protocol.protocol.name == 'ansible_protocol1'
|
||||
- protocol.protocol.mapping_id == 'ansible_mapping1'
|
||||
|
||||
- name: assert return values of keystone_federation_protocol module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(protocol.protocol.keys())|length == 0
|
||||
|
||||
- name: Create protocol (retry - no change) - CHECK MODE
|
||||
check_mode: true
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: present
|
||||
name: ansible_protocol1
|
||||
mapping_id: ansible_mapping1
|
||||
register: protocol
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- protocol is not changed
|
||||
|
||||
- name: Create protocol (retry - no change)
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: present
|
||||
name: ansible_protocol1
|
||||
mapping_id: ansible_mapping1
|
||||
register: protocol
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- protocol is not changed
|
||||
- protocol.protocol.id == 'ansible_protocol1'
|
||||
- protocol.protocol.name == 'ansible_protocol1'
|
||||
- protocol.protocol.mapping_id == 'ansible_mapping1'
|
||||
|
||||
# ========================================================================
|
||||
# Update
|
||||
|
||||
- name: 'Update protocol - CHECK MODE'
|
||||
check_mode: yes
|
||||
- name: Update protocol - CHECK MODE
|
||||
check_mode: true
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'present'
|
||||
name: '{{ protocol_name }}'
|
||||
mapping_id: '{{ mapping_name_2 }}'
|
||||
register: update_protocol
|
||||
- assert:
|
||||
that:
|
||||
- update_protocol is successful
|
||||
- update_protocol is changed
|
||||
state: present
|
||||
name: ansible_protocol1
|
||||
mapping_id: ansible_mapping2
|
||||
register: protocol
|
||||
|
||||
- name: 'Update protocol'
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'present'
|
||||
name: '{{ protocol_name }}'
|
||||
mapping_id: '{{ mapping_name_2 }}'
|
||||
register: update_protocol
|
||||
- assert:
|
||||
that:
|
||||
- update_protocol is successful
|
||||
- update_protocol is changed
|
||||
- '"protocol" in update_protocol'
|
||||
- '"id" in protocol'
|
||||
- '"name" in protocol'
|
||||
- '"idp_id" in protocol'
|
||||
- '"mapping_id" in protocol'
|
||||
- protocol.id == protocol_name
|
||||
- protocol.name == protocol_name
|
||||
- protocol.idp_id == idp_name
|
||||
- protocol.mapping_id == mapping_name_2
|
||||
vars:
|
||||
protocol: '{{ update_protocol.protocol }}'
|
||||
- protocol is changed
|
||||
|
||||
- name: 'Update protocol (retry - no change) - CHECK MODE'
|
||||
check_mode: yes
|
||||
- name: Update protocol
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'present'
|
||||
name: '{{ protocol_name }}'
|
||||
mapping_id: '{{ mapping_name_2 }}'
|
||||
register: update_protocol
|
||||
- assert:
|
||||
that:
|
||||
- update_protocol is successful
|
||||
- update_protocol is not changed
|
||||
state: present
|
||||
name: ansible_protocol1
|
||||
mapping_id: ansible_mapping2
|
||||
register: protocol
|
||||
|
||||
- name: 'Update protocol (retry - no change)'
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'present'
|
||||
name: '{{ protocol_name }}'
|
||||
mapping_id: '{{ mapping_name_2 }}'
|
||||
register: update_protocol
|
||||
- assert:
|
||||
that:
|
||||
- update_protocol is successful
|
||||
- update_protocol is not changed
|
||||
- '"protocol" in update_protocol'
|
||||
- '"id" in protocol'
|
||||
- '"name" in protocol'
|
||||
- '"idp_id" in protocol'
|
||||
- '"mapping_id" in protocol'
|
||||
- protocol.id == protocol_name
|
||||
- protocol.name == protocol_name
|
||||
- protocol.idp_id == idp_name
|
||||
- protocol.mapping_id == mapping_name_2
|
||||
vars:
|
||||
protocol: '{{ update_protocol.protocol }}'
|
||||
- protocol is changed
|
||||
- protocol.protocol.id == 'ansible_protocol1'
|
||||
- protocol.protocol.name == 'ansible_protocol1'
|
||||
- protocol.protocol.mapping_id == 'ansible_mapping2'
|
||||
|
||||
- name: Update protocol (retry - no change) - CHECK MODE
|
||||
check_mode: true
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: present
|
||||
name: ansible_protocol1
|
||||
mapping_id: ansible_mapping2
|
||||
register: protocol
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- protocol is not changed
|
||||
|
||||
- name: Update protocol (retry - no change)
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: present
|
||||
name: ansible_protocol1
|
||||
mapping_id: ansible_mapping2
|
||||
register: protocol
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- protocol is not changed
|
||||
- protocol.protocol.id == 'ansible_protocol1'
|
||||
- protocol.protocol.name == 'ansible_protocol1'
|
||||
- protocol.protocol.mapping_id == 'ansible_mapping2'
|
||||
|
||||
# ========================================================================
|
||||
# Create second protocol to test openstack.cloud.keystone_federation_protocol_info
|
||||
|
||||
- name: 'Create protocol (2)'
|
||||
- name: Create protocol (2)
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'present'
|
||||
name: '{{ protocol_name_2 }}'
|
||||
mapping_id: '{{ mapping_name_1 }}'
|
||||
register: create_protocol_2
|
||||
state: present
|
||||
name: ansible_protocol2
|
||||
mapping_id: ansible_mapping1
|
||||
register: protocol
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- create_protocol_2 is successful
|
||||
- create_protocol_2 is changed
|
||||
- '"protocol" in create_protocol_2'
|
||||
- '"id" in protocol'
|
||||
- '"name" in protocol'
|
||||
- '"idp_id" in protocol'
|
||||
- '"mapping_id" in protocol'
|
||||
- protocol.id == protocol_name_2
|
||||
- protocol.name == protocol_name_2
|
||||
- protocol.idp_id == idp_name
|
||||
- protocol.mapping_id == mapping_name_1
|
||||
vars:
|
||||
protocol: '{{ create_protocol_2.protocol }}'
|
||||
- protocol is changed
|
||||
- protocol.protocol.id == 'ansible_protocol2'
|
||||
- protocol.protocol.name == 'ansible_protocol2'
|
||||
- protocol.protocol.mapping_id == 'ansible_mapping1'
|
||||
|
||||
# ========================================================================
|
||||
# Basic tests of openstack.cloud.keystone_federation_protocol_info
|
||||
|
||||
- name: 'Fetch Protocol info (a specific protocol)'
|
||||
- name: Fetch Protocol info (a specific protocol)
|
||||
openstack.cloud.keystone_federation_protocol_info:
|
||||
name: '{{ protocol_name }}'
|
||||
register: protocol_info
|
||||
name: ansible_protocol1
|
||||
register: protocols
|
||||
|
||||
- name: Check info about protocols
|
||||
assert:
|
||||
that:
|
||||
- protocols.protocols|length > 0
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(protocols.protocols[0].keys())|length == 0
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- protocol_info is successful
|
||||
- '"protocols" in protocol_info'
|
||||
- protocol_info.protocols | length == 1
|
||||
- '"id" in protocol'
|
||||
- '"name" in protocol'
|
||||
- '"idp_id" in protocol'
|
||||
- '"mapping_id" in protocol'
|
||||
- protocol.id == protocol_name
|
||||
- protocol.name == protocol_name
|
||||
- protocol.idp_id == idp_name
|
||||
- protocol.mapping_id == mapping_name_2
|
||||
vars:
|
||||
protocol: '{{ protocol_info.protocols[0] }}'
|
||||
- protocols.protocols[0].id == 'ansible_protocol1'
|
||||
- protocols.protocols[0].name == 'ansible_protocol1'
|
||||
- protocols.protocols[0].mapping_id == 'ansible_mapping2'
|
||||
|
||||
- name: 'Fetch Protocol info (all protocols on our test IDP)'
|
||||
- name: Fetch Protocol info (all protocols on our test IDP)
|
||||
openstack.cloud.keystone_federation_protocol_info: {}
|
||||
# idp_id defined in defaults at the start
|
||||
register: protocol_info
|
||||
register: protocols
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- protocol_info is successful
|
||||
- '"protocols" in protocol_info'
|
||||
# We created the IDP, and we're going to delete it:
|
||||
# we should be able to trust what's attached to it
|
||||
- protocol_info.protocols | length == 2
|
||||
- '"id" in protocol_1'
|
||||
- '"name" in protocol_1'
|
||||
- '"idp_id" in protocol_1'
|
||||
- '"mapping_id" in protocol_1'
|
||||
- '"id" in protocol_2'
|
||||
- '"name" in protocol_2'
|
||||
- '"idp_id" in protocol_2'
|
||||
- '"mapping_id" in protocol_2'
|
||||
- protocol_name in (protocol_info.protocols | map(attribute='id'))
|
||||
- protocol_name in (protocol_info.protocols | map(attribute='id'))
|
||||
- protocol_name_2 in (protocol_info.protocols | map(attribute='name'))
|
||||
- protocol_name_2 in (protocol_info.protocols | map(attribute='name'))
|
||||
- mapping_name_1 in (protocol_info.protocols | map(attribute='mapping_id'))
|
||||
- mapping_name_2 in (protocol_info.protocols | map(attribute='mapping_id'))
|
||||
- protocol_1.idp_id == idp_name
|
||||
- protocol_2.idp_id == idp_name
|
||||
vars:
|
||||
protocol_1: '{{ protocol_info.protocols[0] }}'
|
||||
protocol_2: '{{ protocol_info.protocols[1] }}'
|
||||
# We created the IDP, and we're going to delete it:
|
||||
# we should be able to trust what's attached to it
|
||||
- protocols.protocols | length == 2
|
||||
- "'ansible_protocol1' in (protocols.protocols | map(attribute='id'))"
|
||||
- "'ansible_protocol1' in (protocols.protocols | map(attribute='id'))"
|
||||
- "'ansible_protocol2' in (protocols.protocols | map(attribute='name'))"
|
||||
- "'ansible_protocol2' in (protocols.protocols | map(attribute='name'))"
|
||||
- "'ansible_mapping1' in (protocols.protocols | map(attribute='mapping_id'))"
|
||||
- "'ansible_mapping2' in (protocols.protocols | map(attribute='mapping_id'))"
|
||||
|
||||
# ========================================================================
|
||||
# Deletion
|
||||
|
||||
- name: 'Delete protocol - CHECK MODE'
|
||||
check_mode: yes
|
||||
- name: Delete protocol - CHECK MODE
|
||||
check_mode: true
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'absent'
|
||||
name: '{{ protocol_name }}'
|
||||
register: update_protocol
|
||||
- assert:
|
||||
that:
|
||||
- update_protocol is successful
|
||||
- update_protocol is changed
|
||||
state: absent
|
||||
name: ansible_protocol1
|
||||
register: protocol
|
||||
|
||||
- name: 'Delete protocol'
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'absent'
|
||||
name: '{{ protocol_name }}'
|
||||
register: update_protocol
|
||||
- assert:
|
||||
that:
|
||||
- update_protocol is successful
|
||||
- update_protocol is changed
|
||||
- protocol is changed
|
||||
|
||||
- name: 'Delete protocol (retry - no change) - CHECK MODE'
|
||||
check_mode: yes
|
||||
- name: Delete protocol
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'absent'
|
||||
name: '{{ protocol_name }}'
|
||||
register: update_protocol
|
||||
- assert:
|
||||
that:
|
||||
- update_protocol is successful
|
||||
- update_protocol is not changed
|
||||
state: absent
|
||||
name: ansible_protocol1
|
||||
register: protocol
|
||||
|
||||
- name: 'Delete protocol (retry - no change)'
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'absent'
|
||||
name: '{{ protocol_name }}'
|
||||
register: update_protocol
|
||||
- assert:
|
||||
that:
|
||||
- update_protocol is successful
|
||||
- update_protocol is not changed
|
||||
- protocol is changed
|
||||
|
||||
- name: Delete protocol (retry - no change) - CHECK MODE
|
||||
check_mode: true
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: absent
|
||||
name: ansible_protocol1
|
||||
register: protocol
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- protocol is not changed
|
||||
|
||||
- name: Delete protocol (retry - no change)
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: absent
|
||||
name: ansible_protocol1
|
||||
register: protocol
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- protocol is not changed
|
||||
|
||||
# ========================================================================
|
||||
# Clean up after ourselves
|
||||
always:
|
||||
- name: 'Delete protocol'
|
||||
- name: Delete protocol
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'absent'
|
||||
name: '{{ protocol_name }}'
|
||||
idp_id: '{{ idp_name }}'
|
||||
ignore_errors: yes
|
||||
state: absent
|
||||
name: ansible_protocol1
|
||||
idp_id: ansible_idp
|
||||
ignore_errors: true
|
||||
|
||||
- name: 'Delete protocol (2)'
|
||||
- name: Delete protocol (2)
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'absent'
|
||||
name: '{{ protocol_name_2 }}'
|
||||
idp_id: '{{ idp_name }}'
|
||||
ignore_errors: yes
|
||||
state: absent
|
||||
name: ansible_protocol2
|
||||
idp_id: ansible_idp
|
||||
ignore_errors: true
|
||||
|
||||
- name: 'Delete mapping 1'
|
||||
- name: Delete mapping 1
|
||||
openstack.cloud.federation_mapping:
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name_1 }}'
|
||||
ignore_errors: yes
|
||||
state: absent
|
||||
name: ansible_mapping1
|
||||
ignore_errors: true
|
||||
|
||||
- name: 'Delete mapping 2'
|
||||
- name: Delete mapping 2
|
||||
openstack.cloud.federation_mapping:
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name_2 }}'
|
||||
ignore_errors: yes
|
||||
state: absent
|
||||
name: ansible_mapping2
|
||||
ignore_errors: true
|
||||
|
||||
- name: 'Delete idp'
|
||||
- name: Delete idp
|
||||
openstack.cloud.federation_idp:
|
||||
state: 'absent'
|
||||
name: '{{ idp_name }}'
|
||||
ignore_errors: yes
|
||||
state: absent
|
||||
name: ansible_idp
|
||||
ignore_errors: true
|
||||
|
||||
- name: 'Delete domain'
|
||||
- name: Delete domain
|
||||
openstack.cloud.identity_domain:
|
||||
state: 'absent'
|
||||
name: '{{ domain_name }}'
|
||||
ignore_errors: yes
|
||||
state: absent
|
||||
name: ansible_domain
|
||||
ignore_errors: true
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
idp_name: 'test-idp'
|
||||
idp_name_2: 'test-idp-2'
|
||||
idp_description: 'My example IDP'
|
||||
idp_description_2: 'My example Identity Provider'
|
||||
|
||||
domain_name: 'test-domain'
|
||||
expected_fields:
|
||||
- description
|
||||
- domain_id
|
||||
- id
|
||||
- is_enabled
|
||||
- name
|
||||
- remote_ids
|
||||
remote_ids_1:
|
||||
- 'https://auth.example.com/auth/realms/ExampleRealm'
|
||||
- 'https://auth.stage.example.com/auth/realms/ExampleRealm'
|
||||
- 'https://auth.example.com/auth/realms/ExampleRealm'
|
||||
- 'https://auth.stage.example.com/auth/realms/ExampleRealm'
|
||||
remote_ids_2:
|
||||
- 'https://auth.example.com/auth/realms/ExampleRealm'
|
||||
- 'https://auth.example.com/auth/realms/ExampleRealm'
|
||||
remote_ids_3:
|
||||
- 'https://auth.stage.example.com/auth/realms/ExampleRealm'
|
||||
- 'https://auth.stage.example.com/auth/realms/ExampleRealm'
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
role_name: ansible_keystone_role
|
||||
@@ -1,35 +0,0 @@
|
||||
---
|
||||
- name: Create keystone role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ role_name }}"
|
||||
|
||||
- name: List keystone roles
|
||||
openstack.cloud.identity_role_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: roles
|
||||
|
||||
- name: Check roles
|
||||
assert:
|
||||
that:
|
||||
- roles.openstack_roles | length > 0
|
||||
- "'{{ role_name }}' in (roles.openstack_roles | map(attribute='name') | list)"
|
||||
|
||||
- name: List keystone roles by name
|
||||
openstack.cloud.identity_role_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ role_name}}"
|
||||
register: roles1
|
||||
|
||||
- name: Check roles
|
||||
assert:
|
||||
that:
|
||||
- roles1.openstack_roles | length == 1
|
||||
- roles1.openstack_roles[0]['name'] == role_name
|
||||
|
||||
- name: Delete keystone role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ role_name }}"
|
||||
@@ -1,3 +1,22 @@
|
||||
network_name: network_lb
|
||||
subnet_name: subnet_lb
|
||||
lb_name: test_lb
|
||||
expected_fields:
|
||||
- additional_vips
|
||||
- availability_zone
|
||||
- created_at
|
||||
- description
|
||||
- flavor_id
|
||||
- id
|
||||
- is_admin_state_up
|
||||
- listeners
|
||||
- name
|
||||
- operating_status
|
||||
- pools
|
||||
- project_id
|
||||
- provider
|
||||
- provisioning_status
|
||||
- tags
|
||||
- updated_at
|
||||
- vip_address
|
||||
- vip_network_id
|
||||
- vip_port_id
|
||||
- vip_qos_policy_id
|
||||
- vip_subnet_id
|
||||
|
||||
322
ci/roles/loadbalancer/tasks/lb_modules.yml
Normal file
322
ci/roles/loadbalancer/tasks/lb_modules.yml
Normal file
@@ -0,0 +1,322 @@
|
||||
---
|
||||
- name: Create external network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
external: true
|
||||
name: ansible_external_network
|
||||
state: present
|
||||
|
||||
- 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 }}"
|
||||
name: ansible_internal_network
|
||||
state: present
|
||||
|
||||
- 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 load-balancer
|
||||
openstack.cloud.loadbalancer:
|
||||
assign_floating_ip: true
|
||||
cloud: "{{ cloud }}"
|
||||
floating_ip_network: ansible_external_network
|
||||
name: ansible_lb
|
||||
state: present
|
||||
timeout: 450
|
||||
vip_subnet: ansible_internal_subnet
|
||||
register: load_balancer
|
||||
|
||||
- name: Create load-balancer listener
|
||||
openstack.cloud.lb_listener:
|
||||
cloud: "{{ cloud }}"
|
||||
load_balancer: ansible_lb
|
||||
name: ansible_listener
|
||||
protocol: HTTP
|
||||
protocol_port: 8080
|
||||
state: present
|
||||
register: listener
|
||||
|
||||
- name: Assert return values of lb_listener module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- "['allowed_cidrs', 'alpn_protocols', 'connection_limit', 'created_at', 'default_pool', 'default_pool_id',
|
||||
'default_tls_container_ref', 'description', 'id', 'insert_headers', 'is_admin_state_up', 'l7_policies',
|
||||
'load_balancer_id', 'load_balancers', 'name', 'operating_status', 'project_id', 'protocol', 'protocol_port',
|
||||
'provisioning_status', 'sni_container_refs', 'tags', 'timeout_client_data', 'timeout_member_connect',
|
||||
'timeout_member_data', 'timeout_tcp_inspect', 'tls_ciphers', 'tls_versions', 'updated_at'
|
||||
]|difference(listener.listener.keys())|length == 0"
|
||||
|
||||
- name: Create load-balancer listener again
|
||||
openstack.cloud.lb_listener:
|
||||
cloud: "{{ cloud }}"
|
||||
load_balancer: ansible_lb
|
||||
name: ansible_listener
|
||||
protocol: HTTP
|
||||
protocol_port: 8080
|
||||
state: present
|
||||
register: listener
|
||||
|
||||
- name: Assert return values of lb_listener module
|
||||
assert:
|
||||
that:
|
||||
- listener is not changed
|
||||
|
||||
- name: Update load-balancer listener description
|
||||
openstack.cloud.lb_listener:
|
||||
cloud: "{{ cloud }}"
|
||||
description: "Ansible load-balancer listener"
|
||||
load_balancer: ansible_lb
|
||||
name: ansible_listener
|
||||
protocol: HTTP
|
||||
protocol_port: 8080
|
||||
state: present
|
||||
register: listener
|
||||
|
||||
- name: Assert return values of lb_listener module
|
||||
assert:
|
||||
that:
|
||||
- listener.listener.description == "Ansible load-balancer listener"
|
||||
|
||||
- name: Create load-balancer pool
|
||||
openstack.cloud.lb_pool:
|
||||
cloud: "{{ cloud }}"
|
||||
lb_algorithm: ROUND_ROBIN
|
||||
listener: "{{ listener.listener.id }}"
|
||||
name: ansible_pool
|
||||
protocol: HTTP
|
||||
state: present
|
||||
register: pool
|
||||
|
||||
- name: Assert return values of lb_pool module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- "['alpn_protocols', 'created_at', 'description', 'health_monitor_id', 'id', 'is_admin_state_up', 'lb_algorithm',
|
||||
'listener_id', 'listeners', 'loadbalancer_id', 'loadbalancers', 'members','name', 'operating_status',
|
||||
'project_id', 'protocol', 'provisioning_status', 'session_persistence', 'tags', 'tls_ciphers', 'tls_enabled',
|
||||
'tls_versions', 'updated_at'
|
||||
]|difference(pool.pool.keys())|length == 0"
|
||||
|
||||
- name: Create load-balancer pool again
|
||||
openstack.cloud.lb_pool:
|
||||
cloud: "{{ cloud }}"
|
||||
lb_algorithm: ROUND_ROBIN
|
||||
listener: "{{ listener.listener.id }}"
|
||||
name: ansible_pool
|
||||
protocol: HTTP
|
||||
state: present
|
||||
register: pool
|
||||
|
||||
- name: Assert return values of lb_pool module
|
||||
assert:
|
||||
that:
|
||||
- pool is not changed
|
||||
|
||||
- name: Update load-balancer pool description
|
||||
openstack.cloud.lb_pool:
|
||||
cloud: "{{ cloud }}"
|
||||
description: "Ansible load-balancer pool"
|
||||
lb_algorithm: ROUND_ROBIN
|
||||
listener: "{{ listener.listener.id }}"
|
||||
name: ansible_pool
|
||||
protocol: HTTP
|
||||
state: present
|
||||
register: pool
|
||||
|
||||
- name: Assert return values of lb_pool module
|
||||
assert:
|
||||
that:
|
||||
- pool.pool.description == "Ansible load-balancer pool"
|
||||
|
||||
- name: Create load-balancer pool member
|
||||
openstack.cloud.lb_member:
|
||||
address: 10.7.7.42
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_member
|
||||
pool: ansible_pool
|
||||
protocol_port: 8080
|
||||
state: present
|
||||
register: member
|
||||
|
||||
- name: Assert return values of lb_member module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- "['address', 'backup', 'created_at', 'id', 'is_admin_state_up', 'monitor_address', 'monitor_port', 'name',
|
||||
'operating_status', 'project_id', 'protocol_port', 'provisioning_status', 'subnet_id', 'tags', 'updated_at',
|
||||
'weight'
|
||||
]|difference(member.member.keys())|length == 0"
|
||||
|
||||
- name: Create load-balancer pool member again
|
||||
openstack.cloud.lb_member:
|
||||
address: 10.7.7.42
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_member
|
||||
pool: ansible_pool
|
||||
protocol_port: 8080
|
||||
state: present
|
||||
register: member
|
||||
|
||||
- name: Assert return values of lb_member module
|
||||
assert:
|
||||
that:
|
||||
- member is not changed
|
||||
|
||||
- name: Update load-balancer pool member weight
|
||||
openstack.cloud.lb_member:
|
||||
address: 10.7.7.42
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_member
|
||||
pool: ansible_pool
|
||||
protocol_port: 8080
|
||||
state: present
|
||||
weight: 42
|
||||
register: member
|
||||
|
||||
- name: Assert return values of lb_member module
|
||||
assert:
|
||||
that:
|
||||
- member.member.weight == 42
|
||||
|
||||
- name: Create load-balancer health monitor
|
||||
openstack.cloud.lb_health_monitor:
|
||||
cloud: "{{ cloud }}"
|
||||
delay: 10
|
||||
health_monitor_timeout: 5
|
||||
max_retries: 3
|
||||
name: ansible_health_monitor
|
||||
pool: ansible_pool
|
||||
state: present
|
||||
register: health_monitor
|
||||
|
||||
- name: Assert return values of lb_health_monitor module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- "['created_at', 'delay', 'expected_codes', 'http_method', 'id', 'is_admin_state_up', 'max_retries',
|
||||
'max_retries_down', 'name', 'operating_status', 'pool_id', 'pools', 'project_id', 'provisioning_status',
|
||||
'tags', 'timeout', 'type', 'updated_at', 'url_path'
|
||||
]|difference(health_monitor.health_monitor.keys())|length == 0"
|
||||
|
||||
- name: Create load-balancer health monitor again
|
||||
openstack.cloud.lb_health_monitor:
|
||||
cloud: "{{ cloud }}"
|
||||
delay: 10
|
||||
health_monitor_timeout: 5
|
||||
max_retries: 3
|
||||
name: ansible_health_monitor
|
||||
pool: ansible_pool
|
||||
state: present
|
||||
register: health_monitor
|
||||
|
||||
- name: Assert return values of lb_health_monitor module
|
||||
assert:
|
||||
that:
|
||||
- health_monitor is not changed
|
||||
|
||||
- name: Update load-balancer health monitor delay
|
||||
openstack.cloud.lb_health_monitor:
|
||||
cloud: "{{ cloud }}"
|
||||
delay: 1337
|
||||
health_monitor_timeout: 5
|
||||
max_retries: 3
|
||||
name: ansible_health_monitor
|
||||
pool: ansible_pool
|
||||
state: present
|
||||
register: health_monitor
|
||||
|
||||
- name: Assert return values of lb_health_monitor module
|
||||
assert:
|
||||
that:
|
||||
- health_monitor.health_monitor.delay == 1337
|
||||
|
||||
- name: Delete load-balancer health monitor
|
||||
openstack.cloud.lb_health_monitor:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_health_monitor
|
||||
state: absent
|
||||
|
||||
- name: Delete load-balancer pool member
|
||||
openstack.cloud.lb_member:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_member
|
||||
pool: ansible_pool
|
||||
state: absent
|
||||
|
||||
- name: Delete load-balancer pool
|
||||
openstack.cloud.lb_pool:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_pool
|
||||
state: absent
|
||||
|
||||
- name: Delete load-balancer listener
|
||||
openstack.cloud.lb_listener:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_listener
|
||||
state: absent
|
||||
|
||||
- name: Delete load-balancer
|
||||
openstack.cloud.loadbalancer:
|
||||
cloud: "{{ cloud }}"
|
||||
delete_floating_ip: true
|
||||
name: ansible_lb
|
||||
state: absent
|
||||
timeout: 150
|
||||
|
||||
- name: Delete router
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_router
|
||||
state: absent
|
||||
|
||||
- name: Delete internal subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_internal_subnet
|
||||
state: absent
|
||||
|
||||
- name: Delete internal network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_internal_network
|
||||
state: absent
|
||||
|
||||
- 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
|
||||
@@ -1,16 +1,52 @@
|
||||
|
||||
---
|
||||
- name: Create network {{ network_name }} for LB
|
||||
- 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 external network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name }}"
|
||||
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 subnet {{ subnet_name }} on network {{ network_name }} for LB
|
||||
- name: Create internal network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_internal_network
|
||||
state: present
|
||||
|
||||
- name: Create internal subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
network_name: "{{ network_name }}"
|
||||
name: "{{ subnet_name }}"
|
||||
network_name: ansible_internal_network
|
||||
name: ansible_internal_subnet
|
||||
state: present
|
||||
enable_dhcp: true
|
||||
dns_nameservers:
|
||||
@@ -21,30 +57,230 @@
|
||||
allocation_pool_start: 192.168.0.2
|
||||
allocation_pool_end: 192.168.0.254
|
||||
|
||||
- name: Create loadbalancer - generic
|
||||
- name: Create router 1
|
||||
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: 192.168.0.1
|
||||
name: ansible_router1
|
||||
network: ansible_external_network
|
||||
state: present
|
||||
|
||||
- name: Create load-balancer
|
||||
openstack.cloud.loadbalancer:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ lb_name }}"
|
||||
vip_subnet: "{{ subnet_name }}"
|
||||
timeout: 450
|
||||
name: ansible_lb
|
||||
vip_subnet: ansible_internal_subnet
|
||||
timeout: 1200
|
||||
register: load_balancer
|
||||
|
||||
- name: Delete loadbalancer
|
||||
- name: Assert return values of loadbalancer module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(load_balancer.load_balancer.keys())|length == 0
|
||||
|
||||
- name: Create load-balancer again
|
||||
openstack.cloud.loadbalancer:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_lb
|
||||
vip_subnet: ansible_internal_subnet
|
||||
timeout: 1200
|
||||
register: load_balancer
|
||||
|
||||
- name: Assert return values of loadbalancer module
|
||||
assert:
|
||||
that:
|
||||
- load_balancer is not changed
|
||||
|
||||
- name: Update load-balancer description
|
||||
openstack.cloud.loadbalancer:
|
||||
cloud: "{{ cloud }}"
|
||||
description: "Ansible load-balancer"
|
||||
state: present
|
||||
name: ansible_lb
|
||||
vip_subnet: ansible_internal_subnet
|
||||
timeout: 1200
|
||||
register: load_balancer
|
||||
|
||||
- name: Assert return values of loadbalancer module
|
||||
assert:
|
||||
that:
|
||||
- load_balancer.load_balancer.description == "Ansible load-balancer"
|
||||
|
||||
- name: Delete load-balancer
|
||||
openstack.cloud.loadbalancer:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_lb
|
||||
state: absent
|
||||
name: "{{ lb_name }}"
|
||||
timeout: 150
|
||||
|
||||
- name: Delete subnet {{ subnet_name }} on network {{ network_name }}
|
||||
openstack.cloud.subnet:
|
||||
- name: Create load-balancer with floating ip address
|
||||
openstack.cloud.loadbalancer:
|
||||
assign_floating_ip: true
|
||||
cloud: "{{ cloud }}"
|
||||
network_name: "{{ network_name }}"
|
||||
name: "{{ subnet_name }}"
|
||||
# Help Octavia to find a external network which is connected to ansible_internal_subnet via a router
|
||||
floating_ip_network: ansible_external_network
|
||||
name: ansible_lb
|
||||
state: present
|
||||
timeout: 1200
|
||||
vip_subnet: ansible_internal_subnet
|
||||
register: load_balancer
|
||||
|
||||
- name: Assert return values of loadbalancer module
|
||||
assert:
|
||||
that:
|
||||
- "'floating_ip' in load_balancer.keys()"
|
||||
- load_balancer.load_balancer.vip_address == load_balancer.floating_ip.fixed_ip_address
|
||||
|
||||
- name: Delete load-balancer with floating ip address
|
||||
openstack.cloud.loadbalancer:
|
||||
cloud: "{{ cloud }}"
|
||||
delete_floating_ip: true
|
||||
name: ansible_lb
|
||||
state: absent
|
||||
timeout: 150
|
||||
|
||||
- name: List all floating ips
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: floating_ips
|
||||
|
||||
- name: Assert load-balancer's floating ip has been deleted
|
||||
assert:
|
||||
that:
|
||||
- load_balancer.floating_ip.floating_ip_address not in
|
||||
floating_ips.floating_ips|map(attribute='floating_ip_address')|sort|list
|
||||
|
||||
- name: Create load-balancer with floating ip address from specific network
|
||||
openstack.cloud.loadbalancer:
|
||||
assign_floating_ip: true
|
||||
cloud: "{{ cloud }}"
|
||||
floating_ip_network: ansible_external_network
|
||||
name: ansible_lb
|
||||
state: present
|
||||
timeout: 1200
|
||||
vip_subnet: ansible_internal_subnet
|
||||
register: load_balancer
|
||||
|
||||
- name: Assert return values of loadbalancer module
|
||||
assert:
|
||||
that:
|
||||
- load_balancer.floating_ip.floating_network_id == external_network.network.id
|
||||
|
||||
- name: Create load-balancer with floating ip address from specific network again
|
||||
openstack.cloud.loadbalancer:
|
||||
assign_floating_ip: true
|
||||
cloud: "{{ cloud }}"
|
||||
floating_ip_network: ansible_external_network
|
||||
name: ansible_lb
|
||||
state: present
|
||||
timeout: 1200
|
||||
vip_subnet: ansible_internal_subnet
|
||||
register: load_balancer
|
||||
|
||||
- name: Assert return values of loadbalancer module
|
||||
assert:
|
||||
that:
|
||||
- load_balancer is not changed
|
||||
|
||||
# TODO: Replace with appropriate Ansible module once available
|
||||
- name: Disassociate floating ip from load-balancer
|
||||
command: >
|
||||
openstack --os-cloud={{ cloud }} floating ip unset --port {{ load_balancer.floating_ip.floating_ip_address }}
|
||||
|
||||
- name: Reassign floating ip address to load-balancer
|
||||
openstack.cloud.loadbalancer:
|
||||
assign_floating_ip: true
|
||||
cloud: "{{ cloud }}"
|
||||
floating_ip_network: ansible_external_network
|
||||
name: ansible_lb
|
||||
state: present
|
||||
timeout: 1200
|
||||
vip_subnet: ansible_internal_subnet
|
||||
register: load_balancer2
|
||||
|
||||
- name: Assert return values of loadbalancer module
|
||||
assert:
|
||||
that:
|
||||
- load_balancer2.floating_ip.floating_network_id == external_network.network.id
|
||||
- load_balancer.floating_ip.floating_ip_address == load_balancer2.floating_ip.floating_ip_address
|
||||
|
||||
- name: Reassign specific floating ip address to load-balancer
|
||||
openstack.cloud.loadbalancer:
|
||||
assign_floating_ip: true
|
||||
cloud: "{{ cloud }}"
|
||||
floating_ip_address: 10.6.6.42
|
||||
floating_ip_network: ansible_external_network
|
||||
name: ansible_lb
|
||||
state: present
|
||||
timeout: 1200
|
||||
vip_subnet: ansible_internal_subnet
|
||||
register: load_balancer
|
||||
|
||||
- name: Assert return values of loadbalancer module
|
||||
assert:
|
||||
that:
|
||||
- load_balancer.floating_ip.floating_network_id == external_network.network.id
|
||||
- load_balancer.floating_ip.floating_ip_address == '10.6.6.42'
|
||||
|
||||
- name: Disassociate floating ip address with load-balancer
|
||||
openstack.cloud.loadbalancer:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_lb
|
||||
state: present
|
||||
timeout: 1200
|
||||
vip_subnet: ansible_internal_subnet
|
||||
register: load_balancer
|
||||
|
||||
- name: Assert return values of loadbalancer module
|
||||
assert:
|
||||
that:
|
||||
- "'floating_ip' not in load_balancer.keys()"
|
||||
|
||||
- name: Delete load-balancer
|
||||
openstack.cloud.loadbalancer:
|
||||
cloud: "{{ cloud }}"
|
||||
delete_floating_ip: true
|
||||
name: ansible_lb
|
||||
state: absent
|
||||
timeout: 150
|
||||
|
||||
- name: Delete router 1
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_router1
|
||||
state: absent
|
||||
|
||||
- name: Delete network {{ network_name }} of LB
|
||||
- name: Delete internal subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_internal_subnet
|
||||
state: absent
|
||||
|
||||
- name: Delete internal network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name }}"
|
||||
name: ansible_internal_network
|
||||
state: absent
|
||||
|
||||
- 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
|
||||
|
||||
- import_tasks: lb_modules.yml
|
||||
|
||||
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"
|
||||
15
ci/roles/logging/tasks/main.yaml
Normal file
15
ci/roles/logging/tasks/main.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
- name: Trigger flavor listing to create logs
|
||||
openstack.cloud.compute_flavor_info:
|
||||
cloud: "{{ cloud }}"
|
||||
sdk_log_path: "{{ sdk_log_file_path }}"
|
||||
sdk_log_level: "DEBUG"
|
||||
|
||||
- name: Read openstacksdk's log file
|
||||
ansible.builtin.slurp:
|
||||
src: "{{ sdk_log_file_path }}"
|
||||
register: log
|
||||
|
||||
- name: Print contents of openstacksdk's log
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ log['content'] | b64decode }}"
|
||||
@@ -1,7 +1,35 @@
|
||||
network_name: shade_network
|
||||
network_name_newparams: newparams_network
|
||||
network_shared: false
|
||||
network_external: false
|
||||
expected_fields:
|
||||
- availability_zone_hints
|
||||
- availability_zones
|
||||
- created_at
|
||||
- description
|
||||
- dns_domain
|
||||
- id
|
||||
- ipv4_address_scope_id
|
||||
- ipv6_address_scope_id
|
||||
- is_admin_state_up
|
||||
- is_default
|
||||
- is_port_security_enabled
|
||||
- is_router_external
|
||||
- is_shared
|
||||
- is_vlan_transparent
|
||||
- mtu
|
||||
- name
|
||||
- project_id
|
||||
- provider_network_type
|
||||
- provider_physical_network
|
||||
- provider_segmentation_id
|
||||
- qos_policy_id
|
||||
- revision_number
|
||||
- segments
|
||||
- status
|
||||
- subnet_ids
|
||||
- tags
|
||||
- updated_at
|
||||
dns_domain: example.opendev.org
|
||||
mtu: 1250
|
||||
network_name: shade_network
|
||||
network_name_newparams: newparams_network
|
||||
network_name_updates: update_network
|
||||
network_shared: false
|
||||
port_security_enabled: false
|
||||
|
||||
@@ -5,7 +5,29 @@
|
||||
name: "{{ network_name }}"
|
||||
state: present
|
||||
shared: "{{ network_shared }}"
|
||||
external: "{{ network_external }}"
|
||||
external: false
|
||||
register: infonet
|
||||
|
||||
- name: Check output of creating network
|
||||
assert:
|
||||
that:
|
||||
- infonet.network
|
||||
- item in infonet.network
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- name: Gather networks info
|
||||
openstack.cloud.networks_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ infonet.network.id }}"
|
||||
register: result
|
||||
|
||||
- name: Check output of network info
|
||||
# TODO: Remove ignore_errors once SDK's search_networks() (re)implemented searching by id
|
||||
ignore_errors: true
|
||||
assert:
|
||||
that:
|
||||
- result.networks|length == 1
|
||||
- infonet.network.id == result.networks[0].id
|
||||
|
||||
- name: Gather networks info - generic
|
||||
openstack.cloud.networks_info:
|
||||
@@ -15,12 +37,28 @@
|
||||
shared: "{{ network_shared|string|capitalize }}"
|
||||
register: result
|
||||
|
||||
- name: Check output of network info
|
||||
assert:
|
||||
that:
|
||||
- item in result.networks[0]
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- name: Gather networks info
|
||||
openstack.cloud.networks_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name }}"
|
||||
filters:
|
||||
shared: "False"
|
||||
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 }}
|
||||
- result.networks.0.name == network_name
|
||||
- "'is_shared' in result.networks.0"
|
||||
- result.networks.0['is_shared']|lower == network_shared|lower
|
||||
- "'is_router_external' in result.networks.0"
|
||||
- not (result.networks[0]['is_router_external'] | bool)
|
||||
|
||||
- name: Create network - with new SDK params
|
||||
openstack.cloud.network:
|
||||
@@ -28,33 +66,25 @@
|
||||
name: "{{ network_name_newparams }}"
|
||||
state: present
|
||||
shared: "{{ network_shared }}"
|
||||
external: "{{ network_external }}"
|
||||
external: false
|
||||
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', '<')
|
||||
ignore_errors: true
|
||||
|
||||
- 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', '>=')
|
||||
- result_newparams.networks.0.name == network_name_newparams
|
||||
- result_newparams.networks.0.mtu == mtu
|
||||
- "'is_port_security_enabled' in result_newparams.networks.0"
|
||||
- result_newparams.networks.0['is_port_security_enabled'] == port_security_enabled
|
||||
|
||||
- name: Delete network - generic and with new SDK params
|
||||
openstack.cloud.network:
|
||||
@@ -74,4 +104,67 @@
|
||||
- name: Verify networks info - deleted
|
||||
assert:
|
||||
that:
|
||||
- result_nonet.openstack_networks == []
|
||||
- result_nonet.networks == []
|
||||
|
||||
- name: Create network - updates
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name_updates }}"
|
||||
state: present
|
||||
shared: "{{ network_shared }}"
|
||||
external: false
|
||||
mtu: "{{ mtu }}"
|
||||
port_security_enabled: "{{ port_security_enabled }}"
|
||||
register: result_create_nw_for_updates
|
||||
|
||||
- name: Update network - update failure
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name_updates }}"
|
||||
state: present
|
||||
shared: "{{ network_shared }}"
|
||||
external: false
|
||||
mtu: "{{ mtu }}"
|
||||
port_security_enabled: "{{ port_security_enabled }}"
|
||||
# You cannot update this property.
|
||||
provider_physical_network: cannot_be_updated
|
||||
ignore_errors: true
|
||||
register: result_nw_update_failure
|
||||
|
||||
- name: Verify networks info - update fail
|
||||
assert:
|
||||
that:
|
||||
- result_nw_update_failure is failed
|
||||
|
||||
- name: Update network - update success
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name_updates }}"
|
||||
state: present
|
||||
shared: "{{ network_shared }}"
|
||||
external: false
|
||||
# NOTE: This property should be updated
|
||||
mtu: "{{ mtu - 50 }}"
|
||||
# NOTE: This property should be updated
|
||||
port_security_enabled: "{{ not port_security_enabled }}"
|
||||
register: result_nw_update_success
|
||||
|
||||
- name: Gather networks info - updates
|
||||
openstack.cloud.networks_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name_updates }}"
|
||||
register: result_network_updates_info
|
||||
|
||||
- name: Verify networks info - update success
|
||||
assert:
|
||||
that:
|
||||
- result_nw_update_success is changed
|
||||
- result_network_updates_info.networks.0.name == network_name_updates
|
||||
- result_network_updates_info.networks.0.mtu == mtu - 50
|
||||
- result_network_updates_info.networks.0['is_port_security_enabled'] == (not port_security_enabled)
|
||||
|
||||
- name: Delete network - updates
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name_updates }}"
|
||||
state: absent
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
---
|
||||
# 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
|
||||
10
ci/roles/neutron_rbac_policy/defaults/main.yml
Normal file
10
ci/roles/neutron_rbac_policy/defaults/main.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
expected_fields:
|
||||
- action
|
||||
- id
|
||||
- name
|
||||
- object_id
|
||||
- object_type
|
||||
- project_id
|
||||
- target_project_id
|
||||
- tenant_id
|
||||
all_project_symbol: '*'
|
||||
123
ci/roles/neutron_rbac_policy/tasks/main.yml
Normal file
123
ci/roles/neutron_rbac_policy/tasks/main.yml
Normal file
@@ -0,0 +1,123 @@
|
||||
---
|
||||
- name: Create source project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_source_project
|
||||
description: Source project for network RBAC test
|
||||
domain: default
|
||||
is_enabled: True
|
||||
register: source_project
|
||||
|
||||
- name: Create network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "ansible_network"
|
||||
state: present
|
||||
project: "{{ source_project.project.id }}"
|
||||
shared: false
|
||||
external: true
|
||||
register: network
|
||||
|
||||
- name: Create target project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_target_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: Assert return values of neutron_rbac_policy module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(rbac_policy.rbac_policy.keys())|length == 0
|
||||
|
||||
- name: Get all rbac policies for {{ source_project.project.name }} - after creation
|
||||
openstack.cloud.neutron_rbac_policies_info:
|
||||
cloud: "{{ cloud }}"
|
||||
project: "{{ source_project.project.id }}"
|
||||
register: rbac_policies
|
||||
|
||||
- name: Assert return values of neutron_rbac_policy_info module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(rbac_policies.rbac_policies[0].keys())|length == 0
|
||||
|
||||
- name: Verify policy exists - after creation
|
||||
assert:
|
||||
that:
|
||||
- rbac_policy.rbac_policy.id in
|
||||
( rbac_policies.rbac_policies | map(attribute='id') | list )
|
||||
|
||||
- name: Delete RBAC policy
|
||||
openstack.cloud.neutron_rbac_policy:
|
||||
cloud: "{{ cloud }}"
|
||||
id: "{{ rbac_policy.rbac_policy.id }}"
|
||||
state: absent
|
||||
|
||||
- name: Create a new network RBAC policy by targeting all projects
|
||||
openstack.cloud.neutron_rbac_policy:
|
||||
cloud: "{{ cloud }}"
|
||||
object_id: "{{ network.network.id }}"
|
||||
object_type: 'network'
|
||||
action: 'access_as_shared'
|
||||
target_all_project: true
|
||||
project_id: "{{ source_project.project.id }}"
|
||||
register: rbac_policy
|
||||
|
||||
- name: Assert return values of neutron_rbac_policy module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(rbac_policy.rbac_policy.keys())|length == 0
|
||||
- rbac_policy.rbac_policy.target_project_id == all_project_symbol
|
||||
|
||||
- name: Delete RBAC policy
|
||||
openstack.cloud.neutron_rbac_policy:
|
||||
cloud: "{{ cloud }}"
|
||||
id: "{{ rbac_policy.rbac_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: "{{ source_project.project.id }}"
|
||||
register: rbac_policies_remaining
|
||||
|
||||
- name: Verify policy does not exist - after deletion
|
||||
assert:
|
||||
that:
|
||||
- rbac_policy.rbac_policy.id not in
|
||||
( rbac_policies_remaining.rbac_policies | map(attribute='id') | list )
|
||||
|
||||
- name: Delete target project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_target_project
|
||||
|
||||
- name: Delete network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "ansible_network"
|
||||
state: absent
|
||||
|
||||
- name: Delete source project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_source_project
|
||||
@@ -1,53 +0,0 @@
|
||||
---
|
||||
- name: Create public flavor
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_public_flavor
|
||||
is_public: True
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
ephemeral: 10
|
||||
swap: 1
|
||||
flavorid: 12345
|
||||
|
||||
- name: Delete public flavor
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_public_flavor
|
||||
|
||||
- name: Create private flavor
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_private_flavor
|
||||
is_public: False
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
ephemeral: 10
|
||||
swap: 1
|
||||
flavorid: 12345
|
||||
|
||||
- name: Delete private flavor
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_private_flavor
|
||||
|
||||
- name: Create flavor (defaults)
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_defaults_flavor
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
|
||||
- name: Delete flavor (defaults)
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_defaults_flavor
|
||||
@@ -1,22 +0,0 @@
|
||||
---
|
||||
|
||||
- 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"
|
||||
|
||||
- name: Assert fields
|
||||
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: Get nova conductor services info
|
||||
openstack.cloud.compute_service_info:
|
||||
cloud: "{{ cloud }}"
|
||||
binary: "nova-conductor"
|
||||
register: result
|
||||
failed_when: "result.openstack_compute_services | length <= 0"
|
||||
32
ci/roles/object/defaults/main.yml
Normal file
32
ci/roles/object/defaults/main.yml
Normal file
@@ -0,0 +1,32 @@
|
||||
expected_fields:
|
||||
- accept_ranges
|
||||
- access_control_allow_origin
|
||||
- content_disposition
|
||||
- content_encoding
|
||||
- content_length
|
||||
- content_type
|
||||
- copy_from
|
||||
- delete_after
|
||||
- delete_at
|
||||
- etag
|
||||
- expires_at
|
||||
- id
|
||||
- if_match
|
||||
- if_modified_since
|
||||
- if_none_match
|
||||
- if_unmodified_since
|
||||
- is_content_type_detected
|
||||
- is_newest
|
||||
- is_static_large_object
|
||||
- last_modified_at
|
||||
- manifest
|
||||
- metadata
|
||||
- multipart_manifest
|
||||
- name
|
||||
- object_manifest
|
||||
- range
|
||||
- signature
|
||||
- symlink_target
|
||||
- symlink_target_account
|
||||
- timestamp
|
||||
- transfer_encoding
|
||||
@@ -1,37 +1,76 @@
|
||||
---
|
||||
- name: Create a test object file
|
||||
shell: mktemp
|
||||
register: tmp_file
|
||||
|
||||
- name: Create container
|
||||
openstack.cloud.object:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
container: ansible_container
|
||||
container_access: private
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_container
|
||||
|
||||
- name: Put object
|
||||
- name: Create object from data
|
||||
openstack.cloud.object:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_object
|
||||
filename: "{{ tmp_file.stdout }}"
|
||||
container: ansible_container
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_object
|
||||
data: "this is a test"
|
||||
container: ansible_container
|
||||
register: object
|
||||
|
||||
- name: Assert return values of object module
|
||||
assert:
|
||||
that:
|
||||
- object.object.id == "ansible_object"
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(object.object.keys())|length == 0
|
||||
|
||||
- name: Delete object
|
||||
openstack.cloud.object:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_object
|
||||
container: ansible_container
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_object
|
||||
container: ansible_container
|
||||
|
||||
- name: Create object from file
|
||||
block:
|
||||
- name: Create temporary data file
|
||||
ansible.builtin.tempfile:
|
||||
register: tmp_file
|
||||
|
||||
- name: Populate data file
|
||||
ansible.builtin.copy:
|
||||
content: "this is a test"
|
||||
dest: "{{ tmp_file.path }}"
|
||||
|
||||
- name: Create object from data file
|
||||
openstack.cloud.object:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_object
|
||||
filename: "{{ tmp_file.path }}"
|
||||
container: ansible_container
|
||||
register: object
|
||||
|
||||
always:
|
||||
- name: Remove temporary data file
|
||||
ansible.builtin.file:
|
||||
path: "{{ tmp_file.path }}"
|
||||
state: absent
|
||||
when: tmp_file is defined and 'path' in tmp_file
|
||||
|
||||
- name: Assert return values of object module
|
||||
assert:
|
||||
that:
|
||||
- object.object.id == "ansible_object"
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(object.object.keys())|length == 0
|
||||
|
||||
- name: Delete object
|
||||
openstack.cloud.object:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_object
|
||||
container: ansible_container
|
||||
|
||||
- name: Delete container
|
||||
openstack.cloud.object:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
container: ansible_container
|
||||
|
||||
- name: Delete test object file
|
||||
file:
|
||||
name: "{{ tmp_file.stdout }}"
|
||||
state: absent
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_container
|
||||
|
||||
@@ -1 +1,22 @@
|
||||
container_name: "test-container"
|
||||
expected_fields:
|
||||
- bytes
|
||||
- bytes_used
|
||||
- content_type
|
||||
- count
|
||||
- history_location
|
||||
- id
|
||||
- if_none_match
|
||||
- is_content_type_detected
|
||||
- is_newest
|
||||
- meta_temp_url_key
|
||||
- meta_temp_url_key_2
|
||||
- metadata
|
||||
- name
|
||||
- object_count
|
||||
- read_ACL
|
||||
- storage_policy
|
||||
- sync_key
|
||||
- sync_to
|
||||
- timestamp
|
||||
- versions_location
|
||||
- write_ACL
|
||||
|
||||
@@ -1,60 +1,108 @@
|
||||
---
|
||||
- module_defaults:
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
block:
|
||||
- name: Create an empty container
|
||||
openstack.cloud.object_container:
|
||||
container: "{{ container_name }}"
|
||||
register: container
|
||||
- name: Create an empty container with public access
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_container
|
||||
read_ACL: ".r:*,.rlistings"
|
||||
register: container
|
||||
|
||||
- name: Verify container was created
|
||||
assert:
|
||||
that:
|
||||
- container is success
|
||||
- container is changed
|
||||
- container.container.name == container_name
|
||||
- name: Assert return values of container module
|
||||
assert:
|
||||
that:
|
||||
- container is changed
|
||||
- container.container.name == "ansible_container"
|
||||
- container.container.read_ACL == ".r:*,.rlistings"
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(container.container.keys())|length == 0
|
||||
|
||||
- name: Set metadata for a container
|
||||
openstack.cloud.object_container:
|
||||
container: "{{ container_name }}"
|
||||
metadata: "Cache-Control='no-cache'"
|
||||
register: set_meta
|
||||
- name: Set container metadata aka container properties
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_container
|
||||
metadata:
|
||||
'Cache-Control': 'no-cache'
|
||||
'foo': 'bar'
|
||||
register: container
|
||||
|
||||
- name: Verify container metadata was set
|
||||
assert:
|
||||
that:
|
||||
- set_meta is success
|
||||
- set_meta is changed
|
||||
- name: Verify container metadata was set
|
||||
assert:
|
||||
that:
|
||||
- container is changed
|
||||
- ('cache-control' in container.container.metadata.keys()|map('lower'))
|
||||
- container.container.metadata['foo'] == 'bar'
|
||||
|
||||
- name: Delete some keys from container metadata
|
||||
openstack.cloud.object_container:
|
||||
container: "{{ container_name }}"
|
||||
keys:
|
||||
- Cache-Control
|
||||
register: delete_meta
|
||||
- name: Update container metadata
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_container
|
||||
metadata:
|
||||
'foo': 'baz'
|
||||
register: container
|
||||
|
||||
- name: Verify some keys from container metadata was deleted
|
||||
assert:
|
||||
that:
|
||||
- delete_meta is success
|
||||
- delete_meta is changed
|
||||
- name: Verify container metadata was updated
|
||||
assert:
|
||||
that:
|
||||
- container is changed
|
||||
- ('cache-control' in container.container.metadata.keys()|map('lower'))
|
||||
- container.container.metadata['foo'] == 'baz'
|
||||
|
||||
- name: Delete container
|
||||
openstack.cloud.object_container:
|
||||
container: "{{ container_name }}"
|
||||
state: absent
|
||||
register: deleted
|
||||
- name: Update a container
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_container
|
||||
delete_metadata_keys:
|
||||
- 'Cache-Control'
|
||||
read_ACL: ""
|
||||
register: container
|
||||
|
||||
- name: Verify container was deleted
|
||||
assert:
|
||||
that:
|
||||
- deleted is success
|
||||
- deleted is changed
|
||||
- name: Verify updated container
|
||||
assert:
|
||||
that:
|
||||
- container is changed
|
||||
- ('cache-control' not in container.container.metadata.keys()|map('lower'))
|
||||
- "container.container.metadata == {'foo': 'baz'}"
|
||||
- container.container.read_ACL is none or container.container.read_ACL == ""
|
||||
|
||||
always:
|
||||
- name: Delete container
|
||||
openstack.cloud.object_container:
|
||||
container: "{{ container_name }}"
|
||||
state: absent
|
||||
ignore_errors: yes
|
||||
- name: Delete container
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_container
|
||||
state: absent
|
||||
register: container
|
||||
|
||||
- name: Verify container was deleted
|
||||
assert:
|
||||
that:
|
||||
- container is changed
|
||||
|
||||
- name: Delete container again
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_container
|
||||
state: absent
|
||||
register: container
|
||||
|
||||
- name: Verify container was not deleted again
|
||||
assert:
|
||||
that:
|
||||
- container is not changed
|
||||
|
||||
- name: Create another container for recursive deletion
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_container2
|
||||
|
||||
- name: Load an object into container
|
||||
openstack.cloud.object:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_object
|
||||
data: "this is another test"
|
||||
container: ansible_container2
|
||||
|
||||
- name: Delete container recursively
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_container2
|
||||
delete_with_all_objects: true
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
---
|
||||
stack_name: "test-stack"
|
||||
@@ -1,44 +0,0 @@
|
||||
---
|
||||
- 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')
|
||||
@@ -1,9 +1,42 @@
|
||||
expected_fields:
|
||||
- allowed_address_pairs
|
||||
- binding_host_id
|
||||
- binding_profile
|
||||
- binding_vif_details
|
||||
- binding_vif_type
|
||||
- binding_vnic_type
|
||||
- created_at
|
||||
- data_plane_status
|
||||
- description
|
||||
- device_id
|
||||
- device_owner
|
||||
- device_profile
|
||||
- dns_assignment
|
||||
- dns_domain
|
||||
- dns_name
|
||||
- extra_dhcp_opts
|
||||
- fixed_ips
|
||||
- id
|
||||
- ip_allocation
|
||||
- is_admin_state_up
|
||||
- is_port_security_enabled
|
||||
- mac_address
|
||||
- name
|
||||
- network_id
|
||||
- numa_affinity_policy
|
||||
- project_id
|
||||
- propagate_uplink_status
|
||||
- qos_network_policy_id
|
||||
- qos_policy_id
|
||||
- resource_request
|
||||
- revision_number
|
||||
- security_group_ids
|
||||
- status
|
||||
- tags
|
||||
- tenant_id
|
||||
- trunk_details
|
||||
- updated_at
|
||||
network_name: ansible_port_network
|
||||
network_external: true
|
||||
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"
|
||||
port_name: ansible_port
|
||||
subnet_name: ansible_port_subnet
|
||||
|
||||
@@ -1,145 +1,269 @@
|
||||
---
|
||||
- name: Create network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ network_name }}"
|
||||
external: "{{ network_external }}"
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ network_name }}"
|
||||
external: true
|
||||
register: network
|
||||
|
||||
- name: Create subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ subnet_name }}"
|
||||
network_name: "{{ network_name }}"
|
||||
cidr: 10.5.5.0/24
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ subnet_name }}"
|
||||
network_name: "{{ network_name }}"
|
||||
cidr: 10.5.5.0/24
|
||||
register: subnet
|
||||
|
||||
- name: Create port (no security group or default security group)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
no_security_groups: "{{ no_security_groups }}"
|
||||
fixed_ips:
|
||||
- ip_address: 10.5.5.69
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
no_security_groups: "{{ no_security_groups }}"
|
||||
fixed_ips:
|
||||
- ip_address: 10.5.5.69
|
||||
register: port
|
||||
|
||||
- debug: var=port
|
||||
|
||||
- name: assert return values of port module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(port.port.keys())|length == 0
|
||||
|
||||
- name: List all ports
|
||||
openstack.cloud.port_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: info
|
||||
|
||||
- name: Get info about all ports
|
||||
openstack.cloud.port_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: info
|
||||
|
||||
- name: Check info about ports
|
||||
assert:
|
||||
that:
|
||||
- info.ports|length > 0
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(info.ports[0].keys())|length == 0
|
||||
|
||||
- name: Get port by id
|
||||
openstack.cloud.port_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ info.ports[0].id }}"
|
||||
register: info_id
|
||||
|
||||
- name: Assert infos by id
|
||||
assert:
|
||||
that:
|
||||
- info_id.ports|length == 1
|
||||
- info_id.ports[0].id == info.ports[0].id
|
||||
|
||||
- name: List port with device_id filter
|
||||
openstack.cloud.port_info:
|
||||
cloud: "{{ cloud }}"
|
||||
filters:
|
||||
device_id: "{{ info.ports[0].device_id }}"
|
||||
register: info_filter
|
||||
|
||||
- name: Assert port was returned
|
||||
assert:
|
||||
that:
|
||||
- info_filter.ports | length >= 1
|
||||
|
||||
- name: Delete port (no security group or default security group)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ port_name }}"
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ port_name }}"
|
||||
|
||||
- name: Create security group
|
||||
openstack.cloud.security_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ secgroup_name }}"
|
||||
description: Test group
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_security_group
|
||||
description: Test group
|
||||
register: security_group
|
||||
|
||||
- name: Create port (with security group)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
fixed_ips:
|
||||
- ip_address: 10.5.5.69
|
||||
security_groups:
|
||||
- "{{ secgroup_name }}"
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
fixed_ips:
|
||||
- ip_address: 10.5.5.69
|
||||
security_groups:
|
||||
- ansible_security_group
|
||||
register: port
|
||||
|
||||
- debug: var=port
|
||||
|
||||
- name: Delete port (with security group)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ port_name }}"
|
||||
cloud: "{{ cloud }}"
|
||||
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."
|
||||
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 }}"
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ port_name }}"
|
||||
|
||||
- name: Create port (with allowed_address_pairs and extra_dhcp_opts)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
no_security_groups: "{{ no_security_groups }}"
|
||||
allowed_address_pairs:
|
||||
- ip_address: 10.6.7.0/24
|
||||
extra_dhcp_opts:
|
||||
- opt_name: "bootfile-name"
|
||||
opt_value: "testfile.1"
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
no_security_groups: "{{ no_security_groups }}"
|
||||
allowed_address_pairs:
|
||||
- ip_address: 10.6.7.0/24
|
||||
extra_dhcp_opts:
|
||||
- opt_name: "bootfile-name"
|
||||
opt_value: "testfile.1"
|
||||
register: port
|
||||
|
||||
- debug: var=port
|
||||
|
||||
- name: Delete port (with allowed_address_pairs and extra_dhcp_opts)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ port_name }}"
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ port_name }}"
|
||||
|
||||
- name: Create port which will be updated
|
||||
openstack.cloud.port:
|
||||
allowed_address_pairs:
|
||||
- ip_address: 10.6.7.0/24
|
||||
mac_address: "aa:bb:cc:dd:ee:ff"
|
||||
cloud: "{{ cloud }}"
|
||||
description: "What a great port"
|
||||
extra_dhcp_opts:
|
||||
- ip_version: 4
|
||||
opt_name: "bootfile-name"
|
||||
opt_value: "testfile.1"
|
||||
dns_name: "dns-port-name"
|
||||
dns_domain: "example.com."
|
||||
fixed_ips:
|
||||
- ip_address: 10.5.5.69
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
no_security_groups: true
|
||||
state: present
|
||||
register: port
|
||||
|
||||
- name: Create port which will be updated (again)
|
||||
openstack.cloud.port:
|
||||
allowed_address_pairs:
|
||||
- ip_address: 10.6.7.0/24
|
||||
mac_address: "aa:bb:cc:dd:ee:ff"
|
||||
cloud: "{{ cloud }}"
|
||||
description: "What a great port"
|
||||
extra_dhcp_opts:
|
||||
- ip_version: 4
|
||||
opt_name: "bootfile-name"
|
||||
opt_value: "testfile.1"
|
||||
# We have no valid dns name configured
|
||||
#dns_name: "dns-port-name"
|
||||
#dns_domain: "example.com."
|
||||
fixed_ips:
|
||||
- ip_address: 10.5.5.69
|
||||
subnet_id: "{{ subnet.subnet.id }}"
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
no_security_groups: true
|
||||
state: present
|
||||
register: port_again
|
||||
|
||||
- name: Assert port did not change
|
||||
assert:
|
||||
that:
|
||||
- port.port.id == port_again.port.id
|
||||
- port_again is not changed
|
||||
|
||||
- name: Update port
|
||||
openstack.cloud.port:
|
||||
allowed_address_pairs:
|
||||
- ip_address: 11.9.9.0/24
|
||||
mac_address: "aa:aa:aa:bb:bb:bb"
|
||||
cloud: "{{ cloud }}"
|
||||
description: "This port got updated"
|
||||
extra_dhcp_opts:
|
||||
- opt_name: "bootfile-name"
|
||||
opt_value: "testfile.2"
|
||||
# We have no valid dns name configured
|
||||
#dns_name: "dns-port-name-2"
|
||||
#dns_domain: "another.example.com."
|
||||
fixed_ips:
|
||||
- ip_address: 10.5.5.70
|
||||
subnet_id: "{{ subnet.subnet.id }}"
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
security_groups:
|
||||
- ansible_security_group
|
||||
state: present
|
||||
register: port_updated
|
||||
|
||||
- name: Assert updated port
|
||||
assert:
|
||||
that:
|
||||
- port_updated.port.id == port.port.id
|
||||
- port_updated.port.allowed_address_pairs|length == 1
|
||||
- port_updated.port.allowed_address_pairs[0].ip_address == "11.9.9.0/24"
|
||||
- port_updated.port.allowed_address_pairs[0].mac_address == "aa:aa:aa:bb:bb:bb"
|
||||
- port_updated.port.description == "This port got updated"
|
||||
- port_updated.port.extra_dhcp_opts|length == 1
|
||||
- port_updated.port.extra_dhcp_opts[0].opt_value == "testfile.2"
|
||||
# We have no valid dns name configured
|
||||
#- port_updated.port.dns_name == "dns-port-name-2"
|
||||
#- port_updated.port.dns_domain == "another.example.com."
|
||||
- port_updated.port.fixed_ips|length == 1
|
||||
- port_updated.port.fixed_ips[0].ip_address == "10.5.5.70"
|
||||
- port_updated.port.fixed_ips[0].subnet_id == subnet.subnet.id
|
||||
- port_updated.port.security_group_ids|length == 1
|
||||
- port_updated.port.security_group_ids[0] == security_group.security_group.id
|
||||
|
||||
- name: Delete updated port
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ port_name }}"
|
||||
|
||||
- name: Delete security group
|
||||
openstack.cloud.security_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ secgroup_name }}"
|
||||
|
||||
- name: Test port binding config (runs from train release sdk > 0.28)
|
||||
block:
|
||||
- name: Create port (with binding profile)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
binding_profile: "{{ binding_profile }}"
|
||||
register: port
|
||||
|
||||
- name: Assert binding:profile exists in created port
|
||||
assert:
|
||||
that: "port.port['binding_profile']"
|
||||
|
||||
- debug: var=port
|
||||
|
||||
- name: Delete port (with binding profile)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ port_name }}"
|
||||
when: sdk_version is version(0.28, '>')
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_security_group
|
||||
|
||||
- name: Delete subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ subnet_name }}"
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ subnet_name }}"
|
||||
|
||||
- name: Delete network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ network_name }}"
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ network_name }}"
|
||||
|
||||
10
ci/roles/project/defaults/main.yml
Normal file
10
ci/roles/project/defaults/main.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
expected_fields:
|
||||
- description
|
||||
- domain_id
|
||||
- id
|
||||
- is_domain
|
||||
- is_enabled
|
||||
- name
|
||||
- options
|
||||
- parent_id
|
||||
- tags
|
||||
@@ -1,25 +1,178 @@
|
||||
---
|
||||
- name: Create project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: dummy description
|
||||
domain_id: default
|
||||
enabled: True
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: dummy description
|
||||
domain: default
|
||||
is_enabled: True
|
||||
register: project
|
||||
|
||||
- debug: var=project
|
||||
- name: Assert return values of project module
|
||||
assert:
|
||||
that:
|
||||
- project is changed
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(project.project.keys())|length == 0
|
||||
|
||||
- name: Fetch project
|
||||
openstack.cloud.project_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_project
|
||||
register: project
|
||||
|
||||
- name: Assert project
|
||||
assert:
|
||||
that:
|
||||
- project.projects | length == 1
|
||||
- project.projects.0.name == 'ansible_project'
|
||||
- project.projects.0.description == 'dummy description'
|
||||
|
||||
- name: Create project again
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: dummy description
|
||||
domain: default
|
||||
is_enabled: True
|
||||
register: project
|
||||
|
||||
- name: Assert return values of project module
|
||||
assert:
|
||||
that:
|
||||
- project is not changed
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(project.project.keys())|length == 0
|
||||
|
||||
- name: Update project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: new description
|
||||
register: updatedproject
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: new description
|
||||
extra_specs:
|
||||
tags:
|
||||
- example_tag
|
||||
register: project
|
||||
|
||||
- debug: var=updatedproject
|
||||
- name: Assert project changed
|
||||
assert:
|
||||
that:
|
||||
- project is changed
|
||||
- project.project.description == 'new description'
|
||||
|
||||
- name: Fetch all projects
|
||||
openstack.cloud.project_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: projects
|
||||
|
||||
- name: Assert return values of project_info module
|
||||
assert:
|
||||
that:
|
||||
- projects.projects | length > 0
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(projects.projects.0.keys())|length == 0
|
||||
|
||||
- name: Fetch project by name
|
||||
openstack.cloud.project_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: 'ansible_project'
|
||||
register: projects
|
||||
|
||||
- name: Assert return values of project_info module
|
||||
assert:
|
||||
that:
|
||||
- projects.projects | length == 1
|
||||
- projects.projects.0.name == 'ansible_project'
|
||||
|
||||
- name: Fetch projects with filter
|
||||
openstack.cloud.project_info:
|
||||
cloud: "{{ cloud }}"
|
||||
filters:
|
||||
name: 'ansible_project'
|
||||
register: projects
|
||||
|
||||
- name: Assert return values of project_info module
|
||||
assert:
|
||||
that:
|
||||
- projects.projects | length == 1
|
||||
- projects.projects.0.name == 'ansible_project'
|
||||
|
||||
- name: Fetch project by name and domain
|
||||
openstack.cloud.project_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: 'ansible_project'
|
||||
domain: 'default'
|
||||
register: projects
|
||||
|
||||
- name: Assert return values of project_info module
|
||||
assert:
|
||||
that:
|
||||
- projects.projects | length == 1
|
||||
- projects.projects.0.name == 'ansible_project'
|
||||
|
||||
- name: Delete project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_project
|
||||
register: project
|
||||
|
||||
- name: Assert project changed
|
||||
assert:
|
||||
that: project is changed
|
||||
|
||||
- name: Get project
|
||||
openstack.cloud.project_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_project
|
||||
register: project_info
|
||||
|
||||
- name: Assert project deleted
|
||||
assert:
|
||||
that:
|
||||
- project_info.projects | length == 0
|
||||
|
||||
- name: Delete project again
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_project
|
||||
register: project
|
||||
|
||||
- name: Assert project not changed
|
||||
assert:
|
||||
that: project is not changed
|
||||
|
||||
- name: Create project with extra_specs
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
extra_specs:
|
||||
is_enabled: False
|
||||
register: project
|
||||
|
||||
- name: Assert return values of project module
|
||||
assert:
|
||||
that:
|
||||
- project.project.is_enabled == False
|
||||
|
||||
- name: Update project with extra_specs
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
extra_specs:
|
||||
is_enabled: True
|
||||
register: project
|
||||
|
||||
- name: Assert return values of project module
|
||||
assert:
|
||||
that:
|
||||
- project.project.is_enabled == True
|
||||
|
||||
- name: Delete project
|
||||
openstack.cloud.project:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user