mirror of
https://opendev.org/openstack/ansible-collections-openstack.git
synced 2026-03-27 14:03:03 +00:00
Compare commits
99 Commits
2.3.1
...
stable/1.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e0458dd1a6 | ||
|
|
f448ac258d | ||
|
|
e4be201f20 | ||
|
|
bc16f70e1d | ||
|
|
dec8ecda5a | ||
|
|
dd383c010c | ||
|
|
acd0f01443 | ||
|
|
a4260040c6 | ||
|
|
ef5b217411 | ||
|
|
6592363c7c | ||
|
|
922032cb9f | ||
|
|
a11943d9b1 | ||
|
|
84160f6f78 | ||
|
|
1b03f918ac | ||
|
|
c435002734 | ||
|
|
e8bba38e2e | ||
|
|
058bd87f2a | ||
|
|
7772bf125d | ||
|
|
17e78e5173 | ||
|
|
0e9a6f26c2 | ||
|
|
8dfcd17731 | ||
|
|
39bb4909ee | ||
|
|
ce60e71bde | ||
|
|
b579d03968 | ||
|
|
8743f24c4b | ||
|
|
7a9837dfb5 | ||
|
|
26b53e78b2 | ||
|
|
b8c2310963 | ||
|
|
915a78d7af | ||
|
|
60c39d495f | ||
|
|
2052a47324 | ||
|
|
3ecd3b6e64 | ||
|
|
c4a296c07c | ||
|
|
6b58d28a4e | ||
|
|
620956c61d | ||
|
|
970fb2489c | ||
|
|
8cc678acc1 | ||
|
|
75558c5c2e | ||
|
|
b4bde6af5c | ||
|
|
b935f21f44 | ||
|
|
3c047406dc | ||
|
|
be8965c7fc | ||
|
|
acf64a1f72 | ||
|
|
a4894337d4 | ||
|
|
0b0a80796f | ||
|
|
c63ff6fbc8 | ||
|
|
4f8f6ffaf4 | ||
|
|
0204bbeede | ||
|
|
5626a8d4c9 | ||
|
|
a3bb143f34 | ||
|
|
9c16ee4df3 | ||
|
|
a70a4c3424 | ||
|
|
708ed756ca | ||
|
|
c83884e5c8 | ||
|
|
655ed21ffa | ||
|
|
e64211213a | ||
|
|
39676b664a | ||
|
|
220f2b7dca | ||
|
|
0af7a252bd | ||
|
|
e8f9457893 | ||
|
|
29831685d8 | ||
|
|
82311440b5 | ||
|
|
57012cbaa3 | ||
|
|
5b453c62d1 | ||
|
|
8e1f1d6475 | ||
|
|
4b9e2295e0 | ||
|
|
5bb8312171 | ||
|
|
b3ac841442 | ||
|
|
37c52c321d | ||
|
|
6edc70f965 | ||
|
|
cc8cd08c03 | ||
|
|
b572bf8ae9 | ||
|
|
b3e0d610ea | ||
|
|
291e8b8640 | ||
|
|
f70a50e363 | ||
|
|
befcc4353d | ||
|
|
8a91352a38 | ||
|
|
1d7fd25ac0 | ||
|
|
44fa06cba1 | ||
|
|
26bc8a0666 | ||
|
|
19d0562551 | ||
|
|
07c3ed0c17 | ||
|
|
8708167b5f | ||
|
|
a9565779b5 | ||
|
|
5c2069c47d | ||
|
|
583df2a8a9 | ||
|
|
0f532d10f3 | ||
|
|
87858ab976 | ||
|
|
09c3e4bdc9 | ||
|
|
ebffbe4fe8 | ||
|
|
cbcfce2e23 | ||
|
|
406558dae9 | ||
|
|
c8d89f81a5 | ||
|
|
c0e1f56894 | ||
|
|
a031968f80 | ||
|
|
2e78559cc1 | ||
|
|
bf939a4ce0 | ||
|
|
24d6f36602 | ||
|
|
dd9cdde3d8 |
360
.zuul.yaml
360
.zuul.yaml
@@ -47,20 +47,11 @@
|
||||
devstack_services:
|
||||
designate: true
|
||||
neutron-dns: true
|
||||
neutron-trunk: true
|
||||
zuul_copy_output:
|
||||
'{{ devstack_log_dir }}/test_output.log': 'logs'
|
||||
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
|
||||
@@ -123,72 +114,277 @@
|
||||
- ^plugins/modules/lb_pool.py
|
||||
- ^plugins/modules/loadbalancer.py
|
||||
vars:
|
||||
configure_swap_size: 4096
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$OCTAVIA_CONF:
|
||||
controller_worker:
|
||||
amphora_driver: amphora_noop_driver
|
||||
configure_swap_size: 8192
|
||||
tox_install_siblings: false
|
||||
devstack_plugins:
|
||||
designate: https://opendev.org/openstack/designate
|
||||
octavia: https://opendev.org/openstack/octavia
|
||||
devstack_services:
|
||||
designate: true
|
||||
neutron-dns: true
|
||||
octavia: true
|
||||
o-api: true
|
||||
o-cw: true
|
||||
o-hm: true
|
||||
o-hk: true
|
||||
neutron-dns: true
|
||||
tox_extra_args: -vv --skip-missing-interpreters=false -- loadbalancer
|
||||
tox_install_siblings: false
|
||||
o-hm: true
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-octavia
|
||||
parent: ansible-collections-openstack-functional-devstack-octavia-base
|
||||
branches: master
|
||||
branches: stable/1.0.0
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
with Octavia plugin enabled, using latest releases of openstacksdk
|
||||
with Octavia plugin enabled, using 0.*.* releases of openstacksdk
|
||||
and latest ansible release. Run it only on Load Balancer changes.
|
||||
required-projects:
|
||||
- # Choose parent devstack job from master branch instead of non-existing stable/1.0.0 branch
|
||||
name: openstack/devstack
|
||||
override-checkout: master
|
||||
- # Choose parent devstack job from master branch instead of non-existing stable/1.0.0 branch
|
||||
name: openstack/openstacksdk
|
||||
override-checkout: master
|
||||
vars:
|
||||
tox_constraints_file: '{{ ansible_user_dir }}/{{ zuul.project.src_dir }}/tests/constraints-openstacksdk-0.x.x.txt'
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-releases
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
branches: master
|
||||
branches: stable/1.0.0
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using latest releases of openstacksdk and latest ansible release
|
||||
using 0.*.* releases of openstacksdk and latest ansible release
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.9
|
||||
- # Choose parent devstack job from master branch instead of non-existing stable/1.0.0 branch
|
||||
name: openstack/devstack
|
||||
override-checkout: master
|
||||
- # Choose parent devstack job from master branch instead of non-existing stable/1.0.0 branch
|
||||
name: openstack/openstacksdk
|
||||
override-checkout: master
|
||||
vars:
|
||||
tox_constraints_file: '{{ ansible_user_dir }}/{{ zuul.project.src_dir }}/tests/constraints-openstacksdk-1.x.x.txt'
|
||||
tox_constraints_file: '{{ ansible_user_dir }}/{{ zuul.project.src_dir }}/tests/constraints-openstacksdk-0.x.x.txt'
|
||||
tox_install_siblings: false
|
||||
|
||||
# Job with Ansible 2.9 for checking backward compatibility
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-2.18
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-2.9
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
branches: master
|
||||
branches: stable/1.0.0
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using master of openstacksdk and stable 2.16 branch of ansible
|
||||
using 0.*.* releases of openstacksdk and stable 2.9 branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.18
|
||||
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_18
|
||||
tox_envlist: ansible_2_9
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-2.11
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
nodeset: openstack-single-node-jammy
|
||||
branches: master
|
||||
branches: stable/1.0.0
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using master of openstacksdk and devel branch of ansible
|
||||
# non-voting because we can't prevent ansible devel from breaking us
|
||||
voting: false
|
||||
using 0.*.* releases of openstacksdk and stable 2.12 branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: devel
|
||||
override-checkout: stable-2.11
|
||||
- # Choose parent devstack job from stable/yoga branch instead of non-existing stable/1.0.0 branch
|
||||
name: openstack/devstack
|
||||
override-checkout: stable/yoga
|
||||
- name: openstack/openstacksdk
|
||||
# Yoga has the latest SDK release of the 0.*.* series atm
|
||||
override-checkout: stable/yoga
|
||||
vars:
|
||||
tox_envlist: ansible_2_11
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-2.12
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
branches: stable/1.0.0
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using 0.*.* releases of openstacksdk and stable 2.12 branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.12
|
||||
- # Choose parent devstack job from 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.
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
description: |
|
||||
Run openstack collections functional tests against a wallaby devstack
|
||||
using wallaby branch of openstacksdk and stable 2.12 branch of ansible
|
||||
branches: stable/1.0.0
|
||||
override-checkout: stable/wallaby
|
||||
# job.override-checkout will not override job.required-projects.override-checkout in parent jobs
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.12
|
||||
- # Choose parent devstack job from stable/1.0.0 branch instead of non-existing stable/wallaby branch
|
||||
name: openstack/ansible-collections-openstack
|
||||
override-checkout: stable/1.0.0
|
||||
- # Choose parent devstack job from stable/wallaby branch
|
||||
name: openstack/devstack
|
||||
override-checkout: stable/wallaby
|
||||
- name: openstack/designate
|
||||
override-checkout: stable/wallaby
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/wallaby
|
||||
vars:
|
||||
tox_envlist: ansible_2_12
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-victoria-ansible-2.12
|
||||
# Do not inherit from any parent job which does not run for branch stable/1.0.0 because Zuul would dismiss this job
|
||||
# when collecting parent job variants. For example, when job.branches is set to master in a parent job, then Zuul
|
||||
# will not match that job when it collects job variants.
|
||||
#
|
||||
# Do not inherit from any parent job which sets job.required-projects.override-checkout on openstack/devstack
|
||||
# because Zuul would use that git ref instead of stable branch defined below to checkout projects of parent devstack
|
||||
# jobs when collecting variants for parent jobs.
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
description: |
|
||||
Run openstack collections functional tests against a victoria devstack
|
||||
using victoria branch of openstacksdk and stable 2.12 branch of ansible
|
||||
branches: stable/1.0.0
|
||||
override-checkout: stable/victoria
|
||||
# job.override-checkout will not override job.required-projects.override-checkout in parent jobs
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.12
|
||||
- # Choose parent devstack job from stable/1.0.0 branch instead of non-existing stable/victoria branch
|
||||
name: openstack/ansible-collections-openstack
|
||||
override-checkout: stable/1.0.0
|
||||
- # Choose parent devstack job from stable/victoria branch
|
||||
name: openstack/devstack
|
||||
override-checkout: stable/victoria
|
||||
- name: openstack/designate
|
||||
override-checkout: stable/victoria
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/victoria
|
||||
vars:
|
||||
tox_envlist: ansible_2_12
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ussuri-ansible-2.11
|
||||
# Do not inherit from any parent job which does not run for branch stable/1.0.0 because Zuul would dismiss this job
|
||||
# when collecting parent job variants. For example, when job.branches is set to master in a parent job, then Zuul
|
||||
# will not match that job when it collects job variants.
|
||||
#
|
||||
# Do not inherit from any parent job which sets job.required-projects.override-checkout on openstack/devstack
|
||||
# because Zuul would use that git ref instead of stable branch defined below to checkout projects of parent devstack
|
||||
# jobs when collecting variants for parent jobs.
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
description: |
|
||||
Run openstack collections functional tests against a ussuri devstack
|
||||
using ussuri 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
|
||||
|
||||
# Linters
|
||||
- job:
|
||||
@@ -218,106 +414,86 @@
|
||||
bindep_profile: test py310
|
||||
|
||||
- job:
|
||||
name: openstack-tox-linters-ansible-2.18
|
||||
name: openstack-tox-linters-ansible-2.12
|
||||
parent: openstack-tox-linters-ansible
|
||||
nodeset: ubuntu-focal
|
||||
description: |
|
||||
Run openstack collections linter tests using the 2.18 branch of ansible
|
||||
Run openstack collections linter tests using the 2.12 branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.18
|
||||
override-checkout: stable-2.12
|
||||
vars:
|
||||
tox_envlist: linters_2_18
|
||||
python_version: "3.12"
|
||||
bindep_profile: test py312
|
||||
ensure_tox_version: '<4'
|
||||
tox_envlist: linters_2_12
|
||||
python_version: 3.8
|
||||
bindep_profile: test py38
|
||||
|
||||
# Cross-checks with other projects
|
||||
- job:
|
||||
name: bifrost-collections-src
|
||||
parent: bifrost-integration-tinyipa-ubuntu-jammy
|
||||
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 master branch when collecting parent job variants, refer to git blame for rationale.
|
||||
- # always use existing branch when collecting parent job variants, refer to git blame for rationale.
|
||||
name: openstack/bifrost
|
||||
override-checkout: master
|
||||
- # always use master branch when collecting parent job variants
|
||||
name: openstack/openstacksdk
|
||||
override-checkout: master
|
||||
# Yoga has the latest SDK release of the 0.*.* series atm
|
||||
override-checkout: stable/yoga
|
||||
- job:
|
||||
name: bifrost-keystone-collections-src
|
||||
parent: bifrost-integration-tinyipa-keystone-ubuntu-jammy
|
||||
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 master branch when collecting parent job variants, refer to git blame for rationale.
|
||||
- # always use existing branch when collecting parent job variants, refer to git blame for rationale.
|
||||
name: openstack/bifrost
|
||||
override-checkout: master
|
||||
- # always use master branch when collecting parent job variants
|
||||
name: openstack/openstacksdk
|
||||
override-checkout: master
|
||||
# Yoga has the latest SDK release of the 0.*.* series atm
|
||||
override-checkout: stable/yoga
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-release
|
||||
parent: base
|
||||
run: ci/publish/publish_collection.yml
|
||||
secrets:
|
||||
- ansible_galaxy_info
|
||||
|
||||
- secret:
|
||||
name: ansible_galaxy_info
|
||||
data:
|
||||
url: https://galaxy.ansible.com
|
||||
token: !encrypted/pkcs1-oaep
|
||||
- QJ3c5LfmM4YmqwwLKv4wK5lroWDLGeMyPkmHXhvf0ry3vGjKZvZxVpbIhFXJHXevHov/r
|
||||
nvlqwmG8D5msynQKZDFg2ZwSMIQWRKfSbsSLe7A6NWI2wC+QtZSPiRiBcBcHY1QbNNW21
|
||||
84cssYa1oHOA0WXpomBz1qXuPV48aKLjMnWysgFhNSx3Oog+ZOSCczyyVVuXP1lIWIO26
|
||||
AtRTrEcr37K3JY9usE2PCbZKFOq/+IDPz9fbS7PtBOv7iXOHOf3AfBiJiaJe3q/ecoaaq
|
||||
ejk2WTKWfvq/3rY4pU1976kUcxgcd+jj9ReFyw8edCsc1ecL0qmZFbdHmC03jEcVo4p8I
|
||||
WJQ0D5wk4/u2Fu9texNuBvb62Yu3Y028Zhm5rz8Zl/ISsdaA3losn5S7C7iAH/yKlGQEI
|
||||
N/1X4M0tVPaMtsIhZyyz+JMbeNyVR9ZarqbtpzRtVhjxL7KOiAQbEzAmZcBbCJ2Z5iI+P
|
||||
bTp03f9Y/tZNtkohARvx1TKhv8CvsmyGkMm+r5Y8aWz3SNy8LL6bSwtGun/ifbnadHmw/
|
||||
TD5/UUXHHjBGkeAu9HTtwUZ5Qdkfg92PnPgruAAuOkF1Y4RyRS9qvwhtqyHO8TwU0INRY
|
||||
5MHEzeOQWemoQb/qdENp+J/Q9oMEbpFYv9TkrWkxVoKop6Str8e3FF5sxmN/SE=
|
||||
|
||||
- project:
|
||||
check:
|
||||
jobs:
|
||||
- tox-pep8
|
||||
- openstack-tox-linters-ansible-devel
|
||||
- openstack-tox-linters-ansible-2.18
|
||||
- ansible-collections-openstack-functional-devstack
|
||||
- ansible-collections-openstack-functional-devstack-releases
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.18
|
||||
- ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
- ansible-collections-openstack-functional-devstack-magnum
|
||||
- ansible-collections-openstack-functional-devstack-octavia
|
||||
|
||||
- bifrost-collections-src:
|
||||
voting: false
|
||||
irrelevant-files: *ignore_files
|
||||
- bifrost-keystone-collections-src:
|
||||
voting: false
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-releases:
|
||||
dependencies:
|
||||
- tox-pep8
|
||||
|
||||
gate:
|
||||
jobs:
|
||||
- tox-pep8
|
||||
- openstack-tox-linters-ansible-2.18
|
||||
- ansible-collections-openstack-functional-devstack-releases
|
||||
- ansible-collections-openstack-functional-devstack-magnum
|
||||
- ansible-collections-openstack-functional-devstack-octavia
|
||||
|
||||
periodic:
|
||||
jobs:
|
||||
- openstack-tox-linters-ansible-devel
|
||||
- openstack-tox-linters-ansible-2.18
|
||||
- ansible-collections-openstack-functional-devstack
|
||||
- openstack-tox-linters-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-releases
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.18
|
||||
- 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
|
||||
- ansible-collections-openstack-functional-devstack-octavia
|
||||
|
||||
experimental:
|
||||
jobs:
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-victoria-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-ussuri-ansible-2.11
|
||||
|
||||
tag:
|
||||
jobs:
|
||||
- ansible-collections-openstack-release
|
||||
|
||||
310
CHANGELOG.rst
310
CHANGELOG.rst
@@ -1,233 +1,135 @@
|
||||
==========================================
|
||||
Ansible OpenStack Collection Release Notes
|
||||
==========================================
|
||||
=============================================
|
||||
Openstack Cloud Ansilbe modules Release Notes
|
||||
=============================================
|
||||
|
||||
.. contents:: Topics
|
||||
|
||||
|
||||
v2.3.1
|
||||
======
|
||||
v1.10.0
|
||||
=======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Client TLS certificate support
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add ability to pass client tls certificate
|
||||
|
||||
v2.3.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfixes and new modules
|
||||
|
||||
Major Changes
|
||||
-------------
|
||||
|
||||
- Add Neutron trunk module
|
||||
- Add application_credential module
|
||||
- Add module to filter available volume services
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add inactive state for the images
|
||||
- Add insecure_registry property to coe_cluster_templates
|
||||
- Add support for creation of the default external networks
|
||||
- Add target_all_project option
|
||||
- Add vlan_tranparency for creation networks
|
||||
- Allow munch results in server_info module
|
||||
- Allow to specify multiple allocation pools when creating a subnet
|
||||
- CI - Disable auto-discovery for setuptools
|
||||
- CI - Don't create port with binding profile
|
||||
- CI - Fix CI in collection
|
||||
- CI - Fix linters-devel and devstack tests
|
||||
- CI - Fix regression in quota module
|
||||
- CI - Fix test for server shelve
|
||||
- CI - Migrate Bifrost jobs to Ubuntu Jammy
|
||||
- CI - Remove 2.9 jobs from Zuul config
|
||||
- CI - Run functional testing regardless of pep8/linter results
|
||||
- Enable glance-direct interop image import
|
||||
- Ensure coe_cluster_template compare labels properly
|
||||
- Wait for deleted server to disappear from results
|
||||
- router - Allow specifying external network name in a different project
|
||||
Enable logging of openstacksdk activities and warn users about incompatible openstacksdk releases when using inventory plugin
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Allow wait false when auto_ip is false
|
||||
- Fix exception when creating object from file
|
||||
- Fix exception when updating container with metadata
|
||||
- Fix typo in openstack.cloud.lb_pool
|
||||
- Fix typo in parameter description
|
||||
- fix subnet module - allow cidr option with subnet_pool
|
||||
- Add SDK logging option for openstack ansible collections
|
||||
- Don't use deprecated distutils from python 3.10
|
||||
- Ensure openstacksdk compatibility in inventory plugin
|
||||
- Lowered maximum OpenStack SDK version to 0.98.999 in inventory plugin
|
||||
|
||||
Known Issues
|
||||
------------
|
||||
|
||||
- For compatibility with OpenStack SDK >= 0.99.0 use Ansible OpenStack collection 2.0.0 or later which is currently under development.
|
||||
- Release series 1.x.x of this collection is compatible to OpenStack SDK prior to 0.99.0 only.
|
||||
|
||||
v1.9.1
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfix in keypair module
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Do not remove trailing spaces when reading public key in keypair module
|
||||
|
||||
Known Issues
|
||||
------------
|
||||
|
||||
- For compatibility with OpenStack SDK >= 0.99.0 use Ansible OpenStack collection 2.0.0 or later which is currently under development.
|
||||
- Release series 1.x.x of this collection is compatible to OpenStack SDK prior to 0.99.0 only.
|
||||
|
||||
v1.9.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
This release will enforce openstacksdk<0.99.0, has a dozen modules refactored and several bugs fixed.
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Added support for specifying a maximum version of the OpenStack SDK
|
||||
- Constrain filters in compute_service_info to SDK >= 0.53.0
|
||||
- Drop username from return values of identity_user_info
|
||||
- Fix logic in routers_info
|
||||
- Fixed return value disable{d,s}_reason in compute_service_info module
|
||||
- Fixed return values in compute_service_info module again
|
||||
- Follow up to bump of minimum required OpenStack SDK release to SDK 0.36.0 (Train)
|
||||
- Lowered maximum OpenStack SDK version to 0.98.999
|
||||
- Move dns zone info to use proxy layer
|
||||
- Refactored catalog_service module
|
||||
- Refactored endpoint module
|
||||
- Refactored host_aggregate module
|
||||
- Refactored identity_domain_info module
|
||||
- Refactored identity_group_info module
|
||||
- Refactored identity_role module
|
||||
- Refactored identity_role_info module
|
||||
- Refactored identity_user module
|
||||
- Refactored identity_user_info module
|
||||
- Refactored image_info module
|
||||
- Refactored keypair_info module
|
||||
- Refactored recordset module
|
||||
- Refactored role_assignment module
|
||||
- Set owner in image module
|
||||
- Support description in sg-rule creation
|
||||
- Warn users about us breaking backward compatibility
|
||||
|
||||
Known Issues
|
||||
------------
|
||||
|
||||
- For compatibility with OpenStack SDK >= 0.99.0 use Ansible OpenStack collection 2.0.0 or later which is currently under development.
|
||||
- Release series 1.x.x of this collection is compatible to OpenStack SDK prior to 0.99.0 only.
|
||||
|
||||
v1.8.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Subnet pool module and bugfixes
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Add 'all_projects' to server_action module
|
||||
- Add subnet pool module
|
||||
- Bumped minimum required OpenStack SDK release to SDK 0.36.0 (Train)
|
||||
- Changed compute_flavor_info module to use OpenStack SDK's proxy layer
|
||||
- Dropped deprecated return values in floating_ip_info and assert remaining fields
|
||||
- Fix ansible-lint issues for the newest version
|
||||
- Fix assertion after stack deletion
|
||||
- Handle aggregate host list set to None
|
||||
- Reenabled check-import.sh which tests imports to Ansible Galaxy
|
||||
- Remove old, unsupported parameters from documentation in image_info module
|
||||
- Router - Remove unneeded 'filter' parameter
|
||||
- Updated return value docs of compute_service_info module
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.application_credential - Manage OpenStack Identity (Keystone) application credentials
|
||||
- openstack.cloud.trunk - Add or delete trunks from an OpenStack cloud
|
||||
- openstack.cloud.volume_service_info - Fetch OpenStack Volume (Cinder) services
|
||||
- openstack.cloud.subnet_pool - Create or Delete subnet pools from OpenStack.
|
||||
|
||||
v2.2.0
|
||||
v1.7.2
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
New module for volume_type and bugfixes
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add volume_encryption_type modules
|
||||
- Add volume_type modules
|
||||
Bugfixes
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Fix image module filter
|
||||
- Fix port module idempotency
|
||||
- Fix router module idempotency
|
||||
|
||||
v2.1.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
New module for Ironic and bugfixes
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add baremetal_deploy_template module
|
||||
- Highlight our mode of operation more prominently
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Change security group rules only when instructed to do so
|
||||
- Fix for AttributeError: 'dict' object has no attribute 'status'
|
||||
- Fix issue with multiple records in recordset
|
||||
- Fix mistake in compute_flavor_access notes
|
||||
- Fixed private option in inventory plugin
|
||||
- Respect description option and delete security group rules first
|
||||
- Use true and false instead of yes and no for boolean values
|
||||
|
||||
v2.0.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Our new major release 2.0.0 of the Ansible collection for OpenStack clouds aka ``openstack.cloud`` is a complete overhaul of the code base and brings full compatibility with openstacksdk 1.0.0.
|
||||
|
||||
Highlights of this release are
|
||||
* three new modules which for example provide a generic and uniform API for interacting with OpenStack cloud resources,
|
||||
* a complete refactoring of all existing modules bringing dozens of bugfixes, new features as well as consistent
|
||||
and properly documented module results and options,
|
||||
* 100% compatibility with openstacksdk's first major release 1.0.0,
|
||||
* new guides for contributors from devstack setup over coding guidelines to our release process and
|
||||
* massively increased CI coverage with many new integration tests, now covering all modules and plugins.
|
||||
|
||||
Note, this ``2.0.0`` release *breaks backward compatibility* with previous ``1.x.x`` releases!
|
||||
* ``2.x.x`` releases of this collection are compatible with openstacksdk ``1.x.x`` and later *only*,
|
||||
* ``1.x.x`` releases of this collection are compatible with openstacksdk ``0.x.x`` prior to ``0.99.0`` *only*,
|
||||
* ``2.x.x`` releases of are not backward compatible with ``1.x.x`` releases,
|
||||
* ``1.x.x`` release series will be in maintenance mode now and receive bugfixes only.
|
||||
|
||||
However, this collection as well as openstacksdk continue to be backward compatible with clouds running on older OpenStack releases. For example, it is fine and a fully supported use case to use this 2.0.0 release with clouds based on OpenStack Train, Wallaby or Zed. Feel encouraged to always use the latest releases of this collection and openstacksdk regardless of which version of OpenStack is installed in your cloud.
|
||||
|
||||
This collection is compatible with and tested with Ansible 2.9 and later. However, support for old ``os_*`` short module names such as ``os_server`` have been dropped with this release. You have to call modules using their FQCN (Fully-Qualified Collection Name) such as ``openstack.cloud.server`` instead.
|
||||
|
||||
Many thanks to all contributors who made this release possible. Tens of thousands LOCs have been reviewed and changed and fixed and tested throughout last year. You rock!
|
||||
|
||||
Major Changes
|
||||
-------------
|
||||
|
||||
- Many modules gained support for Ansible's check mode or have been fixed to properly implement a no change policy during check mode runs.
|
||||
- Many modules gained support for updates. In the past, those modules allowed to create and delete OpenStack cloud resources but would ignore when module options had been changed.
|
||||
- Many modules such as ``openstack.cloud.server``, ``openstack.cloud.baremetal_node`` and all load-balancer related modules now properly implement the ``wait`` option. For example, when ``wait`` is set to ``true`` then modules will not return until resources have reached its ``active`` or ``deleted`` state.
|
||||
- Module ``openstack.cloud.resource`` has been added. It provides an generic and uniform interface to create, update and delete any OpenStack cloud resource which openstacksdk supports. This module unlocks a huge amount of functionality from OpenStack clouds to Ansible users which has been inaccessible with existing modules so far.
|
||||
- Module ``openstack.cloud.resources`` has been added. It provides an generic and uniform interface to list any type of OpenStack cloud resources which openstacksdk supports. This module fetch any OpenStack cloud resource without having to implement a new Ansible ``*_info`` module for this type of resource first.
|
||||
- Module ``openstack.cloud.subnet_pool`` has been added. It allows to create and delete subnet pools in OpenStack clouds.
|
||||
- Module examples have been improved and updated for most modules.
|
||||
- Module results have been properly documented for all modules.
|
||||
- Options in all modules have been renamed to match openstacksdk's attribute names (if applicable). The previous option names have been added as aliases to keep module options backward compatible.
|
||||
- Our CI integration tests have been massively expanded. Our test coverage spans across all modules and plugins now, including tests for our inventory plugin and our new ``openstack.cloud.resource`` and ``openstack.cloud.resources`` modules.
|
||||
- Our contributors documentation has been heavily extended. In directory ``docs`` you will find the rationale for our branching strategy, a developer's guide on how to contribute to the collection, a tutorial to set up a DevStack environment for hacking on and testing the collection, a step-by-step guide for publishing new releases and a list of questions to ask when doing reviews or submitting patches for review.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Added generic module options ``sdk_log_path`` and ``sdk_log_level`` which allow to track openstacksdk activity.
|
||||
- Many more options were added to modules but we stopped counting at one point...
|
||||
- Module ``openstack.cloud.coe_cluster`` gained support for option ``is_floating_ip_enabled``.
|
||||
- Module ``openstack.cloud.lb_listener`` gained options ``default_tls_container_ref`` and ``sni_container_refs`` which allow to specify TLS certificates when using the ``TERMINATED_HTTPS`` protocol.
|
||||
- Module ``openstack.cloud.network`` gained support for updates, i.e. existing networks will be properly updated now when module options such as ``mtu`` or ``admin_state_up`` have been changed.
|
||||
- Module ``openstack.cloud.port`` gained an ``description`` option.
|
||||
- Module ``openstack.cloud.role_assignment`` gained an ``system`` option.
|
||||
- Module ``openstack.cloud.security_group_rule`` gained an ``description`` option.
|
||||
- Module ``openstack.cloud.server_action`` gained an option ``all_projects`` which allows to execute actions on servers outside of the current auth-scoped project (if the user has permission to do so).
|
||||
- Module ``openstack.cloud.server_info`` gained an ``description`` option.
|
||||
- Module ``openstack.cloud.server`` gained an ``description`` option.
|
||||
- Module ``openstack.cloud.server`` gained support for updates. For example, options such as ``description`` and floating ip addresses can be updated now.
|
||||
- Module ``openstack.cloud.subnet`` gained an ``subnet_pool`` option.
|
||||
|
||||
Breaking Changes / Porting Guide
|
||||
--------------------------------
|
||||
|
||||
- 2.x.x releases of this collection are not backward compatible with 1.x.x releases. Backward compatibility is guaranteed within each release series only. Module options have been kept backward compatible across both release series, apart from a few exceptions noted below. However, module results have changed for most modules due to deep changes in openstacksdk. For easier porting and usage, we streamlined return values across modules and documented return values of all modules.
|
||||
- Default value for option ``security_groups`` in ``openstack.cloud.server`` has been changed from ``['default']`` to ``[]`` because the latter is the default in python-openstackclient and the former behavior causes issues with existing servers.
|
||||
- Dropped symbolic links with prefix ``os_`` and plugin routing for deprecated ``os_*`` module names. This means users have to call modules of the Ansible OpenStack collection using their FQCN (Fully Qualified Collection Name) such as ``openstack.cloud.server``. Short module names such as ``os_server`` will now raise an Ansible error.
|
||||
- Module ``openstack.cloud.project_access`` has been split into two separate modules ``openstack.cloud.compute_flavor_access`` and ``openstack.cloud.volume_type_access``.
|
||||
- Option ``availability_zone`` has been removed from the list of generic options available in all modules. Instead it has been inserted into the ``openstack.cloud.server`` and ``openstack.cloud.volume`` modules because it is relevant to those two modules only.
|
||||
- Option ``name`` of module ``openstack.cloud.port`` is required now because it is used to find, update and delete ports and idempotency would break otherwise.
|
||||
- Option ``policies`` has been replaced with option ``policy`` in module ``openstack.cloud.server_group``. The former is ancient and was superceded by ``policy`` a long time ago.
|
||||
- Release series 2.x.x of this collection is compatible with openstacksdk 1.0.0 and later only. For compatibility with openstacksdk < 0.99.0 use release series 1.x.x of this collection. Ansible will raise an error when modules and plugins in this collection are used with an incompatible release of openstacksdk.
|
||||
- Special value ``auto`` for option ``id`` in module ``openstack.cloud.compute_flavor`` has been deprecated to be consistent with our other modules and openstacksdk's behaviour.
|
||||
|
||||
Deprecated Features
|
||||
-------------------
|
||||
|
||||
- Option ``is_public`` in module ``openstack.cloud.image`` has been deprecated and replaced with option ``visibility``.
|
||||
- Option ``volume`` in module ``openstack.cloud.image`` has been deprecated and it should be replaced with module ``openstack.cloud.volume`` in user code.
|
||||
|
||||
Removed Features (previously deprecated)
|
||||
----------------------------------------
|
||||
|
||||
- Dropped deprecated ``skip_update_of_driver_password`` option from module ``openstack.cloud.baremetal_node``.
|
||||
- Dropped unmaintained, obsolete and broken inventory script ``scripts/inventory/openstack_inventory.py``. It had been replaced with a proper Ansible inventory plugin ``openstack.cloud.openstack`` during the 1.x.x life cycle.
|
||||
- Module ``openstack.cloud.object`` no longer allows to create and delete containers, its sole purpose is managing an object in a container now. Use module ``openstack.cloud.object_container`` to managing Swift containers instead.
|
||||
- Option ``listeners`` has been removed from module ``openstack.cloud.loadbalancer`` because it duplicates a subset of the functionality (and code) provided by our ``openstack.cloud.lb_{listener,member,pool}`` modules.
|
||||
- Our outdated, undocumented, untested and bloated code templates in ``contrib`` directory which could be used to generate and develop new Ansible modules for this collection have been removed.
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Ansible check mode has been fixed in module ``openstack.cloud.compute_flavor``, it will no longer apply changes when check mode is enabled.
|
||||
- Creating load-balancers with module ``openstack.cloud.loadbalancer`` properly handles situations where several provider networks exist. A floating ip address specified in option ``floating_ip_address`` will be allocated from Neutron external network specified in option ``floating_ip_network``.
|
||||
- Default values for options ``shared``, ``admin_state_up`` and ``external`` in module ``openstack.cloud.network`` have been dropped because they cause failures for clouds which do not have those optional extensions installed.
|
||||
- Dropped default values for options ``min_disk`` and ``min_ram`` in module ``openstack.cloud.image`` because it interferes with its update mechanism and Glance uses those values anyway. Fixed handling of options ``name``, ``id``, ``visibility`` and ``is_public``.
|
||||
- Module ``openstack.cloud.baremetal_node_info`` will now properly return machine details when iterating over all available baremetal nodes.
|
||||
- Module ``openstack.cloud.host_aggregate`` now correctly handles ``hosts`` not being set or being set to ``None``.
|
||||
- Module ``openstack.cloud.identity_user`` will no longer fail when no password is supplied since Keystone allows to create a user without an password.
|
||||
- Module ``openstack.cloud.keypair`` no longer removes trailing spaces when reading a public key because this broke idempotency when using openstackclient and this module at the same time.
|
||||
- Module ``openstack.cloud.quota`` no longer sends invalid attributes such as ``project_id`` to OpenStack API when updating Nova, Neutron and Cinder quotas.
|
||||
- Module ``openstack.cloud.server`` will no longer change security groups to ``['default']`` on existing servers when option ``security_groups`` has not been specified.
|
||||
- Module ``openstack.cloud.subnet`` now properly handles updates, thus idempotency has been fixed and restored.
|
||||
- Modules ``openstack.cloud.security_group`` and ``openstack.cloud.security_group_rule`` gained support for specifying string ``any`` as a valid protocol in security group rules.
|
||||
- Option ``interfaces`` in module ``openstack.cloud.router`` no longer requires option ``network`` to be set, it is ``external_fixed_ips`` what requires ``network``.
|
||||
- Option ``is_public`` in module ``openstack.cloud.image`` will now be handled as a boolean instead of a string to be compatible to Glance API and fix issues when interacting with Glance service.
|
||||
- Option ``network`` in module ``openstack.cloud.router`` is now propery marked as required by options ``enable_snat`` and ``external_fixed_ips``.
|
||||
- Option ``owner`` in module ``openstack.cloud.image`` is now respected when searching for and creating images.
|
||||
- Our OpenStack inventory plugin now properly supports Ansible's cache feature.
|
||||
- Fix collection guidelines
|
||||
|
||||
v1.7.1
|
||||
======
|
||||
|
||||
90
README.md
90
README.md
@@ -6,12 +6,6 @@ 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`:
|
||||
@@ -35,7 +29,7 @@ For using this collection, first you have to install both Python packages `ansib
|
||||
controller:
|
||||
|
||||
```sh
|
||||
pip install "ansible>=2.9" "openstacksdk>=1.0.0"
|
||||
pip install "ansible>=2.9" "openstacksdk>=0.36,<0.99.0"
|
||||
```
|
||||
|
||||
[OpenStack SDK][openstacksdk] has to be available on the Ansible host running the OpenStack modules. Depending on the
|
||||
@@ -70,15 +64,15 @@ ansible-galaxy collection install -r requirements.yml
|
||||
|
||||
## Usage
|
||||
|
||||
To use a module from the Ansible OpenStack collection, call them by their Fully Qualified Collection Name (FQCN),
|
||||
composed of their namespace, collection name and module name:
|
||||
To use a module from the OpenStack Cloud collection, please reference the full namespace, collection name, and module
|
||||
name that you want to use:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- hosts: localhost
|
||||
- name: Using OpenStack Cloud collection
|
||||
hosts: localhost
|
||||
tasks:
|
||||
- name: Create server in an OpenStack cloud
|
||||
openstack.cloud.server:
|
||||
- openstack.cloud.server:
|
||||
name: vm
|
||||
state: present
|
||||
cloud: openstack
|
||||
@@ -93,12 +87,12 @@ Or you can add the full namespace and collection name in the `collections` eleme
|
||||
|
||||
```yaml
|
||||
---
|
||||
- hosts: localhost
|
||||
- name: Using the Ansible OpenStack Collection
|
||||
hosts: localhost
|
||||
collections:
|
||||
- openstack.cloud
|
||||
tasks:
|
||||
- name: Create server in an OpenStack cloud
|
||||
server_volume:
|
||||
- server_volume:
|
||||
state: present
|
||||
cloud: openstack
|
||||
server: Mysql-server
|
||||
@@ -106,68 +100,6 @@ 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
|
||||
@@ -192,7 +124,6 @@ For generic resource listing use Ansible module [`openstack.cloud.resources`](pl
|
||||
```
|
||||
|
||||
[ansible-module-defaults]: https://docs.ansible.com/ansible/latest/user_guide/playbooks_module_defaults.html
|
||||
[crud]: https://en.wikipedia.org/wiki/CRUD
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -222,7 +153,8 @@ 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/) 🍪
|
||||
[OFTC IRC](https://www.oftc.net/) and ping Artem Goncharov <artem.goncharov@gmail.com> (gtema), Jakob Meng
|
||||
<mail@jakobmeng.de> (jm1) or Sagi Shnaidman <sshnaidm@redhat.com> (sshnaidm) 🍪
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -70,6 +70,21 @@ 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:
|
||||
@@ -313,268 +328,79 @@ releases:
|
||||
- lb_member - Add monitor_[address,port] parameter
|
||||
release_summary: Bugfixes
|
||||
release_date: '2022-03-08'
|
||||
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:
|
||||
1.7.2:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Change security group rules only when instructed to do so
|
||||
- 'Fix for AttributeError: ''dict'' object has no attribute ''status'''
|
||||
- Fix issue with multiple records in recordset
|
||||
- Fix mistake in compute_flavor_access notes
|
||||
- Fixed private option in inventory plugin
|
||||
- Respect description option and delete security group rules first
|
||||
- Use true and false instead of yes and no for boolean values
|
||||
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:
|
||||
- Fix collection guidelines
|
||||
release_summary: Bugfixes
|
||||
release_date: '2022-03-10'
|
||||
1.8.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Fix image module filter
|
||||
- Fix port module idempotency
|
||||
- Fix router module idempotency
|
||||
minor_changes:
|
||||
- Add volume_encryption_type modules
|
||||
- Add volume_type modules
|
||||
release_summary: New module for volume_type and bugfixes
|
||||
release_date: '2023-12-01'
|
||||
2.3.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Allow wait false when auto_ip is false
|
||||
- Fix exception when creating object from file
|
||||
- Fix exception when updating container with metadata
|
||||
- Fix typo in openstack.cloud.lb_pool
|
||||
- Fix typo in parameter description
|
||||
- fix subnet module - allow cidr option with subnet_pool
|
||||
major_changes:
|
||||
- Add Neutron trunk module
|
||||
- Add application_credential module
|
||||
- Add module to filter available volume services
|
||||
minor_changes:
|
||||
- Add inactive state for the images
|
||||
- Add insecure_registry property to coe_cluster_templates
|
||||
- Add support for creation of the default external networks
|
||||
- Add target_all_project option
|
||||
- Add vlan_tranparency for creation networks
|
||||
- Allow munch results in server_info module
|
||||
- Allow to specify multiple allocation pools when creating a subnet
|
||||
- CI - Disable auto-discovery for setuptools
|
||||
- CI - Don't create port with binding profile
|
||||
- CI - Fix CI in collection
|
||||
- CI - Fix linters-devel and devstack tests
|
||||
- CI - Fix regression in quota module
|
||||
- CI - Fix test for server shelve
|
||||
- CI - Migrate Bifrost jobs to Ubuntu Jammy
|
||||
- CI - Remove 2.9 jobs from Zuul config
|
||||
- CI - Run functional testing regardless of pep8/linter results
|
||||
- Enable glance-direct interop image import
|
||||
- Ensure coe_cluster_template compare labels properly
|
||||
- Wait for deleted server to disappear from results
|
||||
- router - Allow specifying external network name in a different project
|
||||
release_summary: Bugfixes and new modules
|
||||
- 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: Manage OpenStack Identity (Keystone) application credentials
|
||||
name: application_credential
|
||||
- description: Create or Delete subnet pools from OpenStack.
|
||||
name: subnet_pool
|
||||
namespace: ''
|
||||
- description: Add or delete trunks from an OpenStack cloud
|
||||
name: trunk
|
||||
namespace: ''
|
||||
- description: Fetch OpenStack Volume (Cinder) services
|
||||
name: volume_service_info
|
||||
namespace: ''
|
||||
release_date: '2024-11-28'
|
||||
2.3.1:
|
||||
release_date: '2022-04-08'
|
||||
1.9.0:
|
||||
changes:
|
||||
minor_changes:
|
||||
- Add ability to pass client tls certificate
|
||||
release_summary: Client TLS certificate support
|
||||
release_date: '2024-12-18'
|
||||
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'
|
||||
|
||||
@@ -6,9 +6,9 @@ ignore_other_fragment_extensions: true
|
||||
keep_fragments: false
|
||||
mention_ancestor: true
|
||||
new_plugins_after_name: removed_features
|
||||
notes_dir: fragments
|
||||
prelude_name: release_summary
|
||||
prelude_title: Release Summary
|
||||
notesdir: fragments
|
||||
prelude_section_name: release_summary
|
||||
prelude_section_title: Release Summary
|
||||
sections:
|
||||
- - major_changes
|
||||
- Major Changes
|
||||
@@ -26,6 +26,6 @@ sections:
|
||||
- Bugfixes
|
||||
- - known_issues
|
||||
- Known Issues
|
||||
title: Ansible OpenStack Collection
|
||||
title: Openstack Cloud Ansilbe modules
|
||||
trivial_section_name: trivial
|
||||
use_fqcn: true
|
||||
|
||||
0
changelogs/fragments/.keep
Normal file
0
changelogs/fragments/.keep
Normal file
@@ -2,7 +2,4 @@
|
||||
collections:
|
||||
- ansible.posix
|
||||
- ansible.utils
|
||||
- name: community.general
|
||||
version: 4.8.8
|
||||
# 5.0.0 dropped compatibility with ansible 2.9 and ansible-base 2.10
|
||||
# Ref.: https://github.com/ansible-collections/community.general/commit/1a9b3214fdf1eaccba5cc9ee210cbc5b5070fe4b
|
||||
- community.general
|
||||
|
||||
@@ -1,8 +1 @@
|
||||
address_scope_name: "address_scope"
|
||||
expected_fields:
|
||||
- id
|
||||
- ip_version
|
||||
- is_shared
|
||||
- name
|
||||
- project_id
|
||||
- tenant_id
|
||||
address_scope_name: "adrdess_scope"
|
||||
@@ -7,12 +7,6 @@
|
||||
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:
|
||||
@@ -43,4 +37,4 @@
|
||||
openstack.cloud.address_scope:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ address_scope_name }}"
|
||||
state: absent
|
||||
state: absent
|
||||
@@ -1,9 +0,0 @@
|
||||
expected_fields:
|
||||
- description
|
||||
- expires_at
|
||||
- id
|
||||
- name
|
||||
- project_id
|
||||
- roles
|
||||
- secret
|
||||
- unrestricted
|
||||
@@ -1,61 +0,0 @@
|
||||
---
|
||||
|
||||
- name: Create application credentials
|
||||
openstack.cloud.application_credential:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_creds
|
||||
description: dummy description
|
||||
register: appcred
|
||||
|
||||
- name: Assert return values of application_credential module
|
||||
assert:
|
||||
that:
|
||||
- appcred is changed
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(appcred.application_credential.keys())|length == 0
|
||||
|
||||
- name: Create the application credential again
|
||||
openstack.cloud.application_credential:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_creds
|
||||
description: dummy description
|
||||
register: appcred
|
||||
|
||||
- name: Assert return values of ansible_credential module
|
||||
assert:
|
||||
that:
|
||||
# credentials are immutable so creating twice will cause delete and create
|
||||
- appcred is changed
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(appcred.application_credential.keys())|length == 0
|
||||
|
||||
- name: Update the application credential again
|
||||
openstack.cloud.application_credential:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_creds
|
||||
description: new description
|
||||
register: appcred
|
||||
|
||||
- name: Assert application credential changed
|
||||
assert:
|
||||
that:
|
||||
- appcred is changed
|
||||
- appcred.application_credential.description == 'new description'
|
||||
|
||||
- name: Get list of all keypairs using application credential
|
||||
openstack.cloud.keypair_info:
|
||||
cloud: "{{ appcred.cloud }}"
|
||||
|
||||
- name: Delete application credential
|
||||
openstack.cloud.application_credential:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_creds
|
||||
register: appcred
|
||||
|
||||
- name: Assert application credential changed
|
||||
assert:
|
||||
that: appcred is changed
|
||||
@@ -1,2 +0,0 @@
|
||||
expected_fields:
|
||||
- auth_token
|
||||
@@ -2,10 +2,5 @@
|
||||
- name: Authenticate to the cloud
|
||||
openstack.cloud.auth:
|
||||
cloud={{ cloud }}
|
||||
register: auth
|
||||
|
||||
- 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
|
||||
- debug: var=service_catalog
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
expected_fields:
|
||||
- created_at
|
||||
- extra
|
||||
- id
|
||||
- name
|
||||
- steps
|
||||
- updated_at
|
||||
@@ -1,58 +0,0 @@
|
||||
---
|
||||
# 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 }}"
|
||||
@@ -1,56 +0,0 @@
|
||||
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
|
||||
@@ -1,15 +0,0 @@
|
||||
---
|
||||
# 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
|
||||
@@ -1,56 +0,0 @@
|
||||
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
|
||||
@@ -1,74 +0,0 @@
|
||||
---
|
||||
# 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
|
||||
@@ -1,14 +0,0 @@
|
||||
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
|
||||
@@ -1,112 +0,0 @@
|
||||
---
|
||||
# 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
|
||||
@@ -1,7 +0,0 @@
|
||||
expected_fields:
|
||||
- description
|
||||
- id
|
||||
- is_enabled
|
||||
- links
|
||||
- name
|
||||
- type
|
||||
@@ -23,8 +23,15 @@
|
||||
|
||||
- name: Verify returned values
|
||||
assert:
|
||||
that: item in service_test.service
|
||||
loop: "{{ expected_fields }}"
|
||||
that:
|
||||
- item in service_test.service
|
||||
loop:
|
||||
- description
|
||||
- id
|
||||
- enabled
|
||||
- name
|
||||
- service_type
|
||||
- type
|
||||
|
||||
- name: Check if the service test was created successfully
|
||||
openstack.cloud.catalog_service:
|
||||
@@ -35,8 +42,15 @@
|
||||
|
||||
- name: Verify returned values
|
||||
assert:
|
||||
that: item in service_created.service
|
||||
loop: "{{ expected_fields }}"
|
||||
that:
|
||||
- item in service_created.service
|
||||
loop:
|
||||
- description
|
||||
- id
|
||||
- enabled
|
||||
- name
|
||||
- type
|
||||
- service_type
|
||||
|
||||
- name: Update service test
|
||||
openstack.cloud.catalog_service:
|
||||
@@ -47,34 +61,11 @@
|
||||
name: test
|
||||
register: service_test
|
||||
|
||||
- name: Check if description and is_enabled were updated
|
||||
- name: Check if description and enabled were updated
|
||||
assert:
|
||||
that:
|
||||
- service_test.service.description == "A new description"
|
||||
- not (service_test.service.is_enabled|bool)
|
||||
|
||||
- name: Get all services
|
||||
openstack.cloud.catalog_service_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: services
|
||||
|
||||
- name: Assert return values of catalog_service_info module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(services.services[0].keys())|length == 0
|
||||
|
||||
- name: Get service by name
|
||||
openstack.cloud.catalog_service_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: test
|
||||
register: services
|
||||
|
||||
- name: Assert services returned by catalog_service_info module
|
||||
assert:
|
||||
that:
|
||||
- services.services|length == 1
|
||||
- services.services[0].id == service_test.service.id
|
||||
- not (service_test.service.enabled|bool)
|
||||
|
||||
- name: Delete service test
|
||||
openstack.cloud.catalog_service:
|
||||
|
||||
7
ci/roles/client_config/tasks/main.yml
Normal file
7
ci/roles/client_config/tasks/main.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
- name: List all profiles
|
||||
openstack.cloud.config:
|
||||
register: list
|
||||
|
||||
# WARNING: This will output sensitive authentication information!!!!
|
||||
- debug: var=list
|
||||
@@ -1,26 +1,18 @@
|
||||
expected_fields:
|
||||
- api_address
|
||||
# Magnum might return more fields according to its documentation [0] but
|
||||
# openstacksdk normalizes coe cluster resources, moving most fields from
|
||||
# top level into a 'properties' field [1].
|
||||
# [0] https://docs.openstack.org/api-ref/container-infrastructure-management/#create-new-cluster
|
||||
# [1] https://opendev.org/openstack/openstacksdk/src/commit/d57c1fcab3b6cbe806cbae735fefa4983b200ab2/openstack/cloud/_normalize.py#L484
|
||||
- cluster_template_id
|
||||
- coe_version
|
||||
- create_timeout
|
||||
- created_at
|
||||
- discovery_url
|
||||
- fixed_network
|
||||
- fixed_subnet
|
||||
- flavor_id
|
||||
- id
|
||||
- is_floating_ip_enabled
|
||||
- is_master_lb_enabled
|
||||
- keypair
|
||||
- labels
|
||||
- master_addresses
|
||||
- location
|
||||
- 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:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(coe_cluster.cluster.keys())|length == 0
|
||||
# openstack.cloud.coe_cluster will only return 'id' on cluster creation when wait is false
|
||||
- "['id']|difference(coe_cluster.cluster.keys())|length == 0"
|
||||
|
||||
- name: Pause for 1 minutes to allow Magnum to create the Kubernetes cluster
|
||||
ansible.builtin.pause:
|
||||
|
||||
@@ -1,33 +1,40 @@
|
||||
expected_fields:
|
||||
# Magnum might return more fields according to its documentation [0] but
|
||||
# openstacksdk normalizes coe cluster template resources, moving most
|
||||
# fields from top level into a 'properties' field [1].
|
||||
# [0] https://docs.openstack.org/api-ref/container-infrastructure-management/#create-new-cluster
|
||||
# [1] https://opendev.org/openstack/openstacksdk/src/commit/d57c1fcab3b6cbe806cbae735fefa4983b200ab2/openstack/cloud/_normalize.py#L522
|
||||
- apiserver_port
|
||||
- cluster_distro
|
||||
- coe
|
||||
- created_at
|
||||
- dns_nameserver
|
||||
- docker_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,14 +21,11 @@
|
||||
openstack.cloud.coe_cluster_template:
|
||||
cloud: "{{ cloud }}"
|
||||
coe: kubernetes
|
||||
is_floating_ip_enabled: false
|
||||
floating_ip_enabled: false
|
||||
image_id: '{{ image_id }}'
|
||||
keypair_id: '{{ keypair.keypair.id }}'
|
||||
name: k8s
|
||||
state: present
|
||||
labels:
|
||||
docker_volume_size: 10
|
||||
cloud_provider_tag: v1.23.1
|
||||
register: coe_cluster_template
|
||||
|
||||
- name: Assert return values of coe_cluster_template module
|
||||
@@ -41,14 +38,11 @@
|
||||
openstack.cloud.coe_cluster_template:
|
||||
cloud: "{{ cloud }}"
|
||||
coe: kubernetes
|
||||
is_floating_ip_enabled: false
|
||||
floating_ip_enabled: false
|
||||
image_id: '{{ image_id }}'
|
||||
keypair_id: '{{ keypair.keypair.id }}'
|
||||
name: k8s
|
||||
state: present
|
||||
labels:
|
||||
docker_volume_size: 10
|
||||
cloud_provider_tag: v1.23.1
|
||||
register: coe_cluster_template
|
||||
|
||||
- name: Assert return values of coe_cluster_template module
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
expected_fields:
|
||||
- description
|
||||
- disk
|
||||
- ephemeral
|
||||
- extra_specs
|
||||
- id
|
||||
- is_disabled
|
||||
- is_public
|
||||
- name
|
||||
- original_name
|
||||
- ram
|
||||
- rxtx_factor
|
||||
- swap
|
||||
- vcpus
|
||||
@@ -1,254 +0,0 @@
|
||||
---
|
||||
- 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"
|
||||
@@ -1,96 +0,0 @@
|
||||
---
|
||||
- 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
|
||||
33
ci/roles/compute_flavor_info/tasks/main.yml
Normal file
33
ci/roles/compute_flavor_info/tasks/main.yml
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
- name: List flavors
|
||||
openstack.cloud.compute_flavor_info:
|
||||
cloud: "{{ cloud }}"
|
||||
|
||||
- name: List flavors with filter
|
||||
openstack.cloud.compute_flavor_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "m1.tiny"
|
||||
register: flavor
|
||||
|
||||
- name: Check output of list flavors with filter
|
||||
assert:
|
||||
that:
|
||||
- flavor.openstack_flavors | length == 1
|
||||
|
||||
- name: Assert fields on SDK 0.*
|
||||
when: sdk_version is version(1.0, '<')
|
||||
assert:
|
||||
that:
|
||||
- '["name", "description", "disk", "is_public", "ram",
|
||||
"vcpus", "swap", "ephemeral", "is_disabled", "rxtx_factor", "id",
|
||||
"extra_specs"] | difference(flavor.openstack_flavors.0.keys())
|
||||
| length == 0'
|
||||
|
||||
- name: Assert fields on SDK 1.*
|
||||
when: sdk_version is version(1.0, '>=')
|
||||
assert:
|
||||
that:
|
||||
- '["name", "original_name", "description", "disk", "is_public", "ram",
|
||||
"vcpus", "swap", "ephemeral", "is_disabled", "rxtx_factor", "id",
|
||||
"extra_specs"] | difference(flavor.openstack_flavors.0.keys())
|
||||
| length == 0'
|
||||
@@ -1,11 +0,0 @@
|
||||
expected_fields:
|
||||
- availability_zone
|
||||
- binary
|
||||
- disabled_reason
|
||||
- host
|
||||
- id
|
||||
- is_forced_down
|
||||
- name
|
||||
- state
|
||||
- status
|
||||
- updated_at
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
- 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
|
||||
@@ -1,10 +0,0 @@
|
||||
---
|
||||
- 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)
|
||||
4
ci/roles/dns/defaults/main.yml
Normal file
4
ci/roles/dns/defaults/main.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
dns_zone_name: test.dns.zone.
|
||||
recordset_name: testrecordset.test.dns.zone.
|
||||
records: ['10.0.0.0']
|
||||
updated_records: ['10.1.1.1']
|
||||
32
ci/roles/dns/tasks/main.yml
Normal file
32
ci/roles/dns/tasks/main.yml
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
- name: Create dns zone
|
||||
openstack.cloud.dns_zone:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ dns_zone_name }}"
|
||||
zone_type: "primary"
|
||||
email: test@example.net
|
||||
register: dns_zone
|
||||
|
||||
- debug: var=dns_zone
|
||||
|
||||
- name: Update dns zone
|
||||
openstack.cloud.dns_zone:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ dns_zone.zone.name }}"
|
||||
description: "New descirption"
|
||||
register: updated_dns_zone
|
||||
|
||||
- debug: var=updated_dns_zone
|
||||
|
||||
- name: Delete dns zone
|
||||
openstack.cloud.dns_zone:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ updated_dns_zone.zone.name }}"
|
||||
state: absent
|
||||
register: deleted_dns_zone
|
||||
|
||||
- name: Verify dns zone
|
||||
assert:
|
||||
that:
|
||||
- deleted_dns_zone is successful
|
||||
- deleted_dns_zone is changed
|
||||
@@ -1,17 +0,0 @@
|
||||
expected_fields:
|
||||
- action
|
||||
- attributes
|
||||
- created_at
|
||||
- description
|
||||
- email
|
||||
- id
|
||||
- links
|
||||
- masters
|
||||
- name
|
||||
- pool_id
|
||||
- project_id
|
||||
- serial
|
||||
- status
|
||||
- ttl
|
||||
- type
|
||||
- updated_at
|
||||
@@ -1,67 +0,0 @@
|
||||
---
|
||||
- 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
|
||||
49
ci/roles/dns_zone_info/tasks/main.yml
Normal file
49
ci/roles/dns_zone_info/tasks/main.yml
Normal file
@@ -0,0 +1,49 @@
|
||||
---
|
||||
- name: Set random prefix
|
||||
set_fact:
|
||||
prefix: "{{ 99999999 | random | to_uuid | hash('md5') }}"
|
||||
|
||||
- name: Create dns zone
|
||||
openstack.cloud.dns_zone:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ (prefix + '.test.zone.') }}"
|
||||
email: test@example.net
|
||||
|
||||
- name: Getting info about dns zones
|
||||
openstack.cloud.dns_zone_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: zones
|
||||
|
||||
- name: assert result
|
||||
assert:
|
||||
that:
|
||||
- zones is success
|
||||
- zones is not changed
|
||||
- zones | length > 0
|
||||
|
||||
- name: Getting info about created zone
|
||||
openstack.cloud.dns_zone_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ (prefix + '.test.zone.') }}"
|
||||
register: zone
|
||||
|
||||
- name: assert result
|
||||
assert:
|
||||
that:
|
||||
- zone is success
|
||||
- zone is not changed
|
||||
- zone.zones | length == 1
|
||||
|
||||
- name: Assert keys exist
|
||||
assert:
|
||||
that:
|
||||
- '["action", "attributes", "created_at", "description", "email",
|
||||
"links", "masters", "name", "pool_id", "project_id", "serial",
|
||||
"status", "ttl", "type", "updated_at", "id"] |
|
||||
difference(zone.zones.0.keys()) | length == 0'
|
||||
|
||||
- name: Drop created dns zone
|
||||
openstack.cloud.dns_zone:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ (prefix + '.test.zone.') }}"
|
||||
state: absent
|
||||
@@ -1,9 +0,0 @@
|
||||
expected_fields:
|
||||
- id
|
||||
- interface
|
||||
- is_enabled
|
||||
- links
|
||||
- name
|
||||
- region_id
|
||||
- service_id
|
||||
- url
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
- name: Create a service endpoint for compute
|
||||
- name: Create a service for compute
|
||||
openstack.cloud.endpoint:
|
||||
cloud: "{{ cloud }}"
|
||||
service: nova
|
||||
@@ -9,20 +9,17 @@
|
||||
state: present
|
||||
register: endpoint_test
|
||||
|
||||
- debug: var=endpoint_test
|
||||
|
||||
- name: Assert return values of endpoint module
|
||||
- name: Ensure service was created
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(endpoint_test.endpoint.keys())|length == 0
|
||||
- endpoint_test.endpoint.id is defined
|
||||
|
||||
- name: Ensure service have the proper endpoint
|
||||
assert:
|
||||
that:
|
||||
- endpoint_test.endpoint.url == "http://controller:9292"
|
||||
|
||||
- name: Create service endpoint for compute again
|
||||
- name: Create service for compute again
|
||||
openstack.cloud.endpoint:
|
||||
cloud: "{{ cloud }}"
|
||||
service: nova
|
||||
@@ -37,7 +34,7 @@
|
||||
that:
|
||||
- not endpoint_again.changed
|
||||
|
||||
- name: Update service endpoint url
|
||||
- name: Update endpoint url
|
||||
openstack.cloud.endpoint:
|
||||
cloud: "{{ cloud }}"
|
||||
service: nova
|
||||
@@ -47,12 +44,12 @@
|
||||
state: present
|
||||
register: endpoint_updated
|
||||
|
||||
- name: Ensure service endpoint was updated
|
||||
- name: Ensure endpoint was updated
|
||||
assert:
|
||||
that:
|
||||
- endpoint_updated.endpoint.url == "http://controller:9393"
|
||||
|
||||
- name: Delete service endpoint
|
||||
- name: Delete endpoint
|
||||
openstack.cloud.endpoint:
|
||||
cloud: "{{ cloud }}"
|
||||
service: nova
|
||||
@@ -62,7 +59,7 @@
|
||||
state: absent
|
||||
register: endpoint_deleted
|
||||
|
||||
- name: Ensure service endpoint was deleted
|
||||
- name: Ensure endpoint was deleted
|
||||
assert:
|
||||
that:
|
||||
- endpoint_deleted.changed
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
---
|
||||
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,4 +1,5 @@
|
||||
---
|
||||
# Prepare environment
|
||||
- name: List all images
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
@@ -6,7 +7,7 @@
|
||||
|
||||
- name: Identify CirrOS image name
|
||||
set_fact:
|
||||
image_name: "{{ images.images|community.general.json_query(query)|first }}"
|
||||
image_name: "{{ images.openstack_images|community.general.json_query(query)|first }}"
|
||||
vars:
|
||||
query: "[?starts_with(name, 'cirros')].name"
|
||||
|
||||
@@ -18,122 +19,119 @@
|
||||
|
||||
- name: Assert that public network exists
|
||||
assert:
|
||||
that: public_network.networks|length == 1
|
||||
that: public_network.openstack_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
|
||||
register: port1
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_internal_port1
|
||||
network: ansible_internal
|
||||
fixed_ips:
|
||||
- ip_address: 10.7.7.100
|
||||
|
||||
- name: Create internal port 2
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_internal_port2
|
||||
network: ansible_internal
|
||||
fixed_ips:
|
||||
- ip_address: 10.7.7.101
|
||||
register: port2
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_internal_port2
|
||||
network: ansible_internal
|
||||
fixed_ips:
|
||||
- ip_address: 10.7.7.101
|
||||
|
||||
- name: Create internal port 3
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_internal_port3
|
||||
network: ansible_internal
|
||||
fixed_ips:
|
||||
- ip_address: 10.7.7.102
|
||||
register: port3
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_internal_port3
|
||||
network: ansible_internal
|
||||
fixed_ips:
|
||||
- ip_address: 10.7.7.102
|
||||
|
||||
- name: Create router 1
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_router1
|
||||
network: ansible_external
|
||||
external_fixed_ips:
|
||||
- subnet: ansible_external_subnet
|
||||
ip: 10.6.6.10
|
||||
interfaces:
|
||||
- net: ansible_internal
|
||||
subnet: ansible_internal_subnet
|
||||
portip: 10.7.7.1
|
||||
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.networks.0.id)|
|
||||
selectattr('floating_network_id', '==', public_network.openstack_networks.0.id)|
|
||||
list|length > 0 }}"
|
||||
|
||||
# TODO: Replace with appropriate Ansible module once available
|
||||
@@ -151,286 +149,232 @@
|
||||
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 1 with one nic
|
||||
- name: Create server with one nic
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_server1
|
||||
image: "{{ image_name }}"
|
||||
flavor: m1.tiny
|
||||
nics:
|
||||
# one nic only else simple, first floating ip test does not work
|
||||
- port-name: ansible_internal_port1
|
||||
auto_ip: false
|
||||
wait: true
|
||||
register: server1
|
||||
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 server 1 ports
|
||||
openstack.cloud.port_info:
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
filters:
|
||||
device_id: "{{ server1.server.id }}"
|
||||
register: server1_ports
|
||||
server: ansible_server1
|
||||
register: info
|
||||
|
||||
- name: Assert one fixed ip on server 1
|
||||
- name: Assert one internal port and no floating ips on server 1
|
||||
# If this assertion fails because server has an public ipv4 address (public_v4) then make sure
|
||||
# that no floating ip on public network is associated with "10.7.7.100" before running this role
|
||||
assert:
|
||||
that:
|
||||
- server1_ports.ports|length == 1
|
||||
- server1_ports.ports|sum(attribute='fixed_ips', start=[])|map(attribute='ip_address')|sort|list ==
|
||||
["10.7.7.100"]
|
||||
- info.openstack_servers|length == 1
|
||||
- info.openstack_servers.0.public_v4|length == 0
|
||||
- info.openstack_servers.0.public_v6|length == 0
|
||||
- info.openstack_servers.0.addresses.ansible_internal|length == 1
|
||||
- info.openstack_servers.0.addresses.ansible_internal|map(attribute="addr")|sort|list == ["10.7.7.100"]
|
||||
|
||||
- name: Create server 2 with two nics
|
||||
- name: Create server with two nics
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_server2
|
||||
image: "{{ image_name }}"
|
||||
flavor: m1.tiny
|
||||
nics:
|
||||
- port-name: ansible_internal_port2
|
||||
- port-name: ansible_internal_port3
|
||||
auto_ip: false
|
||||
wait: true
|
||||
register: server2
|
||||
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 server 2 ports
|
||||
openstack.cloud.port_info:
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
filters:
|
||||
device_id: "{{ server2.server.id }}"
|
||||
register: server2_ports
|
||||
server: ansible_server2
|
||||
register: info
|
||||
|
||||
- name: Assert two fixed ips on server 2
|
||||
- name: Assert two internal ports and no floating ips on server 2
|
||||
assert:
|
||||
that:
|
||||
- server2_ports.ports|length == 2
|
||||
- server2_ports.ports|sum(attribute='fixed_ips', start=[])|map(attribute='ip_address')|sort|list ==
|
||||
- info.openstack_servers|length == 1
|
||||
- info.openstack_servers.0.public_v4|length == 0
|
||||
- info.openstack_servers.0.public_v6|length == 0
|
||||
- info.openstack_servers.0.addresses.ansible_internal|length == 2
|
||||
- info.openstack_servers.0.addresses.ansible_internal|map(attribute="addr")|sort|list ==
|
||||
["10.7.7.101", "10.7.7.102"]
|
||||
|
||||
# Tests
|
||||
- name: Assign new floating IP to server from first available external network or nova pool
|
||||
openstack.cloud.floating_ip:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
server: ansible_server1
|
||||
wait: true
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
server: ansible_server1
|
||||
wait: true
|
||||
|
||||
- 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:
|
||||
- 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: 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: present
|
||||
server: ansible_server1
|
||||
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: server1_fips.floating_ips|length == 0
|
||||
|
||||
- name: Find all floating ips for debugging
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: fips
|
||||
|
||||
- name: Print all floating ips for debugging
|
||||
debug: var=fips
|
||||
|
||||
- name: Find all servers for debugging
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: servers
|
||||
server: ansible_server1
|
||||
register: info
|
||||
|
||||
- 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
|
||||
- name: Assert one internal port and one floating ip on server 1
|
||||
assert:
|
||||
that:
|
||||
- server2_fip.floating_ip
|
||||
- info.openstack_servers.0.addresses.ansible_internal|length == 2
|
||||
- info.openstack_servers.0.addresses.ansible_internal|map(attribute="OS-EXT-IPS:type")|sort|list ==
|
||||
["fixed", "floating"]
|
||||
|
||||
- name: Find all floating ips for debugging
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: fips
|
||||
- name: Detach floating IP from server
|
||||
openstack.cloud.floating_ip:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
server: ansible_server1
|
||||
network: public
|
||||
floating_ip_address: "{{ (info.openstack_servers.0.addresses.ansible_internal|
|
||||
selectattr('OS-EXT-IPS:type', '==', 'floating')|map(attribute='addr')|list)[0] }}"
|
||||
|
||||
- name: Print all floating ips for debugging
|
||||
debug: var=fips
|
||||
|
||||
- name: Find all servers for debugging
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: servers
|
||||
server: ansible_server1
|
||||
register: info
|
||||
# When detaching a floating ip from an instance there might be a delay until openstack.cloud.server_info
|
||||
# does not list it any more in info.openstack_servers.0.addresses.ansible_internal, so retry if necessary.
|
||||
retries: 10
|
||||
delay: 3
|
||||
until: info.openstack_servers.0.addresses.ansible_internal|length == 1
|
||||
|
||||
- name: 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
|
||||
- name: Assert one internal port on server 1
|
||||
assert:
|
||||
that:
|
||||
- server2_fips.floating_ips|length == 1
|
||||
- server2_fips.floating_ips|map(attribute='fixed_ip_address')|sort|list ==
|
||||
["10.7.7.101"]
|
||||
- info.openstack_servers.0.addresses.ansible_internal|length == 1
|
||||
- info.openstack_servers.0.addresses.ansible_internal|map(attribute="addr")|list == ["10.7.7.100"]
|
||||
|
||||
- name: Assign a second, specific floating ip to server 2
|
||||
- name: Assign floating IP to server
|
||||
openstack.cloud.floating_ip:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
reuse: yes
|
||||
server: ansible_server2
|
||||
network: public
|
||||
fixed_address: 10.7.7.101
|
||||
wait: true
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
reuse: false # else fixed_address will be ignored
|
||||
server: ansible_server2
|
||||
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
|
||||
register: info
|
||||
|
||||
- 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: server2_fips.floating_ips|length == 1
|
||||
|
||||
- name: Assert second floating ip attached to server 2
|
||||
- name: Assert two internal ports and one floating ip on server 2
|
||||
assert:
|
||||
that:
|
||||
- server2_fips.floating_ips|length == 1
|
||||
- server2_fips.floating_ips|map(attribute='fixed_ip_address')|sort|list ==
|
||||
["10.7.7.102"]
|
||||
- info.openstack_servers.0.addresses.ansible_internal|length == 3
|
||||
- info.openstack_servers.0.addresses.ansible_internal|map(attribute="OS-EXT-IPS:type")|sort|list ==
|
||||
["fixed", "fixed", "floating"]
|
||||
|
||||
- name: Detach second floating ip from server 2
|
||||
- name: Assign a second, specific floating IP to server
|
||||
openstack.cloud.floating_ip:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
server: ansible_server2
|
||||
network: ansible_external
|
||||
floating_ip_address: "10.6.6.150"
|
||||
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: Wait until second floating ip is detached from server 2
|
||||
openstack.cloud.floating_ip_info:
|
||||
# We cannot wait for second floating ip to be attached because OpenStackSDK checks only for first floating ip
|
||||
# Ref.: https://github.com/openstack/openstacksdk/blob/e0372b72af8c5f471fc17e53434d7a814ca958bd/openstack/cloud/_floating_ip.py#L733
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
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
|
||||
server: ansible_server2
|
||||
register: info
|
||||
# retry because we cannot wait for second floating ip
|
||||
retries: 10
|
||||
delay: 3
|
||||
until: server2_fips.floating_ips|length == 0
|
||||
until: info.openstack_servers.0.addresses.ansible_internal|length == 4
|
||||
|
||||
- name: Get first floating ip attached to server 2
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
port: "{{ port2.port.id }}"
|
||||
register: server2_fips
|
||||
- name: Assert two internal ports and two floating ips on server 2
|
||||
assert:
|
||||
that:
|
||||
- info.openstack_servers.0.addresses.ansible_internal|length == 4
|
||||
- ("10.6.6.150" in info.openstack_servers.0.addresses.ansible_internal|map(attribute="addr")|sort|list)
|
||||
|
||||
- name: Detach remaining floating ip from server 2
|
||||
- name: Detach second floating IP from server
|
||||
openstack.cloud.floating_ip:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
server: ansible_server2
|
||||
network: public
|
||||
floating_ip_address: "{{ server2_fips.floating_ips.0.floating_ip_address }}"
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
server: ansible_server2
|
||||
network: ansible_external
|
||||
floating_ip_address: "10.6.6.150"
|
||||
|
||||
- name: Wait until first floating ip is detached from server 2
|
||||
openstack.cloud.floating_ip_info:
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_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
|
||||
server: ansible_server2
|
||||
register: info
|
||||
# When detaching a floating ip from an instance there might be a delay until openstack.cloud.server_info
|
||||
# does not list it any more in info.openstack_servers.0.addresses.ansible_internal, so retry if necessary.
|
||||
retries: 10
|
||||
delay: 3
|
||||
until: server2_fips.floating_ips|length == 0
|
||||
until: info.openstack_servers.0.addresses.ansible_internal|length == 3
|
||||
|
||||
- name: Assert two internal ports and one floating ip on server 2
|
||||
assert:
|
||||
that:
|
||||
- info.openstack_servers.0.addresses.ansible_internal|length == 3
|
||||
|
||||
- name: Detach remaining floating IP from server
|
||||
openstack.cloud.floating_ip:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
server: ansible_server2
|
||||
network: public
|
||||
floating_ip_address: "{{ (info.openstack_servers.0.addresses.ansible_internal|
|
||||
selectattr('OS-EXT-IPS:type', '==', 'floating')|map(attribute='addr')|list)[0] }}"
|
||||
|
||||
- name: Get info about server
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
server: ansible_server2
|
||||
register: info
|
||||
# When detaching a floating ip from an instance there might be a delay until openstack.cloud.server_info
|
||||
# does not list it any more in info.openstack_servers.0.addresses.ansible_internal, so retry if necessary.
|
||||
retries: 10
|
||||
delay: 3
|
||||
until: info.openstack_servers.0.addresses.ansible_internal|length == 2
|
||||
|
||||
- name: Assert two internal ports on server 2
|
||||
assert:
|
||||
that:
|
||||
- info.openstack_servers.0.addresses.ansible_internal|length == 2
|
||||
- info.openstack_servers.0.addresses.ansible_internal|map(attribute="addr")|list == ["10.7.7.101", "10.7.7.102"]
|
||||
|
||||
# Clean environment
|
||||
- name: Delete server with two nics
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_server2
|
||||
wait: true
|
||||
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
|
||||
@@ -438,7 +382,7 @@
|
||||
when: not public_network_had_fips
|
||||
command: >
|
||||
openstack --os-cloud={{ cloud }} floating ip delete
|
||||
{{ fips.floating_ips|selectattr('floating_network_id', '==', public_network.networks.0.id)|
|
||||
{{ fips.floating_ips|selectattr('floating_network_id', '==', public_network.openstack_networks.0.id)|
|
||||
map(attribute="floating_ip_address")|list|join(' ') }}
|
||||
|
||||
# TODO: Replace with appropriate Ansible module once available
|
||||
@@ -448,8 +392,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
|
||||
@@ -463,71 +407,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
|
||||
|
||||
21
ci/roles/floating_ip_info/tasks/main.yml
Normal file
21
ci/roles/floating_ip_info/tasks/main.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
- name: Getting info about allocated ips
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: fips
|
||||
|
||||
- name: assert result
|
||||
assert:
|
||||
that:
|
||||
- fips is success
|
||||
- fips is not changed
|
||||
|
||||
- name: assert fields
|
||||
when: fips.floating_ips|length > 0
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- '["created_at", "description", "dns_domain", "dns_name", "fixed_ip_address", "floating_ip_address",
|
||||
"floating_network_id", "id", "name", "port_details", "port_id", "project_id", "qos_policy_id",
|
||||
"revision_number", "router_id", "status", "subnet_id", "tags", "updated_at"]|
|
||||
difference(fips.floating_ips.0.keys())|length == 0'
|
||||
1
ci/roles/group/defaults/main.yml
Normal file
1
ci/roles/group/defaults/main.yml
Normal file
@@ -0,0 +1 @@
|
||||
group_name: ansible_group
|
||||
19
ci/roles/group/tasks/main.yml
Normal file
19
ci/roles/group/tasks/main.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
- 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 }}"
|
||||
@@ -1,68 +0,0 @@
|
||||
---
|
||||
- name: Create user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
password: secret
|
||||
email: ansible.user@nowhere.net
|
||||
domain: default
|
||||
default_project: demo
|
||||
|
||||
- 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,11 +1,10 @@
|
||||
# Parameter deleted has been renamed to is_deleted in openstacksdk 0.52.0,
|
||||
# hence we cannot test with this list here.
|
||||
# Ref.: https://github.com/openstack/openstacksdk/commit/b60915aab3ee0348f3e3cc8aa548f94d2a68b7eb
|
||||
expected_fields:
|
||||
- availability_zone
|
||||
- created_at
|
||||
- deleted_at
|
||||
- hosts
|
||||
- id
|
||||
- is_deleted
|
||||
- location
|
||||
- metadata
|
||||
- name
|
||||
- updated_at
|
||||
- uuid
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
expected_fields:
|
||||
- description
|
||||
- id
|
||||
- is_enabled
|
||||
- name
|
||||
- links
|
||||
@@ -1,123 +0,0 @@
|
||||
---
|
||||
- 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
|
||||
8
ci/roles/identity_domain_info/defaults/main.yml
Normal file
8
ci/roles/identity_domain_info/defaults/main.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
domain_name: domain_info_test_domain
|
||||
unexistent_domain_name: domain_info_unexistent_domain
|
||||
disabled_domain_name: test_domain_disabled
|
||||
domain_info_fields:
|
||||
- description
|
||||
- id
|
||||
- enabled
|
||||
- name
|
||||
72
ci/roles/identity_domain_info/tasks/main.yml
Normal file
72
ci/roles/identity_domain_info/tasks/main.yml
Normal file
@@ -0,0 +1,72 @@
|
||||
---
|
||||
- block:
|
||||
- name: Ensure domain does not exist
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ unexistent_domain_name }}"
|
||||
- name: Get unexistent domain
|
||||
openstack.cloud.identity_domain_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ unexistent_domain_name }}"
|
||||
register: domain_info
|
||||
- name: Assert no results returned
|
||||
assert:
|
||||
that: not domain_info.openstack_domains
|
||||
|
||||
|
||||
- block:
|
||||
- name: Ensure domain exists
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ domain_name }}"
|
||||
description: "test description"
|
||||
register: domain
|
||||
- name: Get domain
|
||||
openstack.cloud.identity_domain_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ domain_name }}"
|
||||
register: domain_info
|
||||
- name: Assert one result exists
|
||||
assert:
|
||||
that: domain_info.openstack_domains | length == 1
|
||||
- name: Assert fields are present
|
||||
assert:
|
||||
that: item in domain_info.openstack_domains[0]
|
||||
loop: "{{ domain_info_fields }}"
|
||||
- name: Assert returned value
|
||||
assert:
|
||||
that:
|
||||
- domain_info.openstack_domains[0].description == domain.domain.description
|
||||
|
||||
- block:
|
||||
- name: Get all domains
|
||||
openstack.cloud.identity_domain_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: domain_info
|
||||
|
||||
- block:
|
||||
- name: Ensure disabled domain exists
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ disabled_domain_name }}"
|
||||
enabled: false
|
||||
description: "test description"
|
||||
register: domain
|
||||
- name: Get filtered domains
|
||||
openstack.cloud.identity_domain_info:
|
||||
cloud: "{{ cloud }}"
|
||||
filters:
|
||||
enabled: true
|
||||
register: domain_info
|
||||
- name: Assert at least one result
|
||||
assert:
|
||||
that: domain_info.openstack_domains | length >= 1
|
||||
- name: Assert returned value
|
||||
assert:
|
||||
that: item.enabled == true
|
||||
loop: "{{ domain_info.openstack_domains }}"
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
expected_fields:
|
||||
- description
|
||||
- domain_id
|
||||
- id
|
||||
- name
|
||||
@@ -1,220 +0,0 @@
|
||||
---
|
||||
- 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
|
||||
74
ci/roles/identity_group_info/tasks/main.yml
Normal file
74
ci/roles/identity_group_info/tasks/main.yml
Normal file
@@ -0,0 +1,74 @@
|
||||
---
|
||||
- name: List group by domain_id
|
||||
openstack.cloud.identity_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
domain: default
|
||||
register: group_domain
|
||||
|
||||
- name: Assert groups were returned
|
||||
assert:
|
||||
that:
|
||||
- group_domain.openstack_groups | length > 0
|
||||
- group_domain.openstack_groups[0].domain_id == 'default'
|
||||
- group_domain.openstack_groups[0].id is defined
|
||||
- group_domain.openstack_groups[0].description is defined
|
||||
- group_domain.openstack_groups[0].name is defined
|
||||
|
||||
- name: List group by domain_id and group
|
||||
openstack.cloud.identity_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
domain: default
|
||||
name: admins
|
||||
register: groups_info
|
||||
|
||||
- name: Assert groups by domain_id and grouph returned
|
||||
assert:
|
||||
that:
|
||||
- groups_info.openstack_groups | length > 0
|
||||
- groups_info.openstack_groups[0].domain_id == 'default'
|
||||
- groups_info.openstack_groups[0].id is defined
|
||||
- groups_info.openstack_groups[0].description is defined
|
||||
- groups_info.openstack_groups[0].name is defined
|
||||
|
||||
- name: List group by filter
|
||||
openstack.cloud.identity_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
domain: default
|
||||
filters:
|
||||
name: admins
|
||||
register: groups_filter
|
||||
|
||||
- name: Assert group by filter returned
|
||||
assert:
|
||||
that:
|
||||
- groups_filter.openstack_groups | length > 0
|
||||
- groups_filter.openstack_groups[0].domain_id == 'default'
|
||||
- groups_filter.openstack_groups[0].id is defined
|
||||
- groups_filter.openstack_groups[0].description is defined
|
||||
- groups_filter.openstack_groups[0].name is defined
|
||||
|
||||
- name: Verify returned values of group info
|
||||
assert:
|
||||
that:
|
||||
- item in groups_info.openstack_groups[0]
|
||||
loop:
|
||||
- description
|
||||
- domain_id
|
||||
- id
|
||||
- name
|
||||
|
||||
- name: List group by group name
|
||||
openstack.cloud.identity_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: admins
|
||||
register: groups_name
|
||||
|
||||
- name: Assert group by name returned
|
||||
assert:
|
||||
that:
|
||||
- groups_name.openstack_groups | length > 0
|
||||
- groups_name.openstack_groups[0].domain_id == 'default'
|
||||
- groups_name.openstack_groups[0].id is defined
|
||||
- groups_name.openstack_groups[0].description is defined
|
||||
- groups_name.openstack_groups[0].name is defined
|
||||
- groups_name.openstack_groups[0].name == 'admins'
|
||||
@@ -1,6 +1,5 @@
|
||||
role_name: ansible_keystone_role
|
||||
expected_fields:
|
||||
- description
|
||||
- domain_id
|
||||
- id
|
||||
- links
|
||||
- name
|
||||
|
||||
@@ -1,88 +1,83 @@
|
||||
---
|
||||
- name: Create identity role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_role
|
||||
description: "ansible role"
|
||||
register: role
|
||||
- name: Cleanup before tests
|
||||
block:
|
||||
- openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ role_name }}"
|
||||
|
||||
- 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: 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: Try to get role
|
||||
openstack.cloud.identity_role_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_role
|
||||
register: roles
|
||||
- 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: Assert role found
|
||||
assert:
|
||||
that:
|
||||
- roles.roles | length == 1
|
||||
- roles.roles.0.name == 'ansible_role'
|
||||
- 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: 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
|
||||
- block:
|
||||
- name: Delete keystone role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ role_name }}"
|
||||
register: role
|
||||
- name: Assert role changed
|
||||
assert:
|
||||
that: role is changed
|
||||
- name: Try to get role
|
||||
openstack.cloud.identity_role_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ role_name }}"
|
||||
register: roles
|
||||
- name: Assert no role found
|
||||
assert:
|
||||
that:
|
||||
- roles.openstack_roles | length == 0
|
||||
|
||||
62
ci/roles/identity_role_info/tasks/main.yml
Normal file
62
ci/roles/identity_role_info/tasks/main.yml
Normal file
@@ -0,0 +1,62 @@
|
||||
- name: Ensure role does not exist before tests
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: test_role
|
||||
|
||||
- name: Get unexistent role
|
||||
openstack.cloud.identity_role_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: test_role
|
||||
register: roleinfo
|
||||
|
||||
- debug:
|
||||
var: roleinfo
|
||||
|
||||
- name: Assert that no results were returned
|
||||
assert:
|
||||
that: not roleinfo.openstack_roles
|
||||
|
||||
- name: Create keystone role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: test_role
|
||||
|
||||
- name: Create second role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: test_role2
|
||||
|
||||
- name: Get role by name
|
||||
openstack.cloud.identity_role_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: test_role
|
||||
register: roleinfo
|
||||
|
||||
- debug:
|
||||
var: roleinfo
|
||||
|
||||
- name: Assert that only one result was returned
|
||||
assert:
|
||||
that: roleinfo.openstack_roles | length == 1
|
||||
|
||||
- name: Assert that roleinfo has fields
|
||||
assert:
|
||||
that: item in roleinfo.openstack_roles[0]
|
||||
loop:
|
||||
- domain_id
|
||||
- id
|
||||
- name
|
||||
|
||||
- name: Post-test cleanup
|
||||
block:
|
||||
- name: Clean up roles
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ item }}"
|
||||
loop:
|
||||
- test_role
|
||||
- test_role2
|
||||
@@ -1,11 +1,9 @@
|
||||
expected_fields:
|
||||
os_identity_user_fields:
|
||||
- default_project_id
|
||||
- description
|
||||
- domain_id
|
||||
- email
|
||||
- enabled
|
||||
- id
|
||||
- is_enabled
|
||||
- links
|
||||
- name
|
||||
- password
|
||||
- password_expires_at
|
||||
- username
|
||||
|
||||
@@ -1,218 +1,197 @@
|
||||
---
|
||||
- name: Create a user without a password
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
email: ansible.user@nowhere.net
|
||||
domain: default
|
||||
description: "ansible user"
|
||||
default_project: demo
|
||||
register: user
|
||||
- name: 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: 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
|
||||
- block:
|
||||
- name: Delete unexistent user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_user
|
||||
register: user
|
||||
|
||||
- name: Fail when update_password is always but no password specified
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
update_password: always
|
||||
email: ansible.user@nowhere.net
|
||||
domain: default
|
||||
default_project: demo
|
||||
register: user
|
||||
ignore_errors: true
|
||||
- name: Ensure user was not changed
|
||||
assert:
|
||||
that: user is not changed
|
||||
|
||||
- name: Assert that update failed
|
||||
assert:
|
||||
that:
|
||||
- user is failed
|
||||
- user.msg == "update_password is 'always' but password is missing"
|
||||
- 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: Delete user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_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: Create user with a password
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
password: secret
|
||||
email: ansible.user@nowhere.net
|
||||
update_password: on_create
|
||||
domain: default
|
||||
default_project: demo
|
||||
- name: 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 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
|
||||
- assert:
|
||||
that: user.msg == "update_password is always but a password value is missing"
|
||||
|
||||
- name: Assert user was not changed
|
||||
assert:
|
||||
that:
|
||||
- user is not changed
|
||||
- name: Delete user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_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
|
||||
- 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: Ensure user was changed
|
||||
assert:
|
||||
that:
|
||||
- user is changed
|
||||
- name: Assert user has fields
|
||||
assert:
|
||||
that: item in user['user']
|
||||
loop: "{{ os_identity_user_fields }}"
|
||||
|
||||
- block:
|
||||
- name: Create identical user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
password: secret
|
||||
email: ansible.user@nowhere.net
|
||||
update_password: on_create
|
||||
domain: default
|
||||
default_project: demo
|
||||
register: user
|
||||
|
||||
- name: Assert user was not changed
|
||||
assert:
|
||||
that: user is not changed
|
||||
|
||||
- name: Assert user has fields
|
||||
assert:
|
||||
that: item in user['user']
|
||||
loop: "{{ os_identity_user_fields }}"
|
||||
|
||||
- block:
|
||||
- name: Update user with password
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
password: secret2
|
||||
email: updated.ansible.user@nowhere.net
|
||||
register: user
|
||||
|
||||
- name: Ensure user was changed
|
||||
assert:
|
||||
that: user is changed
|
||||
|
||||
- name: Ensure user has fields
|
||||
assert:
|
||||
that: item in user['user']
|
||||
loop: "{{ os_identity_user_fields }}"
|
||||
|
||||
- name: Update user without password and update_password set to always
|
||||
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
|
||||
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
|
||||
|
||||
- name: Assert user update failed
|
||||
assert:
|
||||
that:
|
||||
- user is failed
|
||||
- user.msg == "update_password is 'always' but password is missing"
|
||||
- assert:
|
||||
that: user.msg == "update_password is always but a password value is missing"
|
||||
|
||||
- name: Ensure user with update_password set to on_create
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
update_password: on_create
|
||||
password: secret3
|
||||
email: updated.ansible.user@nowhere.net
|
||||
register: user
|
||||
- block:
|
||||
- name: Ensure user with update_password set to on_create
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
update_password: on_create
|
||||
password: secret3
|
||||
email: updated.ansible.user@nowhere.net
|
||||
register: user
|
||||
|
||||
- name: Ensure user was not changed
|
||||
assert:
|
||||
that:
|
||||
- user is not changed
|
||||
- name: Ensure user was not changed
|
||||
assert:
|
||||
that: user is not changed
|
||||
|
||||
- name: Ensure user with update_password set to always
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
update_password: always
|
||||
password: secret3
|
||||
email: updated.ansible.user@nowhere.net
|
||||
register: user
|
||||
- block:
|
||||
- name: Ensure user with update_password set to always
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
update_password: always
|
||||
password: secret3
|
||||
email: updated.ansible.user@nowhere.net
|
||||
register: user
|
||||
|
||||
- name: Ensure user was changed
|
||||
assert:
|
||||
that:
|
||||
- user is changed
|
||||
- name: Ensure user was changed
|
||||
assert:
|
||||
that: user is changed
|
||||
|
||||
- name: Create user without a password
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user2
|
||||
password: secret
|
||||
email: ansible.user2@nowhere.net
|
||||
update_password: on_create
|
||||
domain: default
|
||||
default_project: demo
|
||||
register: user
|
||||
- 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: Fetch users
|
||||
openstack.cloud.identity_user_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: users
|
||||
- name: Assert user has fields
|
||||
assert:
|
||||
that: item in user['user']
|
||||
loop: "{{ os_identity_user_fields }}"
|
||||
|
||||
- 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
|
||||
- block:
|
||||
- name: Delete user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_user
|
||||
|
||||
- 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
|
||||
- name: Ensure user was changed
|
||||
assert:
|
||||
that: user is changed
|
||||
|
||||
9
ci/roles/identity_user_info/defaults/main.yml
Normal file
9
ci/roles/identity_user_info/defaults/main.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
os_expected_user_info_fields:
|
||||
- default_project_id
|
||||
- description
|
||||
- domain_id
|
||||
- email
|
||||
- enabled
|
||||
- id
|
||||
- name
|
||||
- username
|
||||
72
ci/roles/identity_user_info/tasks/main.yml
Normal file
72
ci/roles/identity_user_info/tasks/main.yml
Normal file
@@ -0,0 +1,72 @@
|
||||
- name: Ensure user does not exist before tests
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_user
|
||||
|
||||
- block:
|
||||
- name: Get unexistent user
|
||||
openstack.cloud.identity_user_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_user
|
||||
register: userinfo
|
||||
- name: Ensure nothing was returned
|
||||
assert:
|
||||
that: not userinfo.openstack_users
|
||||
|
||||
- block:
|
||||
- name: Create user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
password: secret
|
||||
email: ansible.user@nowhere.net
|
||||
domain: default
|
||||
default_project: demo
|
||||
register: user
|
||||
- name: Create second user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user2
|
||||
password: secret
|
||||
email: ansible.user2@nowhere.net
|
||||
domain: default
|
||||
default_project: demo
|
||||
register: user
|
||||
- name: Get first user info
|
||||
openstack.cloud.identity_user_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_user
|
||||
register: userinfo
|
||||
- name: Assert only one result exists
|
||||
assert:
|
||||
that:
|
||||
- userinfo.openstack_users | length == 1
|
||||
- name: Assert userinfo has fields
|
||||
assert:
|
||||
that:
|
||||
- item in userinfo.openstack_users[0]
|
||||
loop: "{{ os_expected_user_info_fields }}"
|
||||
|
||||
- block:
|
||||
- name: Get all users
|
||||
openstack.cloud.identity_user_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: userinfo
|
||||
- name: Assert results were returned
|
||||
assert:
|
||||
that:
|
||||
- userinfo.openstack_users | length > 0
|
||||
|
||||
- name: Post-test cleanup
|
||||
block:
|
||||
- name: Ensure users do not exist
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ item }}"
|
||||
loop:
|
||||
- ansible_user
|
||||
- ansible_user2
|
||||
@@ -1,65 +0,0 @@
|
||||
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,376 +1,154 @@
|
||||
---
|
||||
- name: Test images
|
||||
block:
|
||||
- name: List all images
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: images
|
||||
- name: Create a test image file
|
||||
shell: mktemp
|
||||
register: tmp_file
|
||||
|
||||
- name: Assert existence of CirrOS image
|
||||
assert:
|
||||
that:
|
||||
- images.images | length > 0
|
||||
- name: Fill test image file to 1MB
|
||||
shell: truncate -s 1048576 {{ tmp_file.stdout }}
|
||||
|
||||
- name: Ensure clean environment
|
||||
ansible.builtin.set_fact:
|
||||
tmp_file: !!null
|
||||
- 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: Create a test image file
|
||||
ansible.builtin.tempfile:
|
||||
register: tmp_file
|
||||
- name: Get details of created image
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: ansible_image
|
||||
register: image_info_result
|
||||
|
||||
- name: Fill test image file to 1MB
|
||||
community.general.filesize:
|
||||
path: '{{ tmp_file.path }}'
|
||||
size: 1M
|
||||
- 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: Calculating file checksum
|
||||
ansible.builtin.stat:
|
||||
path: "{{ tmp_file.path }}"
|
||||
checksum_algorithm: sha512
|
||||
get_checksum: true
|
||||
register: image_details
|
||||
- name: Delete raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_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: 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: Create raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
filename: "{{ tmp_file.path }}"
|
||||
is_protected: true
|
||||
checksum: "{{ image_details.stat.checksum }}"
|
||||
disk_format: raw
|
||||
tags:
|
||||
- test
|
||||
- ansible
|
||||
register: image
|
||||
- name: Delete raw image (complex)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_image
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
- name: Try to get details of deleted image
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: ansible_image
|
||||
register: deleted_image_info_result
|
||||
|
||||
- name: Assert return values of image module
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
- image.image.name == 'ansible_image'
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(image.image.keys())|length == 0
|
||||
- name: Verify image is deleted
|
||||
assert:
|
||||
that:
|
||||
- not deleted_image_info_result.openstack_images
|
||||
|
||||
- name: Get details of created image
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: ansible_image
|
||||
register: images
|
||||
- name: Create owner project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: image_owner_project
|
||||
description: Project owning test image
|
||||
domain_id: default
|
||||
enabled: True
|
||||
register: owner_project
|
||||
|
||||
- name: Assert return values of image_info module
|
||||
assert:
|
||||
that:
|
||||
- images.images | length > 0
|
||||
- images.images.0.name == "ansible_image"
|
||||
- images.images.0.tags | sort == ['test', 'ansible'] | sort
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(images.images.0.keys())|length == 0
|
||||
- name: Create raw image (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: 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: Get details of created image (owner by project name)
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: ansible_image
|
||||
register: image_info_result
|
||||
|
||||
- name: Assert not changed
|
||||
assert:
|
||||
that:
|
||||
- image is not changed
|
||||
- name: Verify image owner (owner by project name)
|
||||
assert:
|
||||
that:
|
||||
- image_info_result.openstack_images[0].owner == owner_project.project.id
|
||||
|
||||
- name: Update is_protected on raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
is_protected: false
|
||||
register: image
|
||||
- name: Delete raw image (owner by project name)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_image
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
- image.image.is_protected == false
|
||||
- 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
|
||||
- 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: Update visibility on raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
is_public: false
|
||||
register: image
|
||||
- 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: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image.image.visibility == 'private'
|
||||
- name: Delete raw image (owner by project name and domain name)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_image
|
||||
|
||||
- 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 owner project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: image_owner_project
|
||||
domain_id: default
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
- image.image.visibility == 'public'
|
||||
|
||||
- name: Define visibility on raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
visibility: shared
|
||||
register: image
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
- image.image.visibility == 'shared'
|
||||
|
||||
- name: Rename raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
id: "{{ image.image.id }}"
|
||||
name: 'ansible_image-changed'
|
||||
register: image
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
- image.image.name == 'ansible_image-changed'
|
||||
|
||||
- name: Deactivate raw image
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: inactive
|
||||
id: "{{ image.image.id }}"
|
||||
name: 'ansible_image-changed'
|
||||
register: image
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
- image.image.status == 'deactivated'
|
||||
|
||||
- name: Reactivate raw image
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
id: "{{ image.image.id }}"
|
||||
name: 'ansible_image-changed'
|
||||
register: image
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
- image.image.status == 'active'
|
||||
|
||||
- name: Rename back raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
id: "{{ image.image.id }}"
|
||||
name: ansible_image
|
||||
register: image
|
||||
|
||||
- name: Delete raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_image
|
||||
register: image
|
||||
|
||||
- name: assert image changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
|
||||
- name: Delete raw image again (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_image
|
||||
register: image
|
||||
|
||||
- name: assert image not changed
|
||||
assert:
|
||||
that:
|
||||
- image is not changed
|
||||
|
||||
- name: Create raw image (complex)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
filename: "{{ tmp_file.path }}"
|
||||
disk_format: raw
|
||||
is_public: True
|
||||
min_disk: 10
|
||||
min_ram: 1024
|
||||
# TODO(rcastillo): upload cirros-vmlinuz, cirros-initrd in test setup
|
||||
kernel: cirros-vmlinuz
|
||||
ramdisk: cirros-initrd
|
||||
properties:
|
||||
cpu_arch: x86_64
|
||||
distro: ubuntu
|
||||
register: image
|
||||
|
||||
- name: Assert visibility
|
||||
assert:
|
||||
that:
|
||||
- image.image.visibility == 'public'
|
||||
|
||||
- name: Delete raw image (complex)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_image
|
||||
|
||||
- name: Try to get details of deleted image
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: ansible_image
|
||||
register: images
|
||||
|
||||
- name: Verify image is deleted
|
||||
assert:
|
||||
that:
|
||||
- images.images | length == 0
|
||||
|
||||
- name: Create owner project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: Project owning test image
|
||||
domain: default
|
||||
is_enabled: True
|
||||
register: project
|
||||
|
||||
- name: Create raw image (owner by project name)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
filename: "{{ tmp_file.path }}"
|
||||
disk_format: raw
|
||||
tags:
|
||||
- test
|
||||
- ansible
|
||||
project: ansible_project
|
||||
register: image
|
||||
|
||||
- name: Get details of created image (owner by project name)
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: ansible_image
|
||||
register: images
|
||||
|
||||
- name: Verify image owner (owner by project name)
|
||||
assert:
|
||||
that:
|
||||
- images.images.0.owner == project.project.id
|
||||
|
||||
- name: Delete raw image (owner by project name)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_image
|
||||
|
||||
- name: Create raw image (owner by project name and domain name)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
filename: "{{ tmp_file.path }}"
|
||||
disk_format: raw
|
||||
tags:
|
||||
- test
|
||||
- ansible
|
||||
project: ansible_project
|
||||
project_domain: default
|
||||
register: image
|
||||
|
||||
- name: Get details of created image (owner by project name and domain name)
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: ansible_image
|
||||
register: images
|
||||
|
||||
- name: Verify image owner (owner by project name and domain name)
|
||||
assert:
|
||||
that:
|
||||
- images.images.0.owner == project.project.id
|
||||
|
||||
- name: Delete raw image (owner by project name and domain name)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_image
|
||||
|
||||
- name: Delete owner project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_project
|
||||
domain: default
|
||||
|
||||
- name: Delete mock kernel and ramdisk images
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ item }}"
|
||||
loop:
|
||||
- cirros-vmlinuz
|
||||
- cirros-initrd
|
||||
|
||||
- name: Delete test image file
|
||||
file:
|
||||
name: "{{ tmp_file.path }}"
|
||||
state: absent
|
||||
|
||||
always:
|
||||
- name: Remove temporary image file
|
||||
ansible.builtin.file:
|
||||
path: "{{ tmp_file.path }}"
|
||||
state: absent
|
||||
when: tmp_file is defined and 'path' in tmp_file
|
||||
- name: Delete test image file
|
||||
file:
|
||||
name: "{{ tmp_file.stdout }}"
|
||||
state: absent
|
||||
|
||||
23
ci/roles/image_info/defaults/main.yml
Normal file
23
ci/roles/image_info/defaults/main.yml
Normal file
@@ -0,0 +1,23 @@
|
||||
expected_fields:
|
||||
- checksum
|
||||
- container_format
|
||||
- created_at
|
||||
- direct_url
|
||||
- disk_format
|
||||
- file
|
||||
- id
|
||||
- locations
|
||||
- metadata
|
||||
- min_disk
|
||||
- min_ram
|
||||
- name
|
||||
- os_hidden
|
||||
- owner
|
||||
- properties
|
||||
- schema
|
||||
- size
|
||||
- status
|
||||
- tags
|
||||
- updated_at
|
||||
- virtual_size
|
||||
- visibility
|
||||
11
ci/roles/image_info/tasks/main.yml
Normal file
11
ci/roles/image_info/tasks/main.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
- name: List all images # This will list at least the default cirros image of devstack
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: image_list_result
|
||||
|
||||
- name: Assert fields
|
||||
assert:
|
||||
that:
|
||||
- item in image_list_result.openstack_images.0.keys()
|
||||
loop: "{{ expected_fields }}"
|
||||
@@ -1,2 +0,0 @@
|
||||
[inventory]
|
||||
enable_plugins=openstack.cloud.openstack
|
||||
@@ -1,406 +0,0 @@
|
||||
---
|
||||
- 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
|
||||
@@ -1,11 +0,0 @@
|
||||
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,12 +6,6 @@
|
||||
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 }}"
|
||||
@@ -26,19 +20,19 @@
|
||||
- name: Ensure that list of keypairs contains single element
|
||||
assert:
|
||||
that:
|
||||
- keypairs['keypairs']|length == 1
|
||||
- keypairs['openstack_keypairs']|length == 1
|
||||
|
||||
- name: Assert fields
|
||||
assert:
|
||||
that:
|
||||
- item in keypairs.keypairs.0.keys()
|
||||
- item in keypairs.openstack_keypairs.0.keys()
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
# This assert verifies that Ansible is capable serializing data returned by SDK
|
||||
- name: Ensure public key is returned
|
||||
assert:
|
||||
that:
|
||||
- keypair.keypair.public_key is defined and keypair.keypair.public_key
|
||||
- keypair.key.public_key is defined and keypair.key.public_key
|
||||
|
||||
- name: Create another keypair
|
||||
openstack.cloud.keypair:
|
||||
@@ -67,7 +61,7 @@
|
||||
- name: Ensure that list of keypairs is empty
|
||||
assert:
|
||||
that:
|
||||
- keypairs['keypairs']|length == 0
|
||||
- keypairs['openstack_keypairs']|length == 0
|
||||
|
||||
- name: Delete another keypair
|
||||
openstack.cloud.keypair:
|
||||
@@ -78,7 +72,7 @@
|
||||
- name: Generate test key file
|
||||
user:
|
||||
name: "{{ ansible_env.USER }}"
|
||||
generate_ssh_key: true
|
||||
generate_ssh_key: yes
|
||||
ssh_key_file: .ssh/shade_id_rsa
|
||||
|
||||
- name: Create keypair (file)
|
||||
@@ -97,7 +91,7 @@
|
||||
- name: Ensure that list of keypairs contains single element
|
||||
assert:
|
||||
that:
|
||||
- keypairs['keypairs']|length == 1
|
||||
- keypairs['openstack_keypairs']|length == 1
|
||||
|
||||
- name: Delete keypair (file)
|
||||
openstack.cloud.keypair:
|
||||
@@ -114,7 +108,7 @@
|
||||
- name: Ensure that list of keypairs is empty
|
||||
assert:
|
||||
that:
|
||||
- keypairs['keypairs']|length == 0
|
||||
- keypairs['openstack_keypairs']|length == 0
|
||||
|
||||
- name: Create keypair (key)
|
||||
openstack.cloud.keypair:
|
||||
@@ -132,7 +126,7 @@
|
||||
- name: Ensure that list of keypairs contains single element
|
||||
assert:
|
||||
that:
|
||||
- keypairs['keypairs']|length == 1
|
||||
- keypairs['openstack_keypairs']|length == 1
|
||||
|
||||
- name: Delete keypair (key)
|
||||
openstack.cloud.keypair:
|
||||
@@ -149,7 +143,7 @@
|
||||
- name: Ensure that list of keypairs is empty
|
||||
assert:
|
||||
that:
|
||||
- keypairs['keypairs']|length == 0
|
||||
- keypairs['openstack_keypairs']|length == 0
|
||||
|
||||
- name: Delete test key pub file
|
||||
file:
|
||||
|
||||
1
ci/roles/keystone_domain/defaults/main.yml
Normal file
1
ci/roles/keystone_domain/defaults/main.yml
Normal file
@@ -0,0 +1 @@
|
||||
domain_name: ansible_domain
|
||||
36
ci/roles/keystone_domain/tasks/main.yml
Normal file
36
ci/roles/keystone_domain/tasks/main.yml
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
- 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,4 +1,35 @@
|
||||
expected_fields:
|
||||
- id
|
||||
- mapping_id
|
||||
- name
|
||||
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
|
||||
|
||||
@@ -6,336 +6,388 @@
|
||||
# - Retry change (noop)
|
||||
#
|
||||
- module_defaults:
|
||||
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
|
||||
# meta/action_groups.yml glue seems to be missing
|
||||
# group/os:
|
||||
# cloud: "{{ cloud }}"
|
||||
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: ansible_domain
|
||||
register: 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: Create test Identity Provider
|
||||
- name: 'Create test Identity Provider'
|
||||
openstack.cloud.federation_idp:
|
||||
state: present
|
||||
name: ansible_idp
|
||||
domain_id: '{{ domain.domain.id }}'
|
||||
state: 'present'
|
||||
name: '{{ idp_name }}'
|
||||
domain_id: '{{ domain_id }}'
|
||||
register: create_idp
|
||||
- assert:
|
||||
that:
|
||||
- create_idp is successful
|
||||
|
||||
- name: Create test mapping (1)
|
||||
- name: 'Create test mapping (1)'
|
||||
openstack.cloud.federation_mapping:
|
||||
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)
|
||||
state: 'present'
|
||||
name: '{{ mapping_name_1 }}'
|
||||
rules: '{{ mapping_rules_1 }}'
|
||||
register: create_mapping
|
||||
- assert:
|
||||
that:
|
||||
- create_mapping is successful
|
||||
- name: 'Create test mapping (2)'
|
||||
openstack.cloud.federation_mapping:
|
||||
state: present
|
||||
name: ansible_mapping2
|
||||
rules:
|
||||
- local:
|
||||
- group:
|
||||
domain:
|
||||
name: example_domain
|
||||
name: example_group
|
||||
remote:
|
||||
- type: HTTP_OIDC_GROUPS
|
||||
any_one_of:
|
||||
- group1
|
||||
|
||||
state: 'present'
|
||||
name: '{{ mapping_name_2 }}'
|
||||
rules: '{{ mapping_rules_2 }}'
|
||||
register: create_mapping
|
||||
- assert:
|
||||
that:
|
||||
- create_mapping is successful
|
||||
|
||||
# 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 does not exist to start
|
||||
- name: "Ensure Protocol doesn't exist to start"
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: absent
|
||||
name: ansible_protocol1
|
||||
state: 'absent'
|
||||
name: '{{ protocol_name }}'
|
||||
register: delete_protocol
|
||||
- assert:
|
||||
that:
|
||||
- delete_protocol is successful
|
||||
|
||||
# ========================================================================
|
||||
# Creation
|
||||
|
||||
- name: Create protocol - CHECK MODE
|
||||
check_mode: true
|
||||
- name: 'Create protocol - CHECK MODE'
|
||||
check_mode: yes
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: present
|
||||
name: ansible_protocol1
|
||||
mapping_id: ansible_mapping1
|
||||
register: protocol
|
||||
|
||||
state: 'present'
|
||||
name: '{{ protocol_name }}'
|
||||
mapping_id: '{{ mapping_name_1 }}'
|
||||
register: create_protocol
|
||||
- assert:
|
||||
that:
|
||||
- protocol is changed
|
||||
- create_protocol is successful
|
||||
- create_protocol is changed
|
||||
|
||||
- name: Fetch Protocol info (should be absent)
|
||||
- name: 'Fetch Protocol info (should be absent)'
|
||||
openstack.cloud.keystone_federation_protocol_info:
|
||||
name: ansible_protocol1
|
||||
register: protocols
|
||||
|
||||
name: '{{ protocol_name }}'
|
||||
register: protocol_info
|
||||
ignore_errors: yes
|
||||
- assert:
|
||||
that:
|
||||
- protocols.protocols | length == 0
|
||||
- protocol_info is failed
|
||||
|
||||
- name: Create protocol
|
||||
- name: 'Create protocol'
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: present
|
||||
name: ansible_protocol1
|
||||
mapping_id: ansible_mapping1
|
||||
register: protocol
|
||||
|
||||
state: 'present'
|
||||
name: '{{ protocol_name }}'
|
||||
mapping_id: '{{ mapping_name_1 }}'
|
||||
register: create_protocol
|
||||
- assert:
|
||||
that:
|
||||
- protocol is changed
|
||||
- protocol.protocol.id == 'ansible_protocol1'
|
||||
- protocol.protocol.name == 'ansible_protocol1'
|
||||
- protocol.protocol.mapping_id == 'ansible_mapping1'
|
||||
- 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 }}'
|
||||
|
||||
- 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
|
||||
- name: 'Create protocol (retry - no change) - CHECK MODE'
|
||||
check_mode: yes
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: present
|
||||
name: ansible_protocol1
|
||||
mapping_id: ansible_mapping1
|
||||
register: protocol
|
||||
|
||||
state: 'present'
|
||||
name: '{{ protocol_name }}'
|
||||
mapping_id: '{{ mapping_name_1 }}'
|
||||
register: create_protocol
|
||||
- assert:
|
||||
that:
|
||||
- protocol is not changed
|
||||
- create_protocol is successful
|
||||
- create_protocol is not changed
|
||||
|
||||
- name: Create protocol (retry - no change)
|
||||
- name: 'Create protocol (retry - no change)'
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: present
|
||||
name: ansible_protocol1
|
||||
mapping_id: ansible_mapping1
|
||||
register: protocol
|
||||
|
||||
state: 'present'
|
||||
name: '{{ protocol_name }}'
|
||||
mapping_id: '{{ mapping_name_1 }}'
|
||||
register: create_protocol
|
||||
- assert:
|
||||
that:
|
||||
- protocol is not changed
|
||||
- protocol.protocol.id == 'ansible_protocol1'
|
||||
- protocol.protocol.name == 'ansible_protocol1'
|
||||
- protocol.protocol.mapping_id == 'ansible_mapping1'
|
||||
- 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 }}'
|
||||
|
||||
# ========================================================================
|
||||
# Update
|
||||
|
||||
- name: Update protocol - CHECK MODE
|
||||
check_mode: true
|
||||
- name: 'Update protocol - CHECK MODE'
|
||||
check_mode: yes
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: present
|
||||
name: ansible_protocol1
|
||||
mapping_id: ansible_mapping2
|
||||
register: protocol
|
||||
|
||||
state: 'present'
|
||||
name: '{{ protocol_name }}'
|
||||
mapping_id: '{{ mapping_name_2 }}'
|
||||
register: update_protocol
|
||||
- assert:
|
||||
that:
|
||||
- protocol is changed
|
||||
- update_protocol is successful
|
||||
- update_protocol is changed
|
||||
|
||||
- name: Update protocol
|
||||
- name: 'Update protocol'
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: present
|
||||
name: ansible_protocol1
|
||||
mapping_id: ansible_mapping2
|
||||
register: protocol
|
||||
|
||||
state: 'present'
|
||||
name: '{{ protocol_name }}'
|
||||
mapping_id: '{{ mapping_name_2 }}'
|
||||
register: update_protocol
|
||||
- assert:
|
||||
that:
|
||||
- protocol is changed
|
||||
- protocol.protocol.id == 'ansible_protocol1'
|
||||
- protocol.protocol.name == 'ansible_protocol1'
|
||||
- protocol.protocol.mapping_id == 'ansible_mapping2'
|
||||
- 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 }}'
|
||||
|
||||
- name: Update protocol (retry - no change) - CHECK MODE
|
||||
check_mode: true
|
||||
- name: 'Update protocol (retry - no change) - CHECK MODE'
|
||||
check_mode: yes
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: present
|
||||
name: ansible_protocol1
|
||||
mapping_id: ansible_mapping2
|
||||
register: protocol
|
||||
|
||||
state: 'present'
|
||||
name: '{{ protocol_name }}'
|
||||
mapping_id: '{{ mapping_name_2 }}'
|
||||
register: update_protocol
|
||||
- assert:
|
||||
that:
|
||||
- protocol is not changed
|
||||
- update_protocol is successful
|
||||
- update_protocol is not changed
|
||||
|
||||
- name: Update protocol (retry - no change)
|
||||
- name: 'Update protocol (retry - no change)'
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: present
|
||||
name: ansible_protocol1
|
||||
mapping_id: ansible_mapping2
|
||||
register: protocol
|
||||
|
||||
state: 'present'
|
||||
name: '{{ protocol_name }}'
|
||||
mapping_id: '{{ mapping_name_2 }}'
|
||||
register: update_protocol
|
||||
- assert:
|
||||
that:
|
||||
- protocol is not changed
|
||||
- protocol.protocol.id == 'ansible_protocol1'
|
||||
- protocol.protocol.name == 'ansible_protocol1'
|
||||
- protocol.protocol.mapping_id == 'ansible_mapping2'
|
||||
- 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 }}'
|
||||
|
||||
# ========================================================================
|
||||
# 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: ansible_protocol2
|
||||
mapping_id: ansible_mapping1
|
||||
register: protocol
|
||||
|
||||
state: 'present'
|
||||
name: '{{ protocol_name_2 }}'
|
||||
mapping_id: '{{ mapping_name_1 }}'
|
||||
register: create_protocol_2
|
||||
- assert:
|
||||
that:
|
||||
- protocol is changed
|
||||
- protocol.protocol.id == 'ansible_protocol2'
|
||||
- protocol.protocol.name == 'ansible_protocol2'
|
||||
- protocol.protocol.mapping_id == 'ansible_mapping1'
|
||||
- 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 }}'
|
||||
|
||||
# ========================================================================
|
||||
# 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: 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
|
||||
|
||||
name: '{{ protocol_name }}'
|
||||
register: protocol_info
|
||||
- assert:
|
||||
that:
|
||||
- protocols.protocols[0].id == 'ansible_protocol1'
|
||||
- protocols.protocols[0].name == 'ansible_protocol1'
|
||||
- protocols.protocols[0].mapping_id == 'ansible_mapping2'
|
||||
- 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] }}'
|
||||
|
||||
- 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: protocols
|
||||
|
||||
register: protocol_info
|
||||
- assert:
|
||||
that:
|
||||
# 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'))"
|
||||
- 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] }}'
|
||||
|
||||
# ========================================================================
|
||||
# Deletion
|
||||
|
||||
- name: Delete protocol - CHECK MODE
|
||||
check_mode: true
|
||||
- name: 'Delete protocol - CHECK MODE'
|
||||
check_mode: yes
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: absent
|
||||
name: ansible_protocol1
|
||||
register: protocol
|
||||
|
||||
state: 'absent'
|
||||
name: '{{ protocol_name }}'
|
||||
register: update_protocol
|
||||
- assert:
|
||||
that:
|
||||
- protocol is changed
|
||||
- update_protocol is successful
|
||||
- update_protocol is changed
|
||||
|
||||
- name: Delete protocol
|
||||
- name: 'Delete protocol'
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: absent
|
||||
name: ansible_protocol1
|
||||
register: protocol
|
||||
|
||||
state: 'absent'
|
||||
name: '{{ protocol_name }}'
|
||||
register: update_protocol
|
||||
- assert:
|
||||
that:
|
||||
- protocol is changed
|
||||
- update_protocol is successful
|
||||
- update_protocol is changed
|
||||
|
||||
- name: Delete protocol (retry - no change) - CHECK MODE
|
||||
check_mode: true
|
||||
- name: 'Delete protocol (retry - no change) - CHECK MODE'
|
||||
check_mode: yes
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: absent
|
||||
name: ansible_protocol1
|
||||
register: protocol
|
||||
|
||||
state: 'absent'
|
||||
name: '{{ protocol_name }}'
|
||||
register: update_protocol
|
||||
- assert:
|
||||
that:
|
||||
- protocol is not changed
|
||||
- update_protocol is successful
|
||||
- update_protocol is not changed
|
||||
|
||||
- name: Delete protocol (retry - no change)
|
||||
- name: 'Delete protocol (retry - no change)'
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: absent
|
||||
name: ansible_protocol1
|
||||
register: protocol
|
||||
|
||||
state: 'absent'
|
||||
name: '{{ protocol_name }}'
|
||||
register: update_protocol
|
||||
- assert:
|
||||
that:
|
||||
- protocol is not changed
|
||||
- update_protocol is successful
|
||||
- update_protocol is not changed
|
||||
|
||||
# ========================================================================
|
||||
# Clean up after ourselves
|
||||
always:
|
||||
- name: Delete protocol
|
||||
- name: 'Delete protocol'
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: absent
|
||||
name: ansible_protocol1
|
||||
idp_id: ansible_idp
|
||||
ignore_errors: true
|
||||
state: 'absent'
|
||||
name: '{{ protocol_name }}'
|
||||
idp_id: '{{ idp_name }}'
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Delete protocol (2)
|
||||
- name: 'Delete protocol (2)'
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: absent
|
||||
name: ansible_protocol2
|
||||
idp_id: ansible_idp
|
||||
ignore_errors: true
|
||||
state: 'absent'
|
||||
name: '{{ protocol_name_2 }}'
|
||||
idp_id: '{{ idp_name }}'
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Delete mapping 1
|
||||
- name: 'Delete mapping 1'
|
||||
openstack.cloud.federation_mapping:
|
||||
state: absent
|
||||
name: ansible_mapping1
|
||||
ignore_errors: true
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name_1 }}'
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Delete mapping 2
|
||||
- name: 'Delete mapping 2'
|
||||
openstack.cloud.federation_mapping:
|
||||
state: absent
|
||||
name: ansible_mapping2
|
||||
ignore_errors: true
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name_2 }}'
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Delete idp
|
||||
- name: 'Delete idp'
|
||||
openstack.cloud.federation_idp:
|
||||
state: absent
|
||||
name: ansible_idp
|
||||
ignore_errors: true
|
||||
state: 'absent'
|
||||
name: '{{ idp_name }}'
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Delete domain
|
||||
- name: 'Delete domain'
|
||||
openstack.cloud.identity_domain:
|
||||
state: absent
|
||||
name: ansible_domain
|
||||
ignore_errors: true
|
||||
state: 'absent'
|
||||
name: '{{ domain_name }}'
|
||||
ignore_errors: yes
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
expected_fields:
|
||||
- description
|
||||
- domain_id
|
||||
- id
|
||||
- is_enabled
|
||||
- name
|
||||
- remote_ids
|
||||
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'
|
||||
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,7 +1,3 @@
|
||||
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:
|
||||
group/openstack.cloud.openstack:
|
||||
cloud: "{{ cloud }}"
|
||||
# Backward compatibility with Ansible 2.9
|
||||
# meta/action_groups.yml glue seems to be missing
|
||||
# group/os:
|
||||
# cloud: "{{ cloud }}"
|
||||
openstack.cloud.federation_mapping:
|
||||
cloud: "{{ cloud }}"
|
||||
openstack.cloud.federation_mapping_info:
|
||||
@@ -12,6 +12,10 @@
|
||||
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:
|
||||
@@ -19,20 +23,20 @@
|
||||
name: '{{ mapping_name }}'
|
||||
rules: '{{ mapping_rules_1 }}'
|
||||
register: create_mapping
|
||||
check_mode: true
|
||||
|
||||
check_mode: yes
|
||||
- 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.mappings | length == 0
|
||||
- mapping_info is failed
|
||||
|
||||
- name: 'Create mapping'
|
||||
openstack.cloud.federation_mapping:
|
||||
@@ -40,50 +44,52 @@
|
||||
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
|
||||
- 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
|
||||
- '"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] }}'
|
||||
|
||||
- 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:
|
||||
@@ -91,10 +97,10 @@
|
||||
name: '{{ mapping_name }}'
|
||||
rules: '{{ mapping_rules_1 }}'
|
||||
register: create_mapping
|
||||
check_mode: true
|
||||
|
||||
check_mode: yes
|
||||
- assert:
|
||||
that:
|
||||
- create_mapping is successful
|
||||
- create_mapping is not changed
|
||||
|
||||
- name: 'Create mapping (retry - no change)'
|
||||
@@ -103,10 +109,13 @@
|
||||
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
|
||||
@@ -117,10 +126,10 @@
|
||||
name: '{{ mapping_name }}'
|
||||
rules: '{{ mapping_rules_2 }}'
|
||||
register: update_mapping
|
||||
check_mode: true
|
||||
|
||||
check_mode: yes
|
||||
- assert:
|
||||
that:
|
||||
- update_mapping is successful
|
||||
- update_mapping is changed
|
||||
|
||||
- name: 'Update mapping'
|
||||
@@ -129,10 +138,13 @@
|
||||
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
|
||||
@@ -143,10 +155,13 @@
|
||||
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
|
||||
@@ -157,10 +172,13 @@
|
||||
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
|
||||
@@ -169,37 +187,53 @@
|
||||
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
|
||||
- mapping_info.mappings[0].id == mapping_name_2
|
||||
- mapping_info.mappings[0].name == mapping_name_2
|
||||
- mapping_info.mappings[0].rules | 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] }}'
|
||||
|
||||
- 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: true
|
||||
|
||||
check_mode: yes
|
||||
- assert:
|
||||
that:
|
||||
- delete_mapping is successful
|
||||
- delete_mapping is changed
|
||||
|
||||
- name: 'Delete mapping'
|
||||
@@ -207,9 +241,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'
|
||||
@@ -217,10 +251,10 @@
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name }}'
|
||||
register: delete_mapping
|
||||
check_mode: true
|
||||
|
||||
check_mode: yes
|
||||
- assert:
|
||||
that:
|
||||
- delete_mapping is successful
|
||||
- delete_mapping is not changed
|
||||
|
||||
- name: 'Delete mapping (retry - no change) '
|
||||
@@ -228,28 +262,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.mappings | length == 0
|
||||
- mapping_info is failed
|
||||
|
||||
- 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:
|
||||
@@ -257,10 +291,10 @@
|
||||
openstack.cloud.federation_mapping:
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name }}'
|
||||
ignore_errors: true
|
||||
ignore_errors: yes
|
||||
|
||||
- name: 'Delete second mapping'
|
||||
openstack.cloud.federation_mapping:
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name_2 }}'
|
||||
ignore_errors: true
|
||||
ignore_errors: yes
|
||||
@@ -1,22 +1,3 @@
|
||||
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
|
||||
network_name: network_lb
|
||||
subnet_name: subnet_lb
|
||||
lb_name: test_lb
|
||||
|
||||
@@ -1,322 +0,0 @@
|
||||
---
|
||||
- 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,33 +20,17 @@
|
||||
tags:
|
||||
- amphora
|
||||
|
||||
- name: Create external network
|
||||
- name: Create network {{ network_name }} for LB
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
external: true
|
||||
name: ansible_external_network
|
||||
state: present
|
||||
register: external_network
|
||||
|
||||
- name: Create external subnet
|
||||
openstack.cloud.subnet:
|
||||
cidr: 10.6.6.0/24
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_external_subnet
|
||||
network_name: ansible_external_network
|
||||
name: "{{ network_name }}"
|
||||
state: present
|
||||
|
||||
- name: Create internal network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_internal_network
|
||||
state: present
|
||||
|
||||
- name: Create internal subnet
|
||||
- name: Create subnet {{ subnet_name }} on network {{ network_name }} for LB
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
network_name: ansible_internal_network
|
||||
name: ansible_internal_subnet
|
||||
network_name: "{{ network_name }}"
|
||||
name: "{{ subnet_name }}"
|
||||
state: present
|
||||
enable_dhcp: true
|
||||
dns_nameservers:
|
||||
@@ -57,230 +41,30 @@
|
||||
allocation_pool_start: 192.168.0.2
|
||||
allocation_pool_end: 192.168.0.254
|
||||
|
||||
- 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
|
||||
- name: Create loadbalancer - generic
|
||||
openstack.cloud.loadbalancer:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_lb
|
||||
vip_subnet: ansible_internal_subnet
|
||||
timeout: 1200
|
||||
register: load_balancer
|
||||
name: "{{ lb_name }}"
|
||||
vip_subnet: "{{ subnet_name }}"
|
||||
timeout: 450
|
||||
|
||||
- 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
|
||||
- name: Delete loadbalancer
|
||||
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: Create load-balancer with floating ip address
|
||||
openstack.cloud.loadbalancer:
|
||||
assign_floating_ip: true
|
||||
cloud: "{{ cloud }}"
|
||||
# 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 internal subnet
|
||||
- name: Delete subnet {{ subnet_name }} on network {{ network_name }}
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_internal_subnet
|
||||
network_name: "{{ network_name }}"
|
||||
name: "{{ subnet_name }}"
|
||||
state: absent
|
||||
|
||||
- name: Delete internal network
|
||||
- name: Delete network {{ network_name }} of LB
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_internal_network
|
||||
name: "{{ network_name }}"
|
||||
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,15 +1,20 @@
|
||||
---
|
||||
- name: Trigger flavor listing to create logs
|
||||
- name: Trigger flavor listing
|
||||
openstack.cloud.compute_flavor_info:
|
||||
cloud: "{{ cloud }}"
|
||||
sdk_log_path: "{{ sdk_log_file_path }}"
|
||||
sdk_log_level: "DEBUG"
|
||||
|
||||
- name: Read openstacksdk's log file
|
||||
ansible.builtin.slurp:
|
||||
src: "{{ sdk_log_file_path }}"
|
||||
register: log
|
||||
- name: Check log file presence
|
||||
ansible.builtin.stat:
|
||||
path: "{{ sdk_log_file_path }}"
|
||||
register: sdk_log_file
|
||||
|
||||
- name: Print contents of openstacksdk's log
|
||||
- name: Assert
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- "sdk_log_file.stat.exists"
|
||||
|
||||
- name: Debug log file content
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ log['content'] | b64decode }}"
|
||||
msg: "{{ lookup('ansible.builtin.file', sdk_log_file_path) }}"
|
||||
|
||||
@@ -1,35 +1,7 @@
|
||||
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
|
||||
network_external: false
|
||||
dns_domain: example.opendev.org
|
||||
mtu: 1250
|
||||
port_security_enabled: false
|
||||
|
||||
@@ -5,29 +5,7 @@
|
||||
name: "{{ network_name }}"
|
||||
state: present
|
||||
shared: "{{ network_shared }}"
|
||||
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
|
||||
external: "{{ network_external }}"
|
||||
|
||||
- name: Gather networks info - generic
|
||||
openstack.cloud.networks_info:
|
||||
@@ -37,28 +15,12 @@
|
||||
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.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)
|
||||
- result.openstack_networks.0.name == network_name
|
||||
- (result.openstack_networks.0.shared|lower) == (network_shared|lower)
|
||||
- result.openstack_networks[0]['router:external'] == {{ network_external }}
|
||||
|
||||
- name: Create network - with new SDK params
|
||||
openstack.cloud.network:
|
||||
@@ -66,25 +28,33 @@
|
||||
name: "{{ network_name_newparams }}"
|
||||
state: present
|
||||
shared: "{{ network_shared }}"
|
||||
external: false
|
||||
external: "{{ network_external }}"
|
||||
mtu: "{{ mtu }}"
|
||||
port_security_enabled: "{{ port_security_enabled }}"
|
||||
register: result_create_nw_with_new_params
|
||||
ignore_errors: true
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Check errors below min sdk version - with new SDK params
|
||||
assert:
|
||||
that:
|
||||
- result_create_nw_with_new_params.failed
|
||||
- '"the installed version of the openstacksdk library MUST be >=0.18.0." in result_create_nw_with_new_params.msg'
|
||||
when: sdk_version is version('0.18', '<')
|
||||
|
||||
- name: Gather networks info - with new SDK params
|
||||
openstack.cloud.networks_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name_newparams }}"
|
||||
register: result_newparams
|
||||
when: sdk_version is version('0.18', '>=')
|
||||
|
||||
- name: Verify networks info - with new SDK params
|
||||
assert:
|
||||
that:
|
||||
- result_newparams.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
|
||||
- result_newparams.openstack_networks.0.name == network_name_newparams
|
||||
- result_newparams.openstack_networks.0.mtu == mtu
|
||||
- result_newparams.openstack_networks.0.port_security_enabled == port_security_enabled
|
||||
when: sdk_version is version('0.18', '>=')
|
||||
|
||||
- name: Delete network - generic and with new SDK params
|
||||
openstack.cloud.network:
|
||||
@@ -104,67 +74,4 @@
|
||||
- name: Verify networks info - deleted
|
||||
assert:
|
||||
that:
|
||||
- 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
|
||||
- result_nonet.openstack_networks == []
|
||||
|
||||
85
ci/roles/neutron_rbac/tasks/main.yml
Normal file
85
ci/roles/neutron_rbac/tasks/main.yml
Normal file
@@ -0,0 +1,85 @@
|
||||
---
|
||||
# General run of tests
|
||||
# - Prepare projects/network objects
|
||||
# - Create rbac object
|
||||
# - Get rbac object info
|
||||
# - Verify RBAC object match
|
||||
# - Delete rbac object
|
||||
# - Get rbac object info
|
||||
# - Verify RBAC object deleted
|
||||
|
||||
- name: Create source project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: source_project
|
||||
description: Source project for network RBAC test
|
||||
domain_id: default
|
||||
enabled: True
|
||||
register: source_project
|
||||
|
||||
- name: Create network - generic
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name }}"
|
||||
state: present
|
||||
project: "{{ source_project.project.id }}"
|
||||
shared: false
|
||||
external: "{{ network_external }}"
|
||||
register: network
|
||||
|
||||
- name: Create target project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: Target project for network RBAC test
|
||||
domain_id: default
|
||||
enabled: True
|
||||
register: target_project
|
||||
|
||||
- name: Create a new network RBAC policy
|
||||
openstack.cloud.neutron_rbac_policy:
|
||||
cloud: "{{ cloud }}"
|
||||
object_id: "{{ network.network.id }}"
|
||||
object_type: 'network'
|
||||
action: 'access_as_shared'
|
||||
target_project_id: "{{ target_project.project.id }}"
|
||||
project_id: "{{ source_project.project.id }}"
|
||||
register: rbac_policy
|
||||
|
||||
- name: Get all rbac policies for {{ source_project.project.name }} - after creation
|
||||
openstack.cloud.neutron_rbac_policies_info:
|
||||
cloud: "{{ cloud }}"
|
||||
project_id: "{{ source_project.project.id }}"
|
||||
register: rbac_policies
|
||||
|
||||
- name: Capture all existing policy IDs
|
||||
set_fact:
|
||||
rbac_policy_ids: "{{ rbac_policies.policies | map(attribute='id') | list }}"
|
||||
|
||||
- name: Verify policy exists - after creation
|
||||
assert:
|
||||
that:
|
||||
- rbac_policy.policy.id in rbac_policy_ids
|
||||
|
||||
- name: Delete RBAC policy
|
||||
openstack.cloud.neutron_rbac_policy:
|
||||
cloud: "{{ cloud }}"
|
||||
policy_id: "{{ rbac_policy.policy.id }}"
|
||||
state: absent
|
||||
|
||||
- name: Get all rbac policies for {{ source_project.project.name }} - after deletion
|
||||
openstack.cloud.neutron_rbac_policies_info:
|
||||
cloud: "{{ cloud }}"
|
||||
project_id: "{{ source_project.project.id }}"
|
||||
register: rbac_policies_remaining
|
||||
|
||||
- name: Capture all remaining policy IDs
|
||||
set_fact:
|
||||
remaining_rbac_policy_ids: "{{ rbac_policies_remaining.policies | map(attribute='id') | list }}"
|
||||
|
||||
- name: Verify policy does not exist - after deletion
|
||||
assert:
|
||||
that:
|
||||
- not rbac_policy.policy.id in remaining_rbac_policy_ids
|
||||
@@ -1,10 +0,0 @@
|
||||
expected_fields:
|
||||
- action
|
||||
- id
|
||||
- name
|
||||
- object_id
|
||||
- object_type
|
||||
- project_id
|
||||
- target_project_id
|
||||
- tenant_id
|
||||
all_project_symbol: '*'
|
||||
@@ -1,123 +0,0 @@
|
||||
---
|
||||
- name: Create source project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_source_project
|
||||
description: Source project for network RBAC test
|
||||
domain: default
|
||||
is_enabled: True
|
||||
register: source_project
|
||||
|
||||
- name: Create network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "ansible_network"
|
||||
state: present
|
||||
project: "{{ source_project.project.id }}"
|
||||
shared: false
|
||||
external: true
|
||||
register: network
|
||||
|
||||
- name: Create target project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_target_project
|
||||
description: Target project for network RBAC test
|
||||
domain_id: default
|
||||
enabled: True
|
||||
register: target_project
|
||||
|
||||
- name: Create a new network RBAC policy
|
||||
openstack.cloud.neutron_rbac_policy:
|
||||
cloud: "{{ cloud }}"
|
||||
object_id: "{{ network.network.id }}"
|
||||
object_type: 'network'
|
||||
action: 'access_as_shared'
|
||||
target_project_id: "{{ target_project.project.id }}"
|
||||
project_id: "{{ source_project.project.id }}"
|
||||
register: rbac_policy
|
||||
|
||||
- name: Assert return values of neutron_rbac_policy module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(rbac_policy.rbac_policy.keys())|length == 0
|
||||
|
||||
- name: Get all rbac policies for {{ source_project.project.name }} - after creation
|
||||
openstack.cloud.neutron_rbac_policies_info:
|
||||
cloud: "{{ cloud }}"
|
||||
project: "{{ source_project.project.id }}"
|
||||
register: rbac_policies
|
||||
|
||||
- name: Assert return values of neutron_rbac_policy_info module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(rbac_policies.rbac_policies[0].keys())|length == 0
|
||||
|
||||
- name: Verify policy exists - after creation
|
||||
assert:
|
||||
that:
|
||||
- rbac_policy.rbac_policy.id in
|
||||
( rbac_policies.rbac_policies | map(attribute='id') | list )
|
||||
|
||||
- name: Delete RBAC policy
|
||||
openstack.cloud.neutron_rbac_policy:
|
||||
cloud: "{{ cloud }}"
|
||||
id: "{{ rbac_policy.rbac_policy.id }}"
|
||||
state: absent
|
||||
|
||||
- name: Create a new network RBAC policy by targeting all projects
|
||||
openstack.cloud.neutron_rbac_policy:
|
||||
cloud: "{{ cloud }}"
|
||||
object_id: "{{ network.network.id }}"
|
||||
object_type: 'network'
|
||||
action: 'access_as_shared'
|
||||
target_all_project: true
|
||||
project_id: "{{ source_project.project.id }}"
|
||||
register: rbac_policy
|
||||
|
||||
- name: Assert return values of neutron_rbac_policy module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(rbac_policy.rbac_policy.keys())|length == 0
|
||||
- rbac_policy.rbac_policy.target_project_id == all_project_symbol
|
||||
|
||||
- name: Delete RBAC policy
|
||||
openstack.cloud.neutron_rbac_policy:
|
||||
cloud: "{{ cloud }}"
|
||||
id: "{{ rbac_policy.rbac_policy.id }}"
|
||||
state: absent
|
||||
|
||||
- name: Get all rbac policies for {{ source_project.project.name }} - after deletion
|
||||
openstack.cloud.neutron_rbac_policies_info:
|
||||
cloud: "{{ cloud }}"
|
||||
project: "{{ source_project.project.id }}"
|
||||
register: rbac_policies_remaining
|
||||
|
||||
- name: Verify policy does not exist - after deletion
|
||||
assert:
|
||||
that:
|
||||
- rbac_policy.rbac_policy.id not in
|
||||
( rbac_policies_remaining.rbac_policies | map(attribute='id') | list )
|
||||
|
||||
- name: Delete target project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_target_project
|
||||
|
||||
- name: Delete network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "ansible_network"
|
||||
state: absent
|
||||
|
||||
- name: Delete source project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_source_project
|
||||
53
ci/roles/nova_flavor/tasks/main.yml
Normal file
53
ci/roles/nova_flavor/tasks/main.yml
Normal file
@@ -0,0 +1,53 @@
|
||||
---
|
||||
- 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
|
||||
33
ci/roles/nova_services/tasks/main.yml
Normal file
33
ci/roles/nova_services/tasks/main.yml
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
|
||||
- name: Get nova compute services info
|
||||
openstack.cloud.compute_service_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: result
|
||||
failed_when: "result.openstack_compute_services | length <= 0"
|
||||
|
||||
- name: Assert fields on OpenStack SDK before 0.53
|
||||
when: sdk_version is version(0.53, '<')
|
||||
assert:
|
||||
that:
|
||||
- '["availability_zone", "binary", "disables_reason",
|
||||
"host", "name", "state", "status", "id"] |
|
||||
difference(result.openstack_compute_services.0.keys()) | length == 0'
|
||||
|
||||
- name: Assert fields on OpenStack SDK 0.53 and later
|
||||
when: sdk_version is version(0.53, '>=')
|
||||
assert:
|
||||
that:
|
||||
- '["availability_zone", "binary", "disabled_reason", "is_forced_down",
|
||||
"host", "name", "state", "status", "updated_at", "id"] |
|
||||
difference(result.openstack_compute_services.0.keys()) | length == 0'
|
||||
|
||||
- name: Filter compute services. Supported since OpenStack SDK 0.53.0 (Wallaby).
|
||||
when: sdk_version is version(0.53, '>=')
|
||||
block:
|
||||
- name: Get nova compute services info
|
||||
openstack.cloud.compute_service_info:
|
||||
cloud: "{{ cloud }}"
|
||||
binary: "nova-compute"
|
||||
register: result
|
||||
failed_when: "result.openstack_compute_services | length <= 0"
|
||||
@@ -1,32 +0,0 @@
|
||||
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,76 +1,37 @@
|
||||
---
|
||||
- name: Create a test object file
|
||||
shell: mktemp
|
||||
register: tmp_file
|
||||
|
||||
- name: Create container
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_container
|
||||
|
||||
- name: Create object from data
|
||||
openstack.cloud.object:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_object
|
||||
data: "this is a test"
|
||||
container: ansible_container
|
||||
register: object
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
container: ansible_container
|
||||
container_access: private
|
||||
|
||||
- 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: Put object
|
||||
openstack.cloud.object:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_object
|
||||
filename: "{{ tmp_file.stdout }}"
|
||||
container: ansible_container
|
||||
|
||||
- name: Delete object
|
||||
openstack.cloud.object:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_object
|
||||
container: ansible_container
|
||||
|
||||
- name: Create object from file
|
||||
block:
|
||||
- name: Create temporary data file
|
||||
ansible.builtin.tempfile:
|
||||
register: tmp_file
|
||||
|
||||
- name: Populate data file
|
||||
ansible.builtin.copy:
|
||||
content: "this is a test"
|
||||
dest: "{{ tmp_file.path }}"
|
||||
|
||||
- name: Create object from data file
|
||||
openstack.cloud.object:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_object
|
||||
filename: "{{ tmp_file.path }}"
|
||||
container: ansible_container
|
||||
register: object
|
||||
|
||||
always:
|
||||
- name: Remove temporary data file
|
||||
ansible.builtin.file:
|
||||
path: "{{ tmp_file.path }}"
|
||||
state: absent
|
||||
when: tmp_file is defined and 'path' in tmp_file
|
||||
|
||||
- name: Assert return values of object module
|
||||
assert:
|
||||
that:
|
||||
- object.object.id == "ansible_object"
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(object.object.keys())|length == 0
|
||||
|
||||
- name: Delete object
|
||||
openstack.cloud.object:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_object
|
||||
container: ansible_container
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_object
|
||||
container: ansible_container
|
||||
|
||||
- name: Delete container
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_container
|
||||
openstack.cloud.object:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
container: ansible_container
|
||||
|
||||
- name: Delete test object file
|
||||
file:
|
||||
name: "{{ tmp_file.stdout }}"
|
||||
state: absent
|
||||
|
||||
@@ -1,22 +1 @@
|
||||
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
|
||||
container_name: "test-container"
|
||||
@@ -1,108 +1,60 @@
|
||||
---
|
||||
- name: Create an empty container with public access
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_container
|
||||
read_ACL: ".r:*,.rlistings"
|
||||
register: container
|
||||
- module_defaults:
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
block:
|
||||
- name: Create an empty container
|
||||
openstack.cloud.object_container:
|
||||
container: "{{ container_name }}"
|
||||
register: container
|
||||
|
||||
- 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: Verify container was created
|
||||
assert:
|
||||
that:
|
||||
- container is success
|
||||
- container is changed
|
||||
- container.container.name == container_name
|
||||
|
||||
- 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: Set metadata for a container
|
||||
openstack.cloud.object_container:
|
||||
container: "{{ container_name }}"
|
||||
metadata: "Cache-Control='no-cache'"
|
||||
register: set_meta
|
||||
|
||||
- name: Verify container metadata was set
|
||||
assert:
|
||||
that:
|
||||
- container is changed
|
||||
- ('cache-control' in container.container.metadata.keys()|map('lower'))
|
||||
- container.container.metadata['foo'] == 'bar'
|
||||
- name: Verify container metadata was set
|
||||
assert:
|
||||
that:
|
||||
- set_meta is success
|
||||
- set_meta is changed
|
||||
|
||||
- name: Update container metadata
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_container
|
||||
metadata:
|
||||
'foo': 'baz'
|
||||
register: container
|
||||
- name: Delete some keys from container metadata
|
||||
openstack.cloud.object_container:
|
||||
container: "{{ container_name }}"
|
||||
keys:
|
||||
- Cache-Control
|
||||
register: delete_meta
|
||||
|
||||
- name: Verify container metadata was updated
|
||||
assert:
|
||||
that:
|
||||
- container is changed
|
||||
- ('cache-control' in container.container.metadata.keys()|map('lower'))
|
||||
- container.container.metadata['foo'] == 'baz'
|
||||
- name: Verify some keys from container metadata was deleted
|
||||
assert:
|
||||
that:
|
||||
- delete_meta is success
|
||||
- delete_meta is changed
|
||||
|
||||
- name: Update a container
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_container
|
||||
delete_metadata_keys:
|
||||
- 'Cache-Control'
|
||||
read_ACL: ""
|
||||
register: container
|
||||
- name: Delete container
|
||||
openstack.cloud.object_container:
|
||||
container: "{{ container_name }}"
|
||||
state: absent
|
||||
register: deleted
|
||||
|
||||
- name: Verify updated container
|
||||
assert:
|
||||
that:
|
||||
- container is changed
|
||||
- ('cache-control' not in container.container.metadata.keys()|map('lower'))
|
||||
- "container.container.metadata == {'foo': 'baz'}"
|
||||
- container.container.read_ACL is none or container.container.read_ACL == ""
|
||||
- name: Verify container was deleted
|
||||
assert:
|
||||
that:
|
||||
- deleted is success
|
||||
- deleted is changed
|
||||
|
||||
- name: Delete container
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_container
|
||||
state: absent
|
||||
register: container
|
||||
|
||||
- name: Verify container was deleted
|
||||
assert:
|
||||
that:
|
||||
- container is changed
|
||||
|
||||
- name: Delete container again
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_container
|
||||
state: absent
|
||||
register: container
|
||||
|
||||
- name: Verify container was not deleted again
|
||||
assert:
|
||||
that:
|
||||
- container is not changed
|
||||
|
||||
- name: Create another container for recursive deletion
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_container2
|
||||
|
||||
- name: Load an object into container
|
||||
openstack.cloud.object:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_object
|
||||
data: "this is another test"
|
||||
container: ansible_container2
|
||||
|
||||
- name: Delete container recursively
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_container2
|
||||
delete_with_all_objects: true
|
||||
always:
|
||||
- name: Delete container
|
||||
openstack.cloud.object_container:
|
||||
container: "{{ container_name }}"
|
||||
state: absent
|
||||
ignore_errors: yes
|
||||
2
ci/roles/orchestration/defaults/main.yaml
Normal file
2
ci/roles/orchestration/defaults/main.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
---
|
||||
stack_name: "test-stack"
|
||||
44
ci/roles/orchestration/tasks/main.yaml
Normal file
44
ci/roles/orchestration/tasks/main.yaml
Normal file
@@ -0,0 +1,44 @@
|
||||
---
|
||||
- name: Create minimal stack
|
||||
openstack.cloud.stack:
|
||||
cloud: "{{ cloud }}"
|
||||
# template is searched related to playbook location or as absolute path
|
||||
template: "roles/orchestration/files/hello-world.yaml"
|
||||
name: "{{ stack_name }}"
|
||||
|
||||
- name: List stacks
|
||||
openstack.cloud.stack_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: stacks
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- stacks['stacks']|length > 0
|
||||
|
||||
- name: Get Single stack
|
||||
openstack.cloud.stack_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ stack_name }}"
|
||||
register: test_stack
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- test_stack is defined
|
||||
- test_stack['stacks'][0]['name'] == stack_name
|
||||
|
||||
- name: Delete stack
|
||||
openstack.cloud.stack:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ stack_name }}"
|
||||
state: absent
|
||||
|
||||
- name: Get Single stack
|
||||
openstack.cloud.stack_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ stack_name }}"
|
||||
register: stacks
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- stacks is defined
|
||||
- (stacks['stacks']|length == 0) or (stacks['stacks'][0]['status'] == 'DELETE_COMPLETE')
|
||||
@@ -1,42 +1,9 @@
|
||||
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
|
||||
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"
|
||||
|
||||
@@ -1,269 +1,121 @@
|
||||
---
|
||||
- name: Create network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ network_name }}"
|
||||
external: true
|
||||
register: network
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ network_name }}"
|
||||
external: "{{ network_external }}"
|
||||
|
||||
- name: Create subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ subnet_name }}"
|
||||
network_name: "{{ network_name }}"
|
||||
cidr: 10.5.5.0/24
|
||||
register: subnet
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ subnet_name }}"
|
||||
network_name: "{{ network_name }}"
|
||||
cidr: 10.5.5.0/24
|
||||
|
||||
- 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: ansible_security_group
|
||||
description: Test group
|
||||
register: security_group
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ secgroup_name }}"
|
||||
description: Test 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:
|
||||
- ansible_security_group
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
fixed_ips:
|
||||
- ip_address: 10.5.5.69
|
||||
security_groups:
|
||||
- "{{ secgroup_name }}"
|
||||
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 }}"
|
||||
|
||||
- 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 }}"
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ port_name }}"
|
||||
|
||||
- name: Delete security group
|
||||
openstack.cloud.security_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_security_group
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ secgroup_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 }}"
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
expected_fields:
|
||||
- description
|
||||
- domain_id
|
||||
- id
|
||||
- is_domain
|
||||
- is_enabled
|
||||
- name
|
||||
- options
|
||||
- parent_id
|
||||
- tags
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user