mirror of
https://opendev.org/openstack/ansible-collections-openstack.git
synced 2026-03-27 14:03:03 +00:00
Compare commits
260 Commits
stable/1.0
...
2.2.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
323
.zuul.yaml
323
.zuul.yaml
@@ -52,6 +52,14 @@
|
||||
extensions_to_txt:
|
||||
log: true
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
branches: master
|
||||
description: |
|
||||
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
|
||||
@@ -114,277 +122,99 @@
|
||||
- ^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
|
||||
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
|
||||
parent: ansible-collections-openstack-functional-devstack-octavia-base
|
||||
branches: stable/1.0.0
|
||||
branches: master
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
with Octavia plugin enabled, using 0.*.* releases of openstacksdk
|
||||
with Octavia plugin enabled, using latest 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
|
||||
branches: stable/1.0.0
|
||||
branches: master
|
||||
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
|
||||
using latest releases of openstacksdk and latest ansible release
|
||||
vars:
|
||||
tox_constraints_file: '{{ ansible_user_dir }}/{{ zuul.project.src_dir }}/tests/constraints-openstacksdk-0.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 with Ansible 2.9 for checking backward compatibility
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-2.9
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
branches: stable/1.0.0
|
||||
branches: master
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using 0.*.* releases of openstacksdk and stable 2.9 branch of ansible
|
||||
using master of openstacksdk and stable 2.9 branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.9
|
||||
- # Choose parent devstack job from stable/yoga branch instead of non-existing stable/1.0.0 branch
|
||||
name: openstack/devstack
|
||||
override-checkout: stable/yoga
|
||||
- name: openstack/openstacksdk
|
||||
# Yoga has the latest SDK release of the 0.*.* series atm
|
||||
override-checkout: stable/yoga
|
||||
vars:
|
||||
tox_envlist: ansible_2_9
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-2.11
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
branches: stable/1.0.0
|
||||
branches: master
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using 0.*.* releases of openstacksdk and stable 2.12 branch of ansible
|
||||
using master 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 stable/yoga branch instead of non-existing stable/1.0.0 branch
|
||||
name: openstack/devstack
|
||||
override-checkout: stable/yoga
|
||||
- name: openstack/openstacksdk
|
||||
# Yoga has the latest SDK release of the 0.*.* series atm
|
||||
override-checkout: stable/yoga
|
||||
vars:
|
||||
tox_envlist: ansible_2_11
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-2.12
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
branches: stable/1.0.0
|
||||
branches: master
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using 0.*.* releases of openstacksdk and stable 2.12 branch of ansible
|
||||
using master of openstacksdk and stable 2.12 branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.12
|
||||
- # Choose parent devstack job from stable/yoga branch instead of non-existing stable/1.0.0 branch
|
||||
name: openstack/devstack
|
||||
override-checkout: stable/yoga
|
||||
- name: openstack/openstacksdk
|
||||
# Yoga has the latest SDK release of the 0.*.* series atm
|
||||
override-checkout: stable/yoga
|
||||
vars:
|
||||
tox_envlist: ansible_2_12
|
||||
|
||||
# Stable branches tests
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-xena-ansible-2.12
|
||||
# Do not inherit from any parent job which does not run for branch stable/1.0.0 because Zuul would dismiss this job
|
||||
# when collecting parent job variants. For example, when job.branches is set to master in a parent job, then Zuul
|
||||
# will not match that job when it collects job variants.
|
||||
#
|
||||
# Do not inherit from any parent job which sets job.required-projects.override-checkout on openstack/devstack
|
||||
# because Zuul would use that git ref instead of stable branch defined below to checkout projects of parent devstack
|
||||
# jobs when collecting variants for parent jobs.
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
description: |
|
||||
Run openstack collections functional tests against a xena devstack
|
||||
using xena branch of openstacksdk and stable 2.12 branch of ansible
|
||||
branches: stable/1.0.0
|
||||
override-checkout: stable/xena
|
||||
# job.override-checkout will not override job.required-projects.override-checkout in parent jobs
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.12
|
||||
- # Choose parent devstack job from stable/1.0.0 branch instead of non-existing stable/xena branch
|
||||
name: openstack/ansible-collections-openstack
|
||||
override-checkout: stable/1.0.0
|
||||
- # Choose parent devstack job from stable/xena branch
|
||||
name: openstack/devstack
|
||||
override-checkout: stable/xena
|
||||
- name: openstack/designate
|
||||
override-checkout: stable/xena
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/xena
|
||||
vars:
|
||||
tox_envlist: ansible_2_12
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-wallaby-ansible-2.12
|
||||
# Do not inherit from any parent job which does not run for branch stable/1.0.0 because Zuul would dismiss this job
|
||||
# when collecting parent job variants. For example, when job.branches is set to master in a parent job, then Zuul
|
||||
# will not match that job when it collects job variants.
|
||||
#
|
||||
# Do not inherit from any parent job which sets job.required-projects.override-checkout on openstack/devstack
|
||||
# because Zuul would use that git ref instead of stable branch defined below to checkout projects of parent devstack
|
||||
# jobs when collecting variants for parent jobs.
|
||||
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 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
|
||||
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: stable-2.12
|
||||
- # Choose parent devstack job from stable/1.0.0 branch instead of non-existing stable/wallaby branch
|
||||
name: openstack/ansible-collections-openstack
|
||||
override-checkout: stable/1.0.0
|
||||
- # Choose parent devstack job from stable/wallaby branch
|
||||
name: openstack/devstack
|
||||
override-checkout: stable/wallaby
|
||||
- name: openstack/designate
|
||||
override-checkout: stable/wallaby
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/wallaby
|
||||
vars:
|
||||
tox_envlist: ansible_2_12
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-victoria-ansible-2.12
|
||||
# Do not inherit from any parent job which does not run for branch stable/1.0.0 because Zuul would dismiss this job
|
||||
# when collecting parent job variants. For example, when job.branches is set to master in a parent job, then Zuul
|
||||
# will not match that job when it collects job variants.
|
||||
#
|
||||
# Do not inherit from any parent job which sets job.required-projects.override-checkout on openstack/devstack
|
||||
# because Zuul would use that git ref instead of stable branch defined below to checkout projects of parent devstack
|
||||
# jobs when collecting variants for parent jobs.
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
description: |
|
||||
Run openstack collections functional tests against a victoria devstack
|
||||
using victoria branch of openstacksdk and stable 2.12 branch of ansible
|
||||
branches: stable/1.0.0
|
||||
override-checkout: stable/victoria
|
||||
# job.override-checkout will not override job.required-projects.override-checkout in parent jobs
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.12
|
||||
- # Choose parent devstack job from stable/1.0.0 branch instead of non-existing stable/victoria branch
|
||||
name: openstack/ansible-collections-openstack
|
||||
override-checkout: stable/1.0.0
|
||||
- # Choose parent devstack job from stable/victoria branch
|
||||
name: openstack/devstack
|
||||
override-checkout: stable/victoria
|
||||
- name: openstack/designate
|
||||
override-checkout: stable/victoria
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/victoria
|
||||
vars:
|
||||
tox_envlist: ansible_2_12
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ussuri-ansible-2.11
|
||||
# Do not inherit from any parent job which does not run for branch stable/1.0.0 because Zuul would dismiss this job
|
||||
# when collecting parent job variants. For example, when job.branches is set to master in a parent job, then Zuul
|
||||
# will not match that job when it collects job variants.
|
||||
#
|
||||
# Do not inherit from any parent job which sets job.required-projects.override-checkout on openstack/devstack
|
||||
# because Zuul would use that git ref instead of stable branch defined below to checkout projects of parent devstack
|
||||
# jobs when collecting variants for parent jobs.
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
description: |
|
||||
Run openstack collections functional tests against a ussuri devstack
|
||||
using ussuri 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/designate
|
||||
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/designate
|
||||
override-checkout: train-eol
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/train
|
||||
vars:
|
||||
tox_envlist: ansible_2_11
|
||||
override-checkout: devel
|
||||
|
||||
# Linters
|
||||
- job:
|
||||
@@ -432,57 +262,102 @@
|
||||
- job:
|
||||
name: bifrost-collections-src
|
||||
parent: bifrost-integration-tinyipa-ubuntu-focal
|
||||
override-checkout: stable/yoga
|
||||
# job.override-checkout will not override job.required-projects.override-checkout in parent jobs
|
||||
required-projects:
|
||||
- openstack/ansible-collections-openstack
|
||||
- # always use existing branch when collecting parent job variants, refer to git blame for rationale.
|
||||
- # always use master branch when collecting parent job variants, refer to git blame for rationale.
|
||||
name: openstack/bifrost
|
||||
# Yoga has the latest SDK release of the 0.*.* series atm
|
||||
override-checkout: stable/yoga
|
||||
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
|
||||
override-checkout: stable/yoga
|
||||
# job.override-checkout will not override job.required-projects.override-checkout in parent jobs
|
||||
required-projects:
|
||||
- openstack/ansible-collections-openstack
|
||||
- # always use existing branch when collecting parent job variants, refer to git blame for rationale.
|
||||
- # always use master branch when collecting parent job variants, refer to git blame for rationale.
|
||||
name: openstack/bifrost
|
||||
# Yoga has the latest SDK release of the 0.*.* series atm
|
||||
override-checkout: stable/yoga
|
||||
override-checkout: master
|
||||
- # always use master branch when collecting parent job variants
|
||||
name: openstack/openstacksdk
|
||||
override-checkout: master
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-release
|
||||
parent: base
|
||||
run: ci/publish/publish_collection.yml
|
||||
secrets:
|
||||
- ansible_galaxy_info
|
||||
|
||||
- secret:
|
||||
name: ansible_galaxy_info
|
||||
data:
|
||||
url: https://galaxy.ansible.com
|
||||
token: !encrypted/pkcs1-oaep
|
||||
- lZFzfoCbuwqV1k6qRfl/VS7E+knUW7+zpg7BptrenK4n0g7UY0HtdVkYq0pV0Tj/LbhzG
|
||||
jHD0mehcV1iS6B7ORKg4criJkdDfEx09BD8z8yv0EleiIMmhlrCoMcY593OZMBtVbGi0D
|
||||
CwQtNO98QIsfZogChfLfvRNiBmUV98mEb/p6p3EtGx8J7qcAsqfWxc/CzB8GCleLAHHHT
|
||||
FuikMM03ZnV0ew7E+TPkHbzzPhBZOqS5HYF0HtgttHwIXdfIWp/XdTuEEk7uRRgYZ2Iao
|
||||
ifWRzoKaOQmhM++e1ydCqw9D4y9dZEFNMQLwSqcrvtb8cNwT1kl7SCFqYNE2lbutj4ne6
|
||||
PTBQRsKegMB4Y3ena14fNF6tCynvJLPhF/cjPH2Jhs+B19XQhWkL3TgiOY02W24YHwRcP
|
||||
+LdkM8inAvyVi3DEbEqdjBPO9OFJcBOKPlCdkGvuwdNCuEpEwctWs0gV3voflG2CDKzmJ
|
||||
wu9JJOAWnq/0l1WpuDqWreKeQ/BUGZC2Gb4xRAqofulgvhs4WuYoEccjH4EJFIZ90S1EP
|
||||
R/ZLadqZaEhmjwGM5sMWbBbjT23XsRgg0Tzt9m8DENYMuYDqkMdRbt2jYZa+32p4hyxVe
|
||||
Y6H/pqYq5b9uOzumnShaK4WlmkQyXcNPkoSlMC1h4OGvqX/WUixpI38jyMA5Tc=
|
||||
|
||||
- project:
|
||||
check:
|
||||
jobs:
|
||||
- tox-pep8
|
||||
- openstack-tox-linters-ansible-devel
|
||||
- ansible-collections-openstack-functional-devstack-releases:
|
||||
dependencies:
|
||||
- openstack-tox-linters-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack:
|
||||
dependencies: &deps_unit_lint
|
||||
- tox-pep8
|
||||
- openstack-tox-linters-ansible-2.12
|
||||
|
||||
- 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-magnum:
|
||||
dependencies: *deps_unit_lint
|
||||
- ansible-collections-openstack-functional-devstack-octavia:
|
||||
dependencies: *deps_unit_lint
|
||||
|
||||
- bifrost-collections-src:
|
||||
voting: false
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- bifrost-keystone-collections-src:
|
||||
voting: false
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
|
||||
gate:
|
||||
jobs:
|
||||
- tox-pep8
|
||||
- openstack-tox-linters-ansible-2.12
|
||||
# - 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-magnum
|
||||
- ansible-collections-openstack-functional-devstack-octavia
|
||||
|
||||
periodic:
|
||||
jobs:
|
||||
- openstack-tox-linters-ansible-devel
|
||||
- openstack-tox-linters-ansible-2.12
|
||||
- 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-devel
|
||||
- ansible-collections-openstack-functional-devstack-xena-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-wallaby-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-victoria-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-train-ansible-2.11
|
||||
- bifrost-collections-src
|
||||
- bifrost-keystone-collections-src
|
||||
- ansible-collections-openstack-functional-devstack-magnum
|
||||
@@ -491,8 +366,6 @@
|
||||
experimental:
|
||||
jobs:
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-victoria-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-ussuri-ansible-2.11
|
||||
|
||||
tag:
|
||||
jobs:
|
||||
|
||||
227
CHANGELOG.rst
227
CHANGELOG.rst
@@ -1,135 +1,164 @@
|
||||
=============================================
|
||||
Openstack Cloud Ansilbe modules Release Notes
|
||||
=============================================
|
||||
==========================================
|
||||
Ansible OpenStack Collection Release Notes
|
||||
==========================================
|
||||
|
||||
.. contents:: Topics
|
||||
|
||||
|
||||
v1.10.0
|
||||
=======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Enable logging of openstacksdk activities and warn users about incompatible openstacksdk releases when using inventory plugin
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Add SDK logging option for openstack ansible collections
|
||||
- Don't use deprecated distutils from python 3.10
|
||||
- Ensure openstacksdk compatibility in inventory plugin
|
||||
- Lowered maximum OpenStack SDK version to 0.98.999 in inventory plugin
|
||||
|
||||
Known Issues
|
||||
------------
|
||||
|
||||
- For compatibility with OpenStack SDK >= 0.99.0 use Ansible OpenStack collection 2.0.0 or later which is currently under development.
|
||||
- Release series 1.x.x of this collection is compatible to OpenStack SDK prior to 0.99.0 only.
|
||||
|
||||
v1.9.1
|
||||
v2.2.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfix in keypair module
|
||||
New module for volume_type and bugfixes
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add volume_encryption_type modules
|
||||
- Add volume_type modules
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Do not remove trailing spaces when reading public key in keypair module
|
||||
- Fix image module filter
|
||||
- Fix port module idempotency
|
||||
- Fix router module idempotency
|
||||
|
||||
Known Issues
|
||||
------------
|
||||
|
||||
- For compatibility with OpenStack SDK >= 0.99.0 use Ansible OpenStack collection 2.0.0 or later which is currently under development.
|
||||
- Release series 1.x.x of this collection is compatible to OpenStack SDK prior to 0.99.0 only.
|
||||
|
||||
v1.9.0
|
||||
v2.1.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
This release will enforce openstacksdk<0.99.0, has a dozen modules refactored and several bugs fixed.
|
||||
New module for Ironic and bugfixes
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add baremetal_deploy_template module
|
||||
- Highlight our mode of operation more prominently
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Added support for specifying a maximum version of the OpenStack SDK
|
||||
- Constrain filters in compute_service_info to SDK >= 0.53.0
|
||||
- Drop username from return values of identity_user_info
|
||||
- Fix logic in routers_info
|
||||
- Fixed return value disable{d,s}_reason in compute_service_info module
|
||||
- Fixed return values in compute_service_info module again
|
||||
- Follow up to bump of minimum required OpenStack SDK release to SDK 0.36.0 (Train)
|
||||
- Lowered maximum OpenStack SDK version to 0.98.999
|
||||
- Move dns zone info to use proxy layer
|
||||
- Refactored catalog_service module
|
||||
- Refactored endpoint module
|
||||
- Refactored host_aggregate module
|
||||
- Refactored identity_domain_info module
|
||||
- Refactored identity_group_info module
|
||||
- Refactored identity_role module
|
||||
- Refactored identity_role_info module
|
||||
- Refactored identity_user module
|
||||
- Refactored identity_user_info module
|
||||
- Refactored image_info module
|
||||
- Refactored keypair_info module
|
||||
- Refactored recordset module
|
||||
- Refactored role_assignment module
|
||||
- Set owner in image module
|
||||
- Support description in sg-rule creation
|
||||
- Warn users about us breaking backward compatibility
|
||||
- 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
|
||||
|
||||
Known Issues
|
||||
------------
|
||||
|
||||
- For compatibility with OpenStack SDK >= 0.99.0 use Ansible OpenStack collection 2.0.0 or later which is currently under development.
|
||||
- Release series 1.x.x of this collection is compatible to OpenStack SDK prior to 0.99.0 only.
|
||||
|
||||
v1.8.0
|
||||
v2.0.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Subnet pool module and bugfixes
|
||||
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
|
||||
--------
|
||||
|
||||
- Add 'all_projects' to server_action module
|
||||
- Add subnet pool module
|
||||
- Bumped minimum required OpenStack SDK release to SDK 0.36.0 (Train)
|
||||
- Changed compute_flavor_info module to use OpenStack SDK's proxy layer
|
||||
- Dropped deprecated return values in floating_ip_info and assert remaining fields
|
||||
- Fix ansible-lint issues for the newest version
|
||||
- Fix assertion after stack deletion
|
||||
- Handle aggregate host list set to None
|
||||
- Reenabled check-import.sh which tests imports to Ansible Galaxy
|
||||
- Remove old, unsupported parameters from documentation in image_info module
|
||||
- Router - Remove unneeded 'filter' parameter
|
||||
- Updated return value docs of compute_service_info module
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.subnet_pool - Create or Delete subnet pools from OpenStack.
|
||||
|
||||
v1.7.2
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfixes
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Fix collection guidelines
|
||||
- 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
|
||||
======
|
||||
|
||||
90
README.md
90
README.md
@@ -6,6 +6,12 @@ http://zuul.opendev.org/t/openstack/builds?project=openstack%2Fansible-collectio
|
||||
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.
|
||||
|
||||
**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!
|
||||
|
||||
## Branches and Non Backward Compatibility ⚠️
|
||||
|
||||
Our codebase has been split into two separate release series, `2.x.x` and `1.x.x`:
|
||||
@@ -29,7 +35,7 @@ For using this collection, first you have to install both Python packages `ansib
|
||||
controller:
|
||||
|
||||
```sh
|
||||
pip install "ansible>=2.9" "openstacksdk>=0.36,<0.99.0"
|
||||
pip install "ansible>=2.9" "openstacksdk>=1.0.0"
|
||||
```
|
||||
|
||||
[OpenStack SDK][openstacksdk] has to be available on the Ansible host running the OpenStack modules. Depending on the
|
||||
@@ -64,15 +70,15 @@ ansible-galaxy collection install -r requirements.yml
|
||||
|
||||
## Usage
|
||||
|
||||
To use a module from the OpenStack Cloud collection, please reference the full namespace, collection name, and module
|
||||
name that you want to use:
|
||||
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
|
||||
@@ -87,12 +93,12 @@ Or you can add the full namespace and collection name in the `collections` eleme
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Using the Ansible OpenStack 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
|
||||
@@ -100,6 +106,68 @@ Or you can add the full namespace and collection name in the `collections` eleme
|
||||
device: /dev/vdb
|
||||
```
|
||||
|
||||
For powerful generic [CRUD][crud]-style resource management use Ansible module
|
||||
[`openstack.cloud.resource`](plugins/modules/resource.py):
|
||||
|
||||
```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'
|
||||
|
||||
- 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'
|
||||
|
||||
- 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
|
||||
@@ -124,6 +192,7 @@ Or you can add the full namespace and collection name in the `collections` eleme
|
||||
```
|
||||
|
||||
[ansible-module-defaults]: https://docs.ansible.com/ansible/latest/user_guide/playbooks_module_defaults.html
|
||||
[crud]: https://en.wikipedia.org/wiki/CRUD
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -153,8 +222,7 @@ docs/reviewing.md) (⚠️) before sending your first patch. Pull requests submi
|
||||
## Communication
|
||||
|
||||
We have a Special Interest Group for the Ansible OpenStack collection. Join us in `#openstack-ansible-sig` on
|
||||
[OFTC IRC](https://www.oftc.net/) and ping Artem Goncharov <artem.goncharov@gmail.com> (gtema), Jakob Meng
|
||||
<mail@jakobmeng.de> (jm1) or Sagi Shnaidman <sshnaidm@redhat.com> (sshnaidm) 🍪
|
||||
[OFTC IRC](https://www.oftc.net/) 🍪
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -70,21 +70,6 @@ releases:
|
||||
name: volume_info
|
||||
namespace: ''
|
||||
release_date: '2020-08-17'
|
||||
1.10.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Add SDK logging option for openstack ansible collections
|
||||
- Don't use deprecated distutils from python 3.10
|
||||
- Ensure openstacksdk compatibility in inventory plugin
|
||||
- Lowered maximum OpenStack SDK version to 0.98.999 in inventory plugin
|
||||
known_issues:
|
||||
- For compatibility with OpenStack SDK >= 0.99.0 use Ansible OpenStack collection
|
||||
2.0.0 or later which is currently under development.
|
||||
- Release series 1.x.x of this collection is compatible to OpenStack SDK prior
|
||||
to 0.99.0 only.
|
||||
release_summary: Enable logging of openstacksdk activities and warn users about
|
||||
incompatible openstacksdk releases when using inventory plugin
|
||||
release_date: '2022-10-04'
|
||||
1.2.0:
|
||||
changes:
|
||||
minor_changes:
|
||||
@@ -328,79 +313,216 @@ 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
|
||||
modules:
|
||||
- description: Create or Delete subnet pools from OpenStack.
|
||||
name: subnet_pool
|
||||
namespace: ''
|
||||
release_date: '2022-04-08'
|
||||
1.9.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Added support for specifying a maximum version of the OpenStack SDK
|
||||
- Constrain filters in compute_service_info to SDK >= 0.53.0
|
||||
- Drop username from return values of identity_user_info
|
||||
- Fix logic in routers_info
|
||||
- Fixed return value disable{d,s}_reason in compute_service_info module
|
||||
- Fixed return values in compute_service_info module again
|
||||
- Follow up to bump of minimum required OpenStack SDK release to SDK 0.36.0
|
||||
(Train)
|
||||
- Lowered maximum OpenStack SDK version to 0.98.999
|
||||
- Move dns zone info to use proxy layer
|
||||
- Refactored catalog_service module
|
||||
- Refactored endpoint module
|
||||
- Refactored host_aggregate module
|
||||
- Refactored identity_domain_info module
|
||||
- Refactored identity_group_info module
|
||||
- Refactored identity_role module
|
||||
- Refactored identity_role_info module
|
||||
- Refactored identity_user module
|
||||
- Refactored identity_user_info module
|
||||
- Refactored image_info module
|
||||
- Refactored keypair_info module
|
||||
- Refactored recordset module
|
||||
- Refactored role_assignment module
|
||||
- Set owner in image module
|
||||
- Support description in sg-rule creation
|
||||
- Warn users about us breaking backward compatibility
|
||||
known_issues:
|
||||
- For compatibility with OpenStack SDK >= 0.99.0 use Ansible OpenStack collection
|
||||
2.0.0 or later which is currently under development.
|
||||
- Release series 1.x.x of this collection is compatible to OpenStack SDK prior
|
||||
to 0.99.0 only.
|
||||
release_summary: This release will enforce openstacksdk<0.99.0, has a dozen
|
||||
modules refactored and several bugs fixed.
|
||||
release_date: '2022-08-25'
|
||||
1.9.1:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Do not remove trailing spaces when reading public key in keypair module
|
||||
known_issues:
|
||||
- For compatibility with OpenStack SDK >= 0.99.0 use Ansible OpenStack collection
|
||||
2.0.0 or later which is currently under development.
|
||||
- Release series 1.x.x of this collection is compatible to OpenStack SDK prior
|
||||
to 0.99.0 only.
|
||||
release_summary: Bugfix in keypair module
|
||||
release_date: '2022-09-08'
|
||||
- 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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -2,4 +2,7 @@
|
||||
collections:
|
||||
- ansible.posix
|
||||
- ansible.utils
|
||||
- community.general
|
||||
- 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
|
||||
|
||||
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
|
||||
@@ -23,15 +23,8 @@
|
||||
|
||||
- name: Verify returned values
|
||||
assert:
|
||||
that:
|
||||
- item in service_test.service
|
||||
loop:
|
||||
- description
|
||||
- id
|
||||
- enabled
|
||||
- name
|
||||
- service_type
|
||||
- type
|
||||
that: item in service_test.service
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- name: Check if the service test was created successfully
|
||||
openstack.cloud.catalog_service:
|
||||
@@ -42,15 +35,8 @@
|
||||
|
||||
- name: Verify returned values
|
||||
assert:
|
||||
that:
|
||||
- item in service_created.service
|
||||
loop:
|
||||
- description
|
||||
- id
|
||||
- enabled
|
||||
- name
|
||||
- type
|
||||
- service_type
|
||||
that: item in service_created.service
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- name: Update service test
|
||||
openstack.cloud.catalog_service:
|
||||
@@ -61,11 +47,34 @@
|
||||
name: test
|
||||
register: service_test
|
||||
|
||||
- name: Check if description and enabled were updated
|
||||
- name: Check if description and is_enabled were updated
|
||||
assert:
|
||||
that:
|
||||
- service_test.service.description == "A new description"
|
||||
- not (service_test.service.enabled|bool)
|
||||
- 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:
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
- name: List all profiles
|
||||
openstack.cloud.config:
|
||||
register: list
|
||||
|
||||
# WARNING: This will output sensitive authentication information!!!!
|
||||
- debug: var=list
|
||||
@@ -1,18 +1,26 @@
|
||||
expected_fields:
|
||||
# Magnum might return more fields according to its documentation [0] but
|
||||
# openstacksdk normalizes coe cluster resources, moving most fields from
|
||||
# top level into a 'properties' field [1].
|
||||
# [0] https://docs.openstack.org/api-ref/container-infrastructure-management/#create-new-cluster
|
||||
# [1] https://opendev.org/openstack/openstacksdk/src/commit/d57c1fcab3b6cbe806cbae735fefa4983b200ab2/openstack/cloud/_normalize.py#L484
|
||||
- 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
|
||||
- location
|
||||
- labels
|
||||
- master_addresses
|
||||
- master_count
|
||||
- master_flavor_id
|
||||
- name
|
||||
- node_addresses
|
||||
- node_count
|
||||
- properties
|
||||
- stack_id
|
||||
- status
|
||||
- status_reason
|
||||
- updated_at
|
||||
- uuid
|
||||
|
||||
@@ -69,8 +69,8 @@
|
||||
external_network_id: '{{ external_network.network.id }}'
|
||||
fixed_network: ansible_internal_network
|
||||
fixed_subnet: ansible_internal_subnet
|
||||
floating_ip_enabled: true
|
||||
image_id: '{{ image_id }}'
|
||||
is_floating_ip_enabled: true
|
||||
keypair_id: '{{ keypair.keypair.id }}'
|
||||
name: k8s
|
||||
state: present
|
||||
@@ -90,8 +90,8 @@
|
||||
- name: Assert return values of coe_cluster module
|
||||
assert:
|
||||
that:
|
||||
# openstack.cloud.coe_cluster will only return 'id' on cluster creation when wait is false
|
||||
- "['id']|difference(coe_cluster.cluster.keys())|length == 0"
|
||||
# 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:
|
||||
|
||||
@@ -1,40 +1,33 @@
|
||||
expected_fields:
|
||||
# Magnum might return more fields according to its documentation [0] but
|
||||
# openstacksdk normalizes coe cluster template resources, moving most
|
||||
# fields from top level into a 'properties' field [1].
|
||||
# [0] https://docs.openstack.org/api-ref/container-infrastructure-management/#create-new-cluster
|
||||
# [1] https://opendev.org/openstack/openstacksdk/src/commit/d57c1fcab3b6cbe806cbae735fefa4983b200ab2/openstack/cloud/_normalize.py#L522
|
||||
- apiserver_port
|
||||
- cluster_distro
|
||||
- coe
|
||||
- created_at
|
||||
- dns_nameserver
|
||||
- docker_storage_driver
|
||||
- docker_volume_size
|
||||
- external_network_id
|
||||
- fixed_network
|
||||
- fixed_subnet
|
||||
- flavor_id
|
||||
- floating_ip_enabled
|
||||
- http_proxy
|
||||
- https_proxy
|
||||
- id
|
||||
- image_id
|
||||
- insecure_registry
|
||||
- is_floating_ip_enabled
|
||||
- is_hidden
|
||||
- is_master_lb_enabled
|
||||
- is_public
|
||||
- is_registry_enabled
|
||||
- is_tls_disabled
|
||||
- keypair_id
|
||||
- labels
|
||||
- location
|
||||
- master_flavor_id
|
||||
- name
|
||||
- network_driver
|
||||
- no_proxy
|
||||
- properties
|
||||
- public
|
||||
- registry_enabled
|
||||
- server_type
|
||||
- tls_disabled
|
||||
- updated_at
|
||||
- uuid
|
||||
- volume_driver
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
openstack.cloud.coe_cluster_template:
|
||||
cloud: "{{ cloud }}"
|
||||
coe: kubernetes
|
||||
floating_ip_enabled: false
|
||||
is_floating_ip_enabled: false
|
||||
image_id: '{{ image_id }}'
|
||||
keypair_id: '{{ keypair.keypair.id }}'
|
||||
name: k8s
|
||||
@@ -38,7 +38,7 @@
|
||||
openstack.cloud.coe_cluster_template:
|
||||
cloud: "{{ cloud }}"
|
||||
coe: kubernetes
|
||||
floating_ip_enabled: false
|
||||
is_floating_ip_enabled: false
|
||||
image_id: '{{ image_id }}'
|
||||
keypair_id: '{{ keypair.keypair.id }}'
|
||||
name: k8s
|
||||
|
||||
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: Check output of list flavors with filter
|
||||
assert:
|
||||
that:
|
||||
- flavor.openstack_flavors | length == 1
|
||||
|
||||
- name: Assert fields on SDK 0.*
|
||||
when: sdk_version is version(1.0, '<')
|
||||
assert:
|
||||
that:
|
||||
- '["name", "description", "disk", "is_public", "ram",
|
||||
"vcpus", "swap", "ephemeral", "is_disabled", "rxtx_factor", "id",
|
||||
"extra_specs"] | difference(flavor.openstack_flavors.0.keys())
|
||||
| length == 0'
|
||||
|
||||
- name: Assert fields on SDK 1.*
|
||||
when: sdk_version is version(1.0, '>=')
|
||||
assert:
|
||||
that:
|
||||
- '["name", "original_name", "description", "disk", "is_public", "ram",
|
||||
"vcpus", "swap", "ephemeral", "is_disabled", "rxtx_factor", "id",
|
||||
"extra_specs"] | difference(flavor.openstack_flavors.0.keys())
|
||||
| length == 0'
|
||||
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,32 +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: 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,49 +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: Assert keys exist
|
||||
assert:
|
||||
that:
|
||||
- '["action", "attributes", "created_at", "description", "email",
|
||||
"links", "masters", "name", "pool_id", "project_id", "serial",
|
||||
"status", "ttl", "type", "updated_at", "id"] |
|
||||
difference(zone.zones.0.keys()) | length == 0'
|
||||
|
||||
- name: Drop created dns zone
|
||||
openstack.cloud.dns_zone:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ (prefix + '.test.zone.') }}"
|
||||
state: absent
|
||||
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
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
- name: Create a service for compute
|
||||
- name: Create a service endpoint for compute
|
||||
openstack.cloud.endpoint:
|
||||
cloud: "{{ cloud }}"
|
||||
service: nova
|
||||
@@ -9,17 +9,20 @@
|
||||
state: present
|
||||
register: endpoint_test
|
||||
|
||||
- name: Ensure service was created
|
||||
- debug: var=endpoint_test
|
||||
|
||||
- name: Assert return values of endpoint module
|
||||
assert:
|
||||
that:
|
||||
- endpoint_test.endpoint.id is defined
|
||||
# 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 for compute again
|
||||
- name: Create service endpoint for compute again
|
||||
openstack.cloud.endpoint:
|
||||
cloud: "{{ cloud }}"
|
||||
service: nova
|
||||
@@ -34,7 +37,7 @@
|
||||
that:
|
||||
- not endpoint_again.changed
|
||||
|
||||
- name: Update endpoint url
|
||||
- name: Update service endpoint url
|
||||
openstack.cloud.endpoint:
|
||||
cloud: "{{ cloud }}"
|
||||
service: nova
|
||||
@@ -44,12 +47,12 @@
|
||||
state: present
|
||||
register: endpoint_updated
|
||||
|
||||
- name: Ensure endpoint was updated
|
||||
- name: Ensure service endpoint was updated
|
||||
assert:
|
||||
that:
|
||||
- endpoint_updated.endpoint.url == "http://controller:9393"
|
||||
|
||||
- name: Delete endpoint
|
||||
- name: Delete service endpoint
|
||||
openstack.cloud.endpoint:
|
||||
cloud: "{{ cloud }}"
|
||||
service: nova
|
||||
@@ -59,7 +62,7 @@
|
||||
state: absent
|
||||
register: endpoint_deleted
|
||||
|
||||
- name: Ensure endpoint was 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,4 @@
|
||||
---
|
||||
# Prepare environment
|
||||
- name: List all images
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
@@ -7,7 +6,7 @@
|
||||
|
||||
- name: Identify CirrOS image name
|
||||
set_fact:
|
||||
image_name: "{{ images.openstack_images|community.general.json_query(query)|first }}"
|
||||
image_name: "{{ images.images|community.general.json_query(query)|first }}"
|
||||
vars:
|
||||
query: "[?starts_with(name, 'cirros')].name"
|
||||
|
||||
@@ -19,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
|
||||
@@ -149,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_name }}"
|
||||
flavor: m1.tiny
|
||||
nics:
|
||||
# one nic only else simple, first floating ip test does not work
|
||||
- port-name: ansible_internal_port1
|
||||
auto_ip: false
|
||||
wait: true
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: ansible_server1
|
||||
register: info
|
||||
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_name }}"
|
||||
flavor: m1.tiny
|
||||
nics:
|
||||
- port-name: ansible_internal_port2
|
||||
- port-name: ansible_internal_port3
|
||||
auto_ip: false
|
||||
wait: true
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: ansible_server2
|
||||
register: info
|
||||
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
|
||||
@@ -382,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
|
||||
@@ -392,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
|
||||
@@ -407,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
|
||||
@@ -1,10 +1,11 @@
|
||||
# Parameter deleted has been renamed to is_deleted in openstacksdk 0.52.0,
|
||||
# hence we cannot test with this list here.
|
||||
# Ref.: https://github.com/openstack/openstacksdk/commit/b60915aab3ee0348f3e3cc8aa548f94d2a68b7eb
|
||||
expected_fields:
|
||||
- availability_zone
|
||||
- created_at
|
||||
- deleted_at
|
||||
- hosts
|
||||
- id
|
||||
- location
|
||||
- is_deleted
|
||||
- metadata
|
||||
- name
|
||||
- updated_at
|
||||
- uuid
|
||||
|
||||
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
|
||||
@@ -1,8 +0,0 @@
|
||||
domain_name: domain_info_test_domain
|
||||
unexistent_domain_name: domain_info_unexistent_domain
|
||||
disabled_domain_name: test_domain_disabled
|
||||
domain_info_fields:
|
||||
- description
|
||||
- id
|
||||
- enabled
|
||||
- name
|
||||
@@ -1,72 +0,0 @@
|
||||
---
|
||||
- block:
|
||||
- name: Ensure domain does not exist
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ unexistent_domain_name }}"
|
||||
- name: Get unexistent domain
|
||||
openstack.cloud.identity_domain_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ unexistent_domain_name }}"
|
||||
register: domain_info
|
||||
- name: Assert no results returned
|
||||
assert:
|
||||
that: not domain_info.openstack_domains
|
||||
|
||||
|
||||
- block:
|
||||
- name: Ensure domain exists
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ domain_name }}"
|
||||
description: "test description"
|
||||
register: domain
|
||||
- name: Get domain
|
||||
openstack.cloud.identity_domain_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ domain_name }}"
|
||||
register: domain_info
|
||||
- name: Assert one result exists
|
||||
assert:
|
||||
that: domain_info.openstack_domains | length == 1
|
||||
- name: Assert fields are present
|
||||
assert:
|
||||
that: item in domain_info.openstack_domains[0]
|
||||
loop: "{{ domain_info_fields }}"
|
||||
- name: Assert returned value
|
||||
assert:
|
||||
that:
|
||||
- domain_info.openstack_domains[0].description == domain.domain.description
|
||||
|
||||
- block:
|
||||
- name: Get all domains
|
||||
openstack.cloud.identity_domain_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: domain_info
|
||||
|
||||
- block:
|
||||
- name: Ensure disabled domain exists
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ disabled_domain_name }}"
|
||||
enabled: false
|
||||
description: "test description"
|
||||
register: domain
|
||||
- name: Get filtered domains
|
||||
openstack.cloud.identity_domain_info:
|
||||
cloud: "{{ cloud }}"
|
||||
filters:
|
||||
enabled: true
|
||||
register: domain_info
|
||||
- name: Assert at least one result
|
||||
assert:
|
||||
that: domain_info.openstack_domains | length >= 1
|
||||
- name: Assert returned value
|
||||
assert:
|
||||
that: item.enabled == true
|
||||
loop: "{{ domain_info.openstack_domains }}"
|
||||
|
||||
|
||||
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
|
||||
@@ -1,74 +0,0 @@
|
||||
---
|
||||
- name: List group by domain_id
|
||||
openstack.cloud.identity_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
domain: default
|
||||
register: group_domain
|
||||
|
||||
- name: Assert groups were returned
|
||||
assert:
|
||||
that:
|
||||
- group_domain.openstack_groups | length > 0
|
||||
- group_domain.openstack_groups[0].domain_id == 'default'
|
||||
- group_domain.openstack_groups[0].id is defined
|
||||
- group_domain.openstack_groups[0].description is defined
|
||||
- group_domain.openstack_groups[0].name is defined
|
||||
|
||||
- name: List group by domain_id and group
|
||||
openstack.cloud.identity_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
domain: default
|
||||
name: admins
|
||||
register: groups_info
|
||||
|
||||
- name: Assert groups by domain_id and grouph returned
|
||||
assert:
|
||||
that:
|
||||
- groups_info.openstack_groups | length > 0
|
||||
- groups_info.openstack_groups[0].domain_id == 'default'
|
||||
- groups_info.openstack_groups[0].id is defined
|
||||
- groups_info.openstack_groups[0].description is defined
|
||||
- groups_info.openstack_groups[0].name is defined
|
||||
|
||||
- name: List group by filter
|
||||
openstack.cloud.identity_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
domain: default
|
||||
filters:
|
||||
name: admins
|
||||
register: groups_filter
|
||||
|
||||
- name: Assert group by filter returned
|
||||
assert:
|
||||
that:
|
||||
- groups_filter.openstack_groups | length > 0
|
||||
- groups_filter.openstack_groups[0].domain_id == 'default'
|
||||
- groups_filter.openstack_groups[0].id is defined
|
||||
- groups_filter.openstack_groups[0].description is defined
|
||||
- groups_filter.openstack_groups[0].name is defined
|
||||
|
||||
- name: Verify returned values of group info
|
||||
assert:
|
||||
that:
|
||||
- item in groups_info.openstack_groups[0]
|
||||
loop:
|
||||
- description
|
||||
- domain_id
|
||||
- id
|
||||
- name
|
||||
|
||||
- name: List group by group name
|
||||
openstack.cloud.identity_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: admins
|
||||
register: groups_name
|
||||
|
||||
- name: Assert group by name returned
|
||||
assert:
|
||||
that:
|
||||
- groups_name.openstack_groups | length > 0
|
||||
- groups_name.openstack_groups[0].domain_id == 'default'
|
||||
- groups_name.openstack_groups[0].id is defined
|
||||
- groups_name.openstack_groups[0].description is defined
|
||||
- groups_name.openstack_groups[0].name is defined
|
||||
- groups_name.openstack_groups[0].name == 'admins'
|
||||
@@ -1,5 +1,6 @@
|
||||
role_name: ansible_keystone_role
|
||||
expected_fields:
|
||||
- description
|
||||
- domain_id
|
||||
- id
|
||||
- links
|
||||
- name
|
||||
|
||||
@@ -1,83 +1,88 @@
|
||||
---
|
||||
- name: Cleanup before tests
|
||||
block:
|
||||
- openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ role_name }}"
|
||||
- name: Create identity role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_role
|
||||
description: "ansible role"
|
||||
register: role
|
||||
|
||||
- block:
|
||||
- name: Delete unexistent role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ role_name }}"
|
||||
register: role
|
||||
- name: Assert role didn't change
|
||||
assert:
|
||||
that: role is not changed
|
||||
- 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
|
||||
|
||||
- block:
|
||||
- name: Create keystone role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ role_name }}"
|
||||
register: role
|
||||
- name: Try to get role
|
||||
openstack.cloud.identity_role_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ role_name }}"
|
||||
register: roles
|
||||
- name: Assert role found
|
||||
assert:
|
||||
that:
|
||||
- roles.openstack_roles | length == 1
|
||||
- name: Assert role changed
|
||||
assert:
|
||||
that: role is changed
|
||||
- name: Assert return fields
|
||||
assert:
|
||||
that: item in role['role']
|
||||
loop: "{{ expected_fields }}"
|
||||
- name: Assert return value
|
||||
assert:
|
||||
that: role['role']['name'] == role_name
|
||||
- name: Assert retrieved values
|
||||
assert:
|
||||
that: roles.openstack_roles[0].name == role_name
|
||||
- name: Try to get role
|
||||
openstack.cloud.identity_role_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_role
|
||||
register: roles
|
||||
|
||||
- block:
|
||||
- name: Create existing keystone role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ role_name }}"
|
||||
register: role
|
||||
- name: Assert role not changed
|
||||
assert:
|
||||
that: role is not changed
|
||||
- name: Assert return fields
|
||||
assert:
|
||||
that: item in role['role']
|
||||
loop: "{{ expected_fields }}"
|
||||
- name: Assert role found
|
||||
assert:
|
||||
that:
|
||||
- roles.roles | length == 1
|
||||
- roles.roles.0.name == 'ansible_role'
|
||||
|
||||
- block:
|
||||
- name: Delete keystone role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ role_name }}"
|
||||
register: role
|
||||
- name: Assert role changed
|
||||
assert:
|
||||
that: role is changed
|
||||
- name: Try to get role
|
||||
openstack.cloud.identity_role_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ role_name }}"
|
||||
register: roles
|
||||
- name: Assert no role found
|
||||
assert:
|
||||
that:
|
||||
- roles.openstack_roles | length == 0
|
||||
- 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
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
- name: Ensure role does not exist before tests
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: test_role
|
||||
|
||||
- name: Get unexistent role
|
||||
openstack.cloud.identity_role_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: test_role
|
||||
register: roleinfo
|
||||
|
||||
- debug:
|
||||
var: roleinfo
|
||||
|
||||
- name: Assert that no results were returned
|
||||
assert:
|
||||
that: not roleinfo.openstack_roles
|
||||
|
||||
- name: Create keystone role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: test_role
|
||||
|
||||
- name: Create second role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: test_role2
|
||||
|
||||
- name: Get role by name
|
||||
openstack.cloud.identity_role_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: test_role
|
||||
register: roleinfo
|
||||
|
||||
- debug:
|
||||
var: roleinfo
|
||||
|
||||
- name: Assert that only one result was returned
|
||||
assert:
|
||||
that: roleinfo.openstack_roles | length == 1
|
||||
|
||||
- name: Assert that roleinfo has fields
|
||||
assert:
|
||||
that: item in roleinfo.openstack_roles[0]
|
||||
loop:
|
||||
- domain_id
|
||||
- id
|
||||
- name
|
||||
|
||||
- name: Post-test cleanup
|
||||
block:
|
||||
- name: Clean up roles
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ item }}"
|
||||
loop:
|
||||
- test_role
|
||||
- test_role2
|
||||
@@ -1,9 +1,11 @@
|
||||
os_identity_user_fields:
|
||||
expected_fields:
|
||||
- default_project_id
|
||||
- description
|
||||
- domain_id
|
||||
- email
|
||||
- enabled
|
||||
- id
|
||||
- is_enabled
|
||||
- links
|
||||
- name
|
||||
- username
|
||||
- password
|
||||
- password_expires_at
|
||||
|
||||
@@ -1,197 +1,218 @@
|
||||
---
|
||||
- name: setup
|
||||
block:
|
||||
- name: Delete user before running tests
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ item }}"
|
||||
loop:
|
||||
- ansible_user
|
||||
- ansible_user2
|
||||
register: user
|
||||
- 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
|
||||
|
||||
- block:
|
||||
- name: Delete unexistent user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_user
|
||||
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: Ensure user was not changed
|
||||
assert:
|
||||
that: user is not changed
|
||||
- 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
|
||||
|
||||
- block:
|
||||
- name: Create a user without a password
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
email: ansible.user@nowhere.net
|
||||
domain: default
|
||||
default_project: demo
|
||||
register: user
|
||||
- name: Assert that update failed
|
||||
assert:
|
||||
that:
|
||||
- user is failed
|
||||
- user.msg == "update_password is 'always' but password is missing"
|
||||
|
||||
- name: Ensure user was changed
|
||||
assert:
|
||||
that: user is changed
|
||||
- name: Delete user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_user
|
||||
|
||||
- name: Ensure user has fields
|
||||
assert:
|
||||
that: item in user['user']
|
||||
loop: "{{ os_identity_user_fields }}"
|
||||
|
||||
- name: Fail when update_password is always but no password specified
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
update_password: always
|
||||
email: ansible.user@nowhere.net
|
||||
domain: default
|
||||
default_project: demo
|
||||
register: user
|
||||
ignore_errors: yes
|
||||
- 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
|
||||
|
||||
- assert:
|
||||
that: user.msg == "update_password is always but a password value is missing"
|
||||
- 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: Delete user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_user
|
||||
- name: Assert user was not changed
|
||||
assert:
|
||||
that:
|
||||
- user is not changed
|
||||
|
||||
- block:
|
||||
- name: Create user with a password
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
password: secret
|
||||
email: ansible.user@nowhere.net
|
||||
update_password: on_create
|
||||
domain: default
|
||||
default_project: demo
|
||||
register: user
|
||||
- name: 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: Assert user has fields
|
||||
assert:
|
||||
that: item in user['user']
|
||||
loop: "{{ os_identity_user_fields }}"
|
||||
|
||||
- block:
|
||||
- name: Create identical user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
password: secret
|
||||
email: ansible.user@nowhere.net
|
||||
update_password: on_create
|
||||
domain: default
|
||||
default_project: demo
|
||||
register: user
|
||||
|
||||
- name: Assert user was not changed
|
||||
assert:
|
||||
that: user is not changed
|
||||
|
||||
- name: Assert user has fields
|
||||
assert:
|
||||
that: item in user['user']
|
||||
loop: "{{ os_identity_user_fields }}"
|
||||
|
||||
- block:
|
||||
- name: Update user with password
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
password: secret2
|
||||
email: updated.ansible.user@nowhere.net
|
||||
register: user
|
||||
|
||||
- name: Ensure user was changed
|
||||
assert:
|
||||
that: user is changed
|
||||
|
||||
- name: Ensure user has fields
|
||||
assert:
|
||||
that: item in user['user']
|
||||
loop: "{{ os_identity_user_fields }}"
|
||||
- name: Ensure user was changed
|
||||
assert:
|
||||
that:
|
||||
- user is changed
|
||||
|
||||
- name: Update user without password and update_password set to always
|
||||
block:
|
||||
- openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
update_password: always
|
||||
email: updated.ansible.user@nowhere.net
|
||||
register: user
|
||||
ignore_errors: yes
|
||||
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
|
||||
|
||||
- assert:
|
||||
that: user.msg == "update_password is always but a password value is missing"
|
||||
- name: Assert user update failed
|
||||
assert:
|
||||
that:
|
||||
- user is failed
|
||||
- user.msg == "update_password is 'always' but password is missing"
|
||||
|
||||
- block:
|
||||
- name: Ensure user with update_password set to on_create
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
update_password: on_create
|
||||
password: secret3
|
||||
email: updated.ansible.user@nowhere.net
|
||||
register: user
|
||||
- name: Ensure user 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 was not changed
|
||||
assert:
|
||||
that:
|
||||
- user is not changed
|
||||
|
||||
- block:
|
||||
- name: Ensure user with update_password set to always
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
update_password: always
|
||||
password: secret3
|
||||
email: updated.ansible.user@nowhere.net
|
||||
register: user
|
||||
- name: Ensure user 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: Ensure user was changed
|
||||
assert:
|
||||
that:
|
||||
- user is changed
|
||||
|
||||
- block:
|
||||
- name: Create user without a password
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user2
|
||||
password: secret
|
||||
email: ansible.user2@nowhere.net
|
||||
update_password: on_create
|
||||
domain: default
|
||||
default_project: demo
|
||||
register: user
|
||||
- name: Create user without a password
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user2
|
||||
password: secret
|
||||
email: ansible.user2@nowhere.net
|
||||
update_password: on_create
|
||||
domain: default
|
||||
default_project: demo
|
||||
register: user
|
||||
|
||||
- name: Assert user has fields
|
||||
assert:
|
||||
that: item in user['user']
|
||||
loop: "{{ os_identity_user_fields }}"
|
||||
- name: Fetch users
|
||||
openstack.cloud.identity_user_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: users
|
||||
|
||||
- block:
|
||||
- name: Delete user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_user
|
||||
- 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: Ensure user was changed
|
||||
assert:
|
||||
that: user is changed
|
||||
- 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,9 +0,0 @@
|
||||
os_expected_user_info_fields:
|
||||
- default_project_id
|
||||
- description
|
||||
- domain_id
|
||||
- email
|
||||
- enabled
|
||||
- id
|
||||
- name
|
||||
- username
|
||||
@@ -1,72 +0,0 @@
|
||||
- name: Ensure user does not exist before tests
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_user
|
||||
|
||||
- block:
|
||||
- name: Get unexistent user
|
||||
openstack.cloud.identity_user_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_user
|
||||
register: userinfo
|
||||
- name: Ensure nothing was returned
|
||||
assert:
|
||||
that: not userinfo.openstack_users
|
||||
|
||||
- block:
|
||||
- name: Create user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
password: secret
|
||||
email: ansible.user@nowhere.net
|
||||
domain: default
|
||||
default_project: demo
|
||||
register: user
|
||||
- name: Create second user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user2
|
||||
password: secret
|
||||
email: ansible.user2@nowhere.net
|
||||
domain: default
|
||||
default_project: demo
|
||||
register: user
|
||||
- name: Get first user info
|
||||
openstack.cloud.identity_user_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_user
|
||||
register: userinfo
|
||||
- name: Assert only one result exists
|
||||
assert:
|
||||
that:
|
||||
- userinfo.openstack_users | length == 1
|
||||
- name: Assert userinfo has fields
|
||||
assert:
|
||||
that:
|
||||
- item in userinfo.openstack_users[0]
|
||||
loop: "{{ os_expected_user_info_fields }}"
|
||||
|
||||
- block:
|
||||
- name: Get all users
|
||||
openstack.cloud.identity_user_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: userinfo
|
||||
- name: Assert results were returned
|
||||
assert:
|
||||
that:
|
||||
- userinfo.openstack_users | length > 0
|
||||
|
||||
- name: Post-test cleanup
|
||||
block:
|
||||
- name: Ensure users do not exist
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ item }}"
|
||||
loop:
|
||||
- ansible_user
|
||||
- ansible_user2
|
||||
65
ci/roles/image/defaults/main.yml
Normal file
65
ci/roles/image/defaults/main.yml
Normal file
@@ -0,0 +1,65 @@
|
||||
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,154 +1,348 @@
|
||||
---
|
||||
- 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: ansible_image
|
||||
filename: "{{ tmp_file.stdout }}"
|
||||
disk_format: raw
|
||||
tags:
|
||||
- test
|
||||
- ansible
|
||||
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: ansible_image
|
||||
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_images[0].name == "ansible_image"
|
||||
- image_info_result.openstack_images[0].tags | sort == ['test', 'ansible'] | 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: ansible_image
|
||||
- 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: ansible_image
|
||||
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: ansible_image
|
||||
- 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: Try to get details of deleted image
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: ansible_image
|
||||
register: deleted_image_info_result
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
|
||||
- name: Verify image is deleted
|
||||
assert:
|
||||
that:
|
||||
- not deleted_image_info_result.openstack_images
|
||||
- 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: Create owner project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: image_owner_project
|
||||
description: Project owning test image
|
||||
domain_id: default
|
||||
enabled: True
|
||||
register: owner_project
|
||||
- name: Get details of created image
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: ansible_image
|
||||
register: images
|
||||
|
||||
- name: Create raw image (owner by project name)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
filename: "{{ tmp_file.stdout }}"
|
||||
disk_format: raw
|
||||
tags:
|
||||
- test
|
||||
- ansible
|
||||
project: image_owner_project
|
||||
register: image
|
||||
- name: 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: Get details of created image (owner by project name)
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: ansible_image
|
||||
register: image_info_result
|
||||
- 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: Verify image owner (owner by project name)
|
||||
assert:
|
||||
that:
|
||||
- image_info_result.openstack_images[0].owner == owner_project.project.id
|
||||
- name: Assert not changed
|
||||
assert:
|
||||
that:
|
||||
- image is not changed
|
||||
|
||||
- name: Delete raw image (owner by project name)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_image
|
||||
- name: Update is_protected on raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
is_protected: false
|
||||
register: image
|
||||
|
||||
- name: Create raw image (owner by project name and domain name)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
filename: "{{ tmp_file.stdout }}"
|
||||
disk_format: raw
|
||||
tags:
|
||||
- test
|
||||
- ansible
|
||||
project: image_owner_project
|
||||
project_domain: default
|
||||
register: image
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
- image.image.is_protected == false
|
||||
|
||||
- name: Get details of created image (owner by project name and domain name)
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: ansible_image
|
||||
register: image_info_result
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
|
||||
- name: Verify image owner (owner by project name and domain name)
|
||||
assert:
|
||||
that:
|
||||
- image_info_result.openstack_images[0].owner == owner_project.project.id
|
||||
- name: Update visibility on raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
is_public: false
|
||||
register: image
|
||||
|
||||
- name: Delete raw image (owner by project name and domain name)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_image
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image.image.visibility == 'private'
|
||||
|
||||
- name: Delete owner project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: image_owner_project
|
||||
domain_id: default
|
||||
- name: Update again visibility on raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
is_public: true
|
||||
register: image
|
||||
|
||||
- name: Delete test image file
|
||||
file:
|
||||
name: "{{ tmp_file.stdout }}"
|
||||
state: absent
|
||||
- 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: 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
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
expected_fields:
|
||||
- checksum
|
||||
- container_format
|
||||
- created_at
|
||||
- direct_url
|
||||
- disk_format
|
||||
- file
|
||||
- id
|
||||
- locations
|
||||
- metadata
|
||||
- min_disk
|
||||
- min_ram
|
||||
- name
|
||||
- os_hidden
|
||||
- owner
|
||||
- properties
|
||||
- schema
|
||||
- size
|
||||
- status
|
||||
- tags
|
||||
- updated_at
|
||||
- virtual_size
|
||||
- visibility
|
||||
@@ -1,11 +0,0 @@
|
||||
---
|
||||
- name: List all images # This will list at least the default cirros image of devstack
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: image_list_result
|
||||
|
||||
- name: Assert fields
|
||||
assert:
|
||||
that:
|
||||
- item in image_list_result.openstack_images.0.keys()
|
||||
loop: "{{ expected_fields }}"
|
||||
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
|
||||
406
ci/roles/inventory/tasks/main.yml
Normal file
406
ci/roles/inventory/tasks/main.yml
Normal file
@@ -0,0 +1,406 @@
|
||||
---
|
||||
- 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: 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
|
||||
@@ -6,6 +6,12 @@
|
||||
state: present
|
||||
register: keypair
|
||||
|
||||
- name: Assert fields
|
||||
assert:
|
||||
that:
|
||||
- item in keypair.keypair
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- name: Get list of all keypairs
|
||||
openstack.cloud.keypair_info:
|
||||
cloud: "{{ cloud }}"
|
||||
@@ -20,19 +26,19 @@
|
||||
- name: Ensure that list of keypairs contains single element
|
||||
assert:
|
||||
that:
|
||||
- keypairs['openstack_keypairs']|length == 1
|
||||
- keypairs['keypairs']|length == 1
|
||||
|
||||
- name: Assert fields
|
||||
assert:
|
||||
that:
|
||||
- item in keypairs.openstack_keypairs.0.keys()
|
||||
- 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.key.public_key is defined and keypair.key.public_key
|
||||
- keypair.keypair.public_key is defined and keypair.keypair.public_key
|
||||
|
||||
- name: Create another keypair
|
||||
openstack.cloud.keypair:
|
||||
@@ -61,7 +67,7 @@
|
||||
- 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:
|
||||
@@ -72,7 +78,7 @@
|
||||
- name: Generate test key file
|
||||
user:
|
||||
name: "{{ ansible_env.USER }}"
|
||||
generate_ssh_key: yes
|
||||
generate_ssh_key: true
|
||||
ssh_key_file: .ssh/shade_id_rsa
|
||||
|
||||
- name: Create keypair (file)
|
||||
@@ -91,7 +97,7 @@
|
||||
- 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:
|
||||
@@ -108,7 +114,7 @@
|
||||
- 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:
|
||||
@@ -126,7 +132,7 @@
|
||||
- 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:
|
||||
@@ -143,7 +149,7 @@
|
||||
- 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:
|
||||
|
||||
@@ -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,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
|
||||
@@ -4,7 +4,7 @@
|
||||
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
|
||||
- name: Upload Amphora image for Octavia to test load-balancers
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
container_format: bare
|
||||
@@ -20,17 +20,33 @@
|
||||
tags:
|
||||
- amphora
|
||||
|
||||
- name: Create network {{ network_name }} for LB
|
||||
- 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:
|
||||
@@ -41,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,20 +1,15 @@
|
||||
---
|
||||
- name: Trigger flavor listing
|
||||
- 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: Check log file presence
|
||||
ansible.builtin.stat:
|
||||
path: "{{ sdk_log_file_path }}"
|
||||
register: sdk_log_file
|
||||
- name: Read openstacksdk's log file
|
||||
ansible.builtin.slurp:
|
||||
src: "{{ sdk_log_file_path }}"
|
||||
register: log
|
||||
|
||||
- name: Assert
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- "sdk_log_file.stat.exists"
|
||||
|
||||
- name: Debug log file content
|
||||
- name: Print contents of openstacksdk's log
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ lookup('ansible.builtin.file', sdk_log_file_path) }}"
|
||||
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
|
||||
|
||||
9
ci/roles/neutron_rbac_policy/defaults/main.yml
Normal file
9
ci/roles/neutron_rbac_policy/defaults/main.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
expected_fields:
|
||||
- action
|
||||
- id
|
||||
- name
|
||||
- object_id
|
||||
- object_type
|
||||
- project_id
|
||||
- target_project_id
|
||||
- tenant_id
|
||||
@@ -1,38 +1,29 @@
|
||||
---
|
||||
# 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
|
||||
name: ansible_source_project
|
||||
description: Source project for network RBAC test
|
||||
domain_id: default
|
||||
enabled: True
|
||||
domain: default
|
||||
is_enabled: True
|
||||
register: source_project
|
||||
|
||||
- name: Create network - generic
|
||||
- name: Create network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name }}"
|
||||
name: "ansible_network"
|
||||
state: present
|
||||
project: "{{ source_project.project.id }}"
|
||||
shared: false
|
||||
external: "{{ network_external }}"
|
||||
external: true
|
||||
register: network
|
||||
|
||||
- name: Create target project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
name: ansible_target_project
|
||||
description: Target project for network RBAC test
|
||||
domain_id: default
|
||||
enabled: True
|
||||
@@ -48,38 +39,62 @@
|
||||
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_id: "{{ source_project.project.id }}"
|
||||
project: "{{ 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: 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.policy.id in rbac_policy_ids
|
||||
- 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 }}"
|
||||
policy_id: "{{ rbac_policy.policy.id }}"
|
||||
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_id: "{{ source_project.project.id }}"
|
||||
project: "{{ 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
|
||||
- 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,33 +0,0 @@
|
||||
---
|
||||
|
||||
- name: Get nova compute services info
|
||||
openstack.cloud.compute_service_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: result
|
||||
failed_when: "result.openstack_compute_services | length <= 0"
|
||||
|
||||
- name: Assert fields on OpenStack SDK before 0.53
|
||||
when: sdk_version is version(0.53, '<')
|
||||
assert:
|
||||
that:
|
||||
- '["availability_zone", "binary", "disables_reason",
|
||||
"host", "name", "state", "status", "id"] |
|
||||
difference(result.openstack_compute_services.0.keys()) | length == 0'
|
||||
|
||||
- name: Assert fields on OpenStack SDK 0.53 and later
|
||||
when: sdk_version is version(0.53, '>=')
|
||||
assert:
|
||||
that:
|
||||
- '["availability_zone", "binary", "disabled_reason", "is_forced_down",
|
||||
"host", "name", "state", "status", "updated_at", "id"] |
|
||||
difference(result.openstack_compute_services.0.keys()) | length == 0'
|
||||
|
||||
- name: Filter compute services. Supported since OpenStack SDK 0.53.0 (Wallaby).
|
||||
when: sdk_version is version(0.53, '>=')
|
||||
block:
|
||||
- name: Get nova compute services info
|
||||
openstack.cloud.compute_service_info:
|
||||
cloud: "{{ cloud }}"
|
||||
binary: "nova-compute"
|
||||
register: result
|
||||
failed_when: "result.openstack_compute_services | length <= 0"
|
||||
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,35 @@
|
||||
---
|
||||
- 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
|
||||
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: 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,93 @@
|
||||
---
|
||||
- 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 a container
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_container
|
||||
delete_metadata_keys:
|
||||
- 'Cache-Control'
|
||||
read_ACL: ""
|
||||
register: container
|
||||
|
||||
- name: Verify some keys from container metadata was deleted
|
||||
assert:
|
||||
that:
|
||||
- delete_meta is success
|
||||
- delete_meta 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': 'bar'}"
|
||||
- container.container.read_ACL is none or container.container.read_ACL == ""
|
||||
|
||||
- name: Delete container
|
||||
openstack.cloud.object_container:
|
||||
container: "{{ container_name }}"
|
||||
state: absent
|
||||
register: deleted
|
||||
- name: Delete container
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_container
|
||||
state: absent
|
||||
register: container
|
||||
|
||||
- name: Verify container was deleted
|
||||
assert:
|
||||
that:
|
||||
- deleted is success
|
||||
- deleted is changed
|
||||
- name: Verify container was deleted
|
||||
assert:
|
||||
that:
|
||||
- container is changed
|
||||
|
||||
always:
|
||||
- name: Delete container
|
||||
openstack.cloud.object_container:
|
||||
container: "{{ container_name }}"
|
||||
state: absent
|
||||
ignore_errors: yes
|
||||
- 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,45 @@
|
||||
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"
|
||||
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
|
||||
no_security_groups: True
|
||||
port_name: ansible_port
|
||||
subnet_name: ansible_port_subnet
|
||||
|
||||
@@ -1,121 +1,290 @@
|
||||
---
|
||||
- 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 }}"
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_security_group
|
||||
|
||||
- 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 }}"
|
||||
|
||||
- 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:
|
||||
|
||||
30
ci/roles/quota/defaults/main.yml
Normal file
30
ci/roles/quota/defaults/main.yml
Normal file
@@ -0,0 +1,30 @@
|
||||
test_project: ansible_project
|
||||
test_network_quota:
|
||||
floating_ips: 5
|
||||
networks: 50
|
||||
ports: 300
|
||||
rbac_policies: 5
|
||||
routers: 5
|
||||
security_group_rules: 5
|
||||
security_groups: 5
|
||||
subnet_pools: 5
|
||||
subnets: 5
|
||||
test_volume_quota:
|
||||
backup_gigabytes: 500
|
||||
backups: 5
|
||||
gigabytes: 500
|
||||
groups: 1
|
||||
per_volume_gigabytes: 10
|
||||
snapshots: 5
|
||||
volumes: 5
|
||||
test_compute_quota:
|
||||
cores: 5
|
||||
injected_file_content_bytes: 5
|
||||
injected_file_path_bytes: 5
|
||||
injected_files: 5
|
||||
instances: 5
|
||||
key_pairs: 5
|
||||
metadata_items: 5
|
||||
ram: 5
|
||||
server_group_members: 5
|
||||
server_groups: 5
|
||||
131
ci/roles/quota/tasks/main.yml
Normal file
131
ci/roles/quota/tasks/main.yml
Normal file
@@ -0,0 +1,131 @@
|
||||
---
|
||||
- module_defaults:
|
||||
group/openstack.cloud.openstack:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ test_project }}"
|
||||
# Backward compatibility with Ansible 2.9
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ test_project }}"
|
||||
openstack.cloud.quota:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ test_project }}"
|
||||
block:
|
||||
- name: Create test project
|
||||
openstack.cloud.project:
|
||||
state: present
|
||||
|
||||
- name: Clear quotas before tests
|
||||
openstack.cloud.quota:
|
||||
state: absent
|
||||
register: default_quotas
|
||||
|
||||
- name: Set network quota
|
||||
openstack.cloud.quota: "{{ test_network_quota }}"
|
||||
register: quotas
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that: quotas is changed
|
||||
|
||||
- name: Assert field values
|
||||
assert:
|
||||
that: quotas.quotas.network[item.key] == item.value
|
||||
loop: "{{ test_network_quota | dict2items }}"
|
||||
|
||||
- name: Set network quota again
|
||||
openstack.cloud.quota: "{{ test_network_quota }}"
|
||||
register: quotas
|
||||
|
||||
- name: Assert not changed
|
||||
assert:
|
||||
that: quotas is not changed
|
||||
|
||||
- name: Set volume quotas
|
||||
openstack.cloud.quota: "{{ test_volume_quota }}"
|
||||
register: quotas
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that: quotas is changed
|
||||
|
||||
- name: Assert field values
|
||||
assert:
|
||||
that: quotas.quotas.volume[item.key] == item.value
|
||||
loop: "{{ test_volume_quota | dict2items }}"
|
||||
|
||||
- name: Set volume quotas again
|
||||
openstack.cloud.quota: "{{ test_volume_quota }}"
|
||||
register: quotas
|
||||
|
||||
- name: Assert not changed
|
||||
assert:
|
||||
that: quotas is not changed
|
||||
|
||||
- name: Set compute quotas
|
||||
openstack.cloud.quota: "{{ test_compute_quota }}"
|
||||
register: quotas
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that: quotas is changed
|
||||
|
||||
- name: Assert field values
|
||||
assert:
|
||||
that: quotas.quotas.compute[item.key] == item.value
|
||||
loop: "{{ test_compute_quota | dict2items }}"
|
||||
|
||||
- name: Set compute quotas again
|
||||
openstack.cloud.quota: "{{ test_compute_quota }}"
|
||||
register: quotas
|
||||
|
||||
- name: Unset all quotas
|
||||
openstack.cloud.quota:
|
||||
state: absent
|
||||
register: quotas
|
||||
|
||||
- name: Assert defaults restore
|
||||
assert:
|
||||
that: quotas.quotas == default_quotas.quotas
|
||||
|
||||
- name: Set all quotas at once
|
||||
openstack.cloud.quota:
|
||||
"{{ [test_network_quota, test_volume_quota, test_compute_quota] | combine }}"
|
||||
register: quotas
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that: quotas is changed
|
||||
|
||||
- name: Assert volume values
|
||||
assert:
|
||||
that: quotas.quotas.volume[item.key] == item.value
|
||||
loop: "{{ test_volume_quota | dict2items }}"
|
||||
|
||||
- name: Assert network values
|
||||
assert:
|
||||
that: quotas.quotas.network[item.key] == item.value
|
||||
loop: "{{ test_network_quota | dict2items }}"
|
||||
|
||||
- name: Assert compute values
|
||||
assert:
|
||||
that: quotas.quotas.compute[item.key] == item.value
|
||||
loop: "{{ test_compute_quota | dict2items }}"
|
||||
|
||||
- name: Set all quotas at once again
|
||||
openstack.cloud.quota:
|
||||
"{{ [test_network_quota, test_volume_quota, test_compute_quota] | combine }}"
|
||||
register: quotas
|
||||
|
||||
- name: Assert not changed
|
||||
assert:
|
||||
that: quotas is not changed
|
||||
|
||||
- name: Unset all quotas
|
||||
openstack.cloud.quota:
|
||||
state: absent
|
||||
register: quotas
|
||||
|
||||
- name: Delete test project
|
||||
openstack.cloud.project:
|
||||
state: absent
|
||||
@@ -1,7 +1,7 @@
|
||||
dns_zone_name: test.dns.zone.
|
||||
recordset_name: testrecordset.test.dns.zone.
|
||||
records: ['10.0.0.0']
|
||||
updated_records: ['10.1.1.1']
|
||||
records: ['10.0.0.0', '10.0.0.2']
|
||||
updated_records: ['10.1.1.1', '10.0.0.2']
|
||||
|
||||
recordset_fields:
|
||||
- action
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
- recordset is changed
|
||||
- recordset["recordset"].name == recordset_name
|
||||
- recordset["recordset"].zone_name == dns_zone.zone.name
|
||||
- recordset["recordset"].records == records
|
||||
- recordset["recordset"].records | list | sort == records | list | sort
|
||||
|
||||
- name: Assert recordset fields
|
||||
assert:
|
||||
@@ -71,7 +71,7 @@
|
||||
- recordset is changed
|
||||
- recordset["recordset"].zone_name == dns_zone.zone.name
|
||||
- recordset["recordset"].name == recordset_name
|
||||
- recordset["recordset"].records == updated_records
|
||||
- recordset["recordset"].records | list | sort == updated_records | list | sort
|
||||
|
||||
- name: Assert recordset fields
|
||||
assert:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user