mirror of
https://opendev.org/openstack/ansible-collections-openstack.git
synced 2026-03-27 14:03:03 +00:00
Compare commits
131 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b7765776a7 | ||
|
|
4490e008c4 | ||
|
|
f376d4679e | ||
|
|
12ec8c63c2 | ||
|
|
72f371c157 | ||
|
|
ce421fe370 | ||
|
|
f20ec3a151 | ||
|
|
a89ec027b0 | ||
|
|
322f96c4db | ||
|
|
50b55560fc | ||
|
|
0c0013504e | ||
|
|
e651838f3e | ||
|
|
4553282545 | ||
|
|
235628dace | ||
|
|
4ee8621b37 | ||
|
|
d07039a7ec | ||
|
|
54728a83fa | ||
|
|
8431232eeb | ||
|
|
b21b8b1084 | ||
|
|
e2ffed388e | ||
|
|
ff44a1d1e5 | ||
|
|
9f893824c5 | ||
|
|
b9df964149 | ||
|
|
0c8fe9002e | ||
|
|
e010db6273 | ||
|
|
88277a59af | ||
|
|
1a4d0128c7 | ||
|
|
03a86669de | ||
|
|
fa7526a0ec | ||
|
|
7446ab23b8 | ||
|
|
4171ee52b7 | ||
|
|
60f1b8e2a5 | ||
|
|
0bff3f286f | ||
|
|
5188e281b9 | ||
|
|
966b6597f3 | ||
|
|
5636d502ce | ||
|
|
4db925b452 | ||
|
|
3ce4455bc8 | ||
|
|
309c3025ba | ||
|
|
637d321a9a | ||
|
|
74c18f34f3 | ||
|
|
00be40a462 | ||
|
|
1eb5d85b68 | ||
|
|
d0a4d6e8cc | ||
|
|
29c03592cc | ||
|
|
7888b51053 | ||
|
|
0e4dc21bab | ||
|
|
623b4afbd1 | ||
|
|
80e6597f96 | ||
|
|
8f1512166e | ||
|
|
eabe945194 | ||
|
|
06115c77b7 | ||
|
|
4a1b092efb | ||
|
|
da1fab6629 | ||
|
|
0efb855c68 | ||
|
|
329a5ef50d | ||
|
|
47708e0172 | ||
|
|
17d5c7de8e | ||
|
|
82792ab5d5 | ||
|
|
d4033b4cea | ||
|
|
426b6e782a | ||
|
|
75b2c60960 | ||
|
|
c9527889a0 | ||
|
|
42a5cb5601 | ||
|
|
aa387aab3a | ||
|
|
af79857bfb | ||
|
|
a51d922bee | ||
|
|
0cbaeb6fbb | ||
|
|
532857c0b2 | ||
|
|
acd9bc993b | ||
|
|
0904ddd2fe | ||
|
|
2120814356 | ||
|
|
ad70a20af5 | ||
|
|
a32cff23c7 | ||
|
|
f29a8407af | ||
|
|
555178ecc6 | ||
|
|
f93172677c | ||
|
|
2a461cadd9 | ||
|
|
e3c61aeefd | ||
|
|
3e4413ec31 | ||
|
|
37afe5f2e6 | ||
|
|
7e190d12b4 | ||
|
|
3d9f9a0f87 | ||
|
|
57e1087177 | ||
|
|
6cb6e70645 | ||
|
|
662ac61640 | ||
|
|
891fb6df53 | ||
|
|
0c6752215b | ||
|
|
a6f1177584 | ||
|
|
2dc2806c57 | ||
|
|
59df183660 | ||
|
|
2c287d754c | ||
|
|
28d32b53e8 | ||
|
|
2cb67620aa | ||
|
|
5217b6bdc4 | ||
|
|
96ea60a883 | ||
|
|
0eef3cb978 | ||
|
|
e695000daa | ||
|
|
0258878400 | ||
|
|
ea7ba854d5 | ||
|
|
6b3bf3bba0 | ||
|
|
daaa6bf561 | ||
|
|
2027eb1f46 | ||
|
|
944f9ca498 | ||
|
|
ca6824bffe | ||
|
|
a10be98638 | ||
|
|
6787924f13 | ||
|
|
d1d6b4d2dd | ||
|
|
06e76a1687 | ||
|
|
464d7767bb | ||
|
|
718f3a6b3a | ||
|
|
3320c662c8 | ||
|
|
77acba047b | ||
|
|
890401b605 | ||
|
|
8da4e852f0 | ||
|
|
f3e9c78c18 | ||
|
|
47382d52ed | ||
|
|
0e2058988e | ||
|
|
ab1a2a19d7 | ||
|
|
17a1d72b1c | ||
|
|
58ec1030a4 | ||
|
|
da01746e53 | ||
|
|
c329f65b41 | ||
|
|
18b03e1971 | ||
|
|
16a81fc221 | ||
|
|
50deae71f4 | ||
|
|
b1e5ca91cf | ||
|
|
185d0a5eca | ||
|
|
2b8aa2cb08 | ||
|
|
3c8fbc6b27 | ||
|
|
d212be018b |
328
.zuul.yaml
328
.zuul.yaml
@@ -9,6 +9,15 @@
|
||||
required-projects:
|
||||
- openstack/ansible-collections-openstack
|
||||
- openstack/designate
|
||||
irrelevant-files: &ignore_files
|
||||
- changelogs/.*
|
||||
- COPYING
|
||||
- docs/.*
|
||||
- .*\.md
|
||||
- .*\.rst
|
||||
- tools/run-ansible-sanity.sh
|
||||
- tests/sanity/.*
|
||||
- contrib/.*
|
||||
vars:
|
||||
zuul_work_dir: src/opendev.org/openstack/ansible-collections-openstack
|
||||
tox_envlist: ansible
|
||||
@@ -19,6 +28,42 @@
|
||||
devstack_services:
|
||||
designate: true
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-octavia
|
||||
parent: ansible-collections-openstack-functional-devstack
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
with Octavia plugin enabled, using releases of openstacksdk and latest
|
||||
ansible release. Run it only on Load Balancer changes.
|
||||
pre-run: ci/playbooks/get_amphora_tarball.yaml
|
||||
required-projects:
|
||||
- openstack/octavia
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.11
|
||||
files:
|
||||
- ^ci/roles/loadbalancer/.*$
|
||||
- ^plugins/modules/lb_health_monitor.py
|
||||
- ^plugins/modules/lb_listener.py
|
||||
- ^plugins/modules/lb_member.py
|
||||
- ^plugins/modules/lb_pool.py
|
||||
- ^plugins/modules/loadbalancer.py
|
||||
vars:
|
||||
tox_envlist: ansible
|
||||
devstack_plugins:
|
||||
designate: https://opendev.org/openstack/designate
|
||||
octavia: https://opendev.org/openstack/octavia
|
||||
devstack_services:
|
||||
designate: true
|
||||
octavia: true
|
||||
o-api: true
|
||||
o-cw: true
|
||||
o-hk: true
|
||||
o-hm: true
|
||||
devstack_localrc:
|
||||
OCTAVIA_AMP_IMAGE_FILE: "/tmp/test-only-amphora-x64-haproxy-ubuntu-bionic.qcow2"
|
||||
OCTAVIA_AMP_IMAGE_SIZE: 3
|
||||
OCTAVIA_AMP_IMAGE_NAME: "test-only-amphora-x64-haproxy-ubuntu-bionic"
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-releases
|
||||
parent: ansible-collections-openstack-functional-devstack
|
||||
@@ -43,14 +88,14 @@
|
||||
tox_envlist: ansible-2.9
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-2.10
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-2.11
|
||||
parent: ansible-collections-openstack-functional-devstack
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using master of openstacksdk and stable 2.10 branch of ansible
|
||||
using master of openstacksdk and stable 2.11 branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.10
|
||||
override-checkout: stable-2.11
|
||||
vars:
|
||||
tox_envlist: ansible
|
||||
|
||||
@@ -67,29 +112,34 @@
|
||||
vars:
|
||||
tox_envlist: ansible-2.11
|
||||
|
||||
# Pip installation job
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-pip
|
||||
parent: ansible-collections-openstack-functional-devstack
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using master of openstacksdk with latest ansible release.
|
||||
Ansible collection is built using PIP.
|
||||
vars:
|
||||
tox_envlist: ansible-pip
|
||||
|
||||
# Stable branches tests
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-victoria-ansible-2.10
|
||||
name: ansible-collections-openstack-functional-devstack-wallaby-ansible-2.11
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
description: |
|
||||
Run openstack collections functional tests against a wallaby devstack
|
||||
using wallaby brach of openstacksdk and stable 2.11 branch of ansible
|
||||
voting: true
|
||||
override-checkout: stable/wallaby
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.11
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/wallaby
|
||||
vars:
|
||||
tox_envlist: ansible
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-victoria-ansible-2.11
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
description: |
|
||||
Run openstack collections functional tests against a victoria devstack
|
||||
using victoria brach of openstacksdk and stable 2.10 branch of ansible
|
||||
using victoria brach of openstacksdk and stable 2.11 branch of ansible
|
||||
voting: true
|
||||
override-checkout: stable/victoria
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.10
|
||||
override-checkout: stable-2.11
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/victoria
|
||||
vars:
|
||||
@@ -97,16 +147,16 @@
|
||||
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ussuri-ansible-2.10
|
||||
name: ansible-collections-openstack-functional-devstack-ussuri-ansible-2.11
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
description: |
|
||||
Run openstack collections functional tests against a ussuri devstack
|
||||
using ussuri brach of openstacksdk and stable 2.10 branch of ansible
|
||||
using ussuri brach of openstacksdk and stable 2.11 branch of ansible
|
||||
voting: true
|
||||
override-checkout: stable/ussuri
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.10
|
||||
override-checkout: stable-2.11
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/ussuri
|
||||
- name: openstack/os-client-config
|
||||
@@ -115,16 +165,15 @@
|
||||
tox_envlist: ansible
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-train-ansible-2.10
|
||||
name: ansible-collections-openstack-functional-devstack-train-ansible-2.11
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
description: |
|
||||
Run openstack collections functional tests against a train devstack
|
||||
using train brach of openstacksdk and stable 2.10 branch of ansible
|
||||
voting: false
|
||||
using train brach of openstacksdk and stable 2.11 branch of ansible
|
||||
override-checkout: stable/train
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.10
|
||||
override-checkout: stable-2.11
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/train
|
||||
- name: openstack/os-client-config
|
||||
@@ -133,55 +182,16 @@
|
||||
tox_envlist: ansible
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-stein-ansible-2.10
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
description: |
|
||||
Run openstack collections functional tests against a stein devstack
|
||||
using stein brach of openstacksdk and stable 2.10 branch of ansible
|
||||
voting: true
|
||||
override-checkout: stable/stein
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.10
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/stein
|
||||
- name: openstack/os-client-config
|
||||
override-checkout: stable/stein
|
||||
vars:
|
||||
tox_envlist: ansible
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-rocky-ansible-2.10
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
description: |
|
||||
Run openstack collections functional tests against a rocky devstack
|
||||
using rocky brach of openstacksdk and stable 2.10 branch of ansible
|
||||
voting: true
|
||||
override-checkout: stable/rocky
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.10
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/rocky
|
||||
- name: openstack/os-client-config
|
||||
override-checkout: stable/rocky
|
||||
- name: openstack/shade
|
||||
override-checkout: stable/rocky
|
||||
|
||||
vars:
|
||||
tox_envlist: ansible
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-queens-ansible-2.10
|
||||
name: ansible-collections-openstack-functional-devstack-queens-ansible-2.11
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
description: |
|
||||
Run openstack collections functional tests against a queens devstack
|
||||
using master branch of openstacksdk and stable 2.10 branch of ansible
|
||||
using master branch of openstacksdk and stable 2.11 branch of ansible
|
||||
voting: true
|
||||
override-checkout: stable/queens
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.10
|
||||
override-checkout: stable-2.11
|
||||
- name: openstack/openstacksdk
|
||||
# Run queens with highest possible py2 version of SDK
|
||||
override-checkout: stable/train
|
||||
@@ -205,6 +215,45 @@
|
||||
vars:
|
||||
tox_envlist: ansible-2.11
|
||||
|
||||
# Experimental pipeline jobs
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-stein-ansible-2.11
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
description: |
|
||||
Run openstack collections functional tests against a stein devstack
|
||||
using stein brach of openstacksdk and stable 2.11 branch of ansible
|
||||
voting: true
|
||||
override-checkout: stable/stein
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.11
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/stein
|
||||
- name: openstack/os-client-config
|
||||
override-checkout: stable/stein
|
||||
vars:
|
||||
tox_envlist: ansible
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-rocky-ansible-2.11
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
description: |
|
||||
Run openstack collections functional tests against a rocky devstack
|
||||
using rocky brach of openstacksdk and stable 2.11 branch of ansible
|
||||
voting: true
|
||||
override-checkout: stable/rocky
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.11
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/rocky
|
||||
- name: openstack/os-client-config
|
||||
override-checkout: stable/rocky
|
||||
- name: openstack/shade
|
||||
override-checkout: stable/rocky
|
||||
|
||||
vars:
|
||||
tox_envlist: ansible
|
||||
|
||||
# Linters
|
||||
- job:
|
||||
@@ -222,15 +271,15 @@
|
||||
tox_envlist: linters-2.11
|
||||
|
||||
- job:
|
||||
name: openstack-tox-linters-ansible-2.10
|
||||
name: openstack-tox-linters-ansible-2.11
|
||||
parent: openstack-tox-linters
|
||||
nodeset: ubuntu-bionic
|
||||
description: |
|
||||
Run openstack collections linter tests using the 2.10 branch of ansible
|
||||
Run openstack collections linter tests using the 2.11 branch of ansible
|
||||
voting: true
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.10
|
||||
override-checkout: stable-2.11
|
||||
|
||||
- job:
|
||||
name: openstack-tox-linters-ansible-2.9
|
||||
@@ -258,63 +307,69 @@
|
||||
required-projects:
|
||||
- openstack/ansible-collections-openstack
|
||||
|
||||
# TripleO jobs
|
||||
- job:
|
||||
name: tripleo-ci-centos-8-standalone-osa
|
||||
parent: tripleo-ci-centos-8-standalone
|
||||
vars:
|
||||
consumer_job: false
|
||||
build_container_images: true
|
||||
# Run only on files used in TripleO
|
||||
files: &ooo_files
|
||||
- ^plugins/modules/catalog_service.*$
|
||||
- ^plugins/modules/endpoint.*$
|
||||
- ^plugins/modules/identity_domain.*$
|
||||
- ^plugins/modules/identity_domain_info.*$
|
||||
- ^plugins/modules/identity_role.*$
|
||||
- ^plugins/modules/identity_user.*$
|
||||
- ^plugins/modules/keypair.*$
|
||||
- ^plugins/modules/project.*$
|
||||
- ^plugins/modules/role_assignment.*$
|
||||
- ^plugins/modules/stack.*$
|
||||
- ^plugins/module_utils/openstack.*$
|
||||
|
||||
- job:
|
||||
name: tripleo-ci-centos-8-standalone-train-osa
|
||||
parent: tripleo-ci-centos-8-standalone-osa
|
||||
voting: false
|
||||
override-checkout: stable/train
|
||||
vars:
|
||||
branch_override: stable/train
|
||||
|
||||
- project:
|
||||
check:
|
||||
jobs:
|
||||
- tox-pep8
|
||||
- openstack-tox-linters-ansible-devel
|
||||
- openstack-tox-linters-ansible-2.10
|
||||
# Issue with ansible-test 2.9: https://github.com/ansible/ansible/pull/73530
|
||||
- openstack-tox-linters-ansible-2.9:
|
||||
voting: false
|
||||
- openstack-tox-linters-ansible-2.11
|
||||
- openstack-tox-linters-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack:
|
||||
dependencies: &deps_unit_lint
|
||||
- tox-pep8
|
||||
# - openstack-tox-linters-ansible-2.9
|
||||
- openstack-tox-linters-ansible-2.10
|
||||
irrelevant-files: &ignore_files
|
||||
- changelogs/.*
|
||||
- COPYING
|
||||
- docs/.*
|
||||
- .*\.md
|
||||
- .*\.rst
|
||||
- tools/run-ansible-sanity.sh
|
||||
- tests/sanity/.*
|
||||
- contrib/.*
|
||||
- openstack-tox-linters-ansible-2.9
|
||||
- openstack-tox-linters-ansible-2.11
|
||||
|
||||
- ansible-collections-openstack-functional-devstack-releases:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.9:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.10:
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.11:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-ansible-devel:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-ansible-pip:
|
||||
- ansible-collections-openstack-functional-devstack-wallaby-ansible-2.11:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-victoria-ansible-2.10:
|
||||
- ansible-collections-openstack-functional-devstack-victoria-ansible-2.11:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-ussuri-ansible-2.10:
|
||||
- ansible-collections-openstack-functional-devstack-ussuri-ansible-2.11:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-train-ansible-2.10:
|
||||
- ansible-collections-openstack-functional-devstack-train-ansible-2.11:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-stein-ansible-2.10:
|
||||
- ansible-collections-openstack-functional-devstack-queens-ansible-2.11:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-rocky-ansible-2.10:
|
||||
voting: false
|
||||
- ansible-collections-openstack-functional-devstack-octavia:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-queens-ansible-2.10:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
|
||||
- bifrost-collections-src:
|
||||
voting: false
|
||||
@@ -325,41 +380,52 @@
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
|
||||
- tripleo-ci-centos-8-standalone-osa:
|
||||
dependencies: *deps_unit_lint
|
||||
|
||||
- tripleo-ci-centos-8-standalone-train-osa:
|
||||
voting: false
|
||||
dependencies: *deps_unit_lint
|
||||
|
||||
gate:
|
||||
jobs:
|
||||
- tox-pep8
|
||||
- openstack-tox-linters-ansible-2.10
|
||||
# https://github.com/ansible/ansible/pull/73530
|
||||
# - openstack-tox-linters-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack
|
||||
- ansible-collections-openstack-functional-devstack-releases
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.10
|
||||
- ansible-collections-openstack-functional-devstack-ansible-pip
|
||||
- ansible-collections-openstack-functional-devstack-victoria-ansible-2.10
|
||||
- ansible-collections-openstack-functional-devstack-ussuri-ansible-2.10
|
||||
# - ansible-collections-openstack-functional-devstack-train-ansible-2.10
|
||||
- ansible-collections-openstack-functional-devstack-stein-ansible-2.10
|
||||
- ansible-collections-openstack-functional-devstack-rocky-ansible-2.10
|
||||
- ansible-collections-openstack-functional-devstack-queens-ansible-2.10
|
||||
|
||||
periodic:
|
||||
jobs:
|
||||
- openstack-tox-linters-ansible-devel
|
||||
- openstack-tox-linters-ansible-2.10
|
||||
- openstack-tox-linters-ansible-2.11
|
||||
- openstack-tox-linters-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack
|
||||
- ansible-collections-openstack-functional-devstack-releases
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.10
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-wallaby-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-victoria-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-ussuri-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-train-ansible-2.11
|
||||
# - ansible-collections-openstack-functional-devstack-queens-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-octavia
|
||||
- tripleo-ci-centos-8-standalone-osa
|
||||
|
||||
periodic:
|
||||
jobs:
|
||||
- openstack-tox-linters-ansible-devel
|
||||
- openstack-tox-linters-ansible-2.11
|
||||
- openstack-tox-linters-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack
|
||||
- ansible-collections-openstack-functional-devstack-releases
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
- ansible-collections-openstack-functional-devstack-ansible-pip
|
||||
- ansible-collections-openstack-functional-devstack-victoria-ansible-2.10
|
||||
- ansible-collections-openstack-functional-devstack-ussuri-ansible-2.10
|
||||
- ansible-collections-openstack-functional-devstack-train-ansible-2.10
|
||||
- ansible-collections-openstack-functional-devstack-stein-ansible-2.10
|
||||
- ansible-collections-openstack-functional-devstack-rocky-ansible-2.10
|
||||
- ansible-collections-openstack-functional-devstack-queens-ansible-2.10
|
||||
- ansible-collections-openstack-functional-devstack-wallaby-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-victoria-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-ussuri-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-train-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-queens-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-queens-ansible-devel
|
||||
- bifrost-collections-src
|
||||
- bifrost-keystone-collections-src
|
||||
- ansible-collections-openstack-functional-devstack-octavia
|
||||
|
||||
experimental:
|
||||
jobs:
|
||||
- ansible-collections-openstack-functional-devstack-stein-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-rocky-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-queens-ansible-devel
|
||||
|
||||
@@ -5,6 +5,103 @@ Openstack Cloud Ansilbe modules Release Notes
|
||||
.. contents:: Topics
|
||||
|
||||
|
||||
v1.5.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
New modules for DNS and FIPs and bugfixes.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add bindep.txt for ansible-builder
|
||||
- Add check_mode attribute to OpenstackModule
|
||||
- Migrating image module from AnsibleModule to OpenStackModule
|
||||
- Switch KeystoneFederationProtocolInfo module to OpenStackModule
|
||||
- Switch ProjectAccess module to OpenStackModule
|
||||
- Switch Quota module to OpenStackModule
|
||||
- Switch Recordset module to OpenStackModule
|
||||
- Switch ServerGroup module to OpenStackModule
|
||||
- Switch ServerMetadata module to OpenStackModule
|
||||
- Switch Snapshot module to OpenStackModule
|
||||
- Switch Stack module to OpenStackModule
|
||||
- Switch auth module to OpenStackModule
|
||||
- Switch catalog_service module to OpenStackModule
|
||||
- Switch coe_cluster module to OpenStackModule
|
||||
- Switch coe_cluster_template module to OpenStackModule
|
||||
- Switch endpoint module to OpenStackModule
|
||||
- Switch federation_idp module to OpenStackModule
|
||||
- Switch federation_idp_info module to OpenStackModule
|
||||
- Switch federation_mapping module to OpenStackModule
|
||||
- Switch federation_mapping_info module to OpenStackModule
|
||||
- Switch federation_protocol module to OpenStackModule
|
||||
- Switch flavor module to OpenStackModule
|
||||
- Switch flavor_info module to OpenStackModule
|
||||
- Switch floating_ip module to OpenStackModule
|
||||
- Switch group_assignment module to OpenStackModule
|
||||
- Switch hostaggregate module to OpenStackModule
|
||||
- Switch identity_domain module to OpenStackModule
|
||||
- Switch identity_domain_info module to OpenStackModule
|
||||
- Switch identity_group module to OpenStackModule
|
||||
- Switch identity_group_info module to OpenStackModule
|
||||
- Switch identity_role module to OpenStackModule
|
||||
- Switch identity_user module to OpenStackModule
|
||||
- Switch lb_listener module to OpenStackModule
|
||||
- Switch lb_member module to OpenStackModule
|
||||
- Switch lb_pool module to OpenStackModule
|
||||
- Switch object module to OpenStackModule
|
||||
- Switch port module to OpenStackModule
|
||||
- Switch port_info module to OpenStackModule
|
||||
- Switch project and project_info module to OpenStackModule
|
||||
- Switch role_assignment module to OpenStackModule
|
||||
- Switch user_info module to OpenStackModule
|
||||
- image - Add support to setting image tags
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Update checks for validate_certs in openstack_cloud_from_module
|
||||
- compute_flavor - Fix the idempotent of compute_flavor module
|
||||
- host_aggregate - Fix host_aggregate to tolerate aggregate.hosts being None
|
||||
- inventory/openstack - Fix inventory plugin on Ansible 2.11
|
||||
- port - fix update on empty list of allowed address pairs
|
||||
- setup.cfg Replace dashes with underscores
|
||||
- subnet - Only apply necessary changes to subnets
|
||||
- volume - Fail if referenced source image for a new volume does not exist
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.dns_zone_info - Getting information about dns zones
|
||||
- openstack.cloud.floating_ip_info - Get information about floating ips
|
||||
|
||||
v1.4.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
New object_container module and bugfixes.
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Add Octavia job for testing Load Balancer
|
||||
- Add binding profile to port module
|
||||
- Add execution environment metadata
|
||||
- Fix CI for latest ansible-test with no_log
|
||||
- Fix issues with newest ansible-test 2.11
|
||||
- Prepare for Ansible 2.11 tests
|
||||
- add option to exclude legacy groups
|
||||
- security_group_rule add support ipv6-icmp
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.object_container - Manage Swift container
|
||||
|
||||
v1.3.0
|
||||
======
|
||||
|
||||
|
||||
7
bindep.txt
Normal file
7
bindep.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
# This is a cross-platform list tracking distribution packages needed by tests;
|
||||
# see https://docs.openstack.org/infra/bindep/ for additional information.
|
||||
|
||||
gcc [compile platform:centos-8 platform:rhel-8]
|
||||
python38-cryptography [platform:centos-8 platform:rhel-8]
|
||||
python38-devel [compile platform:centos-8 platform:rhel-8]
|
||||
python38-requests [platform:centos-8 platform:rhel-8]
|
||||
@@ -149,3 +149,83 @@ releases:
|
||||
name: stack_info
|
||||
namespace: ''
|
||||
release_date: '2021-02-16'
|
||||
1.4.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Add Octavia job for testing Load Balancer
|
||||
- Add binding profile to port module
|
||||
- Add execution environment metadata
|
||||
- Fix CI for latest ansible-test with no_log
|
||||
- Fix issues with newest ansible-test 2.11
|
||||
- Prepare for Ansible 2.11 tests
|
||||
- add option to exclude legacy groups
|
||||
- security_group_rule add support ipv6-icmp
|
||||
release_summary: New object_container module and bugfixes.
|
||||
modules:
|
||||
- description: Manage Swift container
|
||||
name: object_container
|
||||
namespace: ''
|
||||
release_date: '2021-04-08'
|
||||
1.5.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Update checks for validate_certs in openstack_cloud_from_module
|
||||
- compute_flavor - Fix the idempotent of compute_flavor module
|
||||
- host_aggregate - Fix host_aggregate to tolerate aggregate.hosts being None
|
||||
- inventory/openstack - Fix inventory plugin on Ansible 2.11
|
||||
- port - fix update on empty list of allowed address pairs
|
||||
- setup.cfg Replace dashes with underscores
|
||||
- subnet - Only apply necessary changes to subnets
|
||||
- volume - Fail if referenced source image for a new volume does not exist
|
||||
minor_changes:
|
||||
- Add bindep.txt for ansible-builder
|
||||
- Add check_mode attribute to OpenstackModule
|
||||
- Migrating image module from AnsibleModule to OpenStackModule
|
||||
- Switch KeystoneFederationProtocolInfo module to OpenStackModule
|
||||
- Switch ProjectAccess module to OpenStackModule
|
||||
- Switch Quota module to OpenStackModule
|
||||
- Switch Recordset module to OpenStackModule
|
||||
- Switch ServerGroup module to OpenStackModule
|
||||
- Switch ServerMetadata module to OpenStackModule
|
||||
- Switch Snapshot module to OpenStackModule
|
||||
- Switch Stack module to OpenStackModule
|
||||
- Switch auth module to OpenStackModule
|
||||
- Switch catalog_service module to OpenStackModule
|
||||
- Switch coe_cluster module to OpenStackModule
|
||||
- Switch coe_cluster_template module to OpenStackModule
|
||||
- Switch endpoint module to OpenStackModule
|
||||
- Switch federation_idp module to OpenStackModule
|
||||
- Switch federation_idp_info module to OpenStackModule
|
||||
- Switch federation_mapping module to OpenStackModule
|
||||
- Switch federation_mapping_info module to OpenStackModule
|
||||
- Switch federation_protocol module to OpenStackModule
|
||||
- Switch flavor module to OpenStackModule
|
||||
- Switch flavor_info module to OpenStackModule
|
||||
- Switch floating_ip module to OpenStackModule
|
||||
- Switch group_assignment module to OpenStackModule
|
||||
- Switch hostaggregate module to OpenStackModule
|
||||
- Switch identity_domain module to OpenStackModule
|
||||
- Switch identity_domain_info module to OpenStackModule
|
||||
- Switch identity_group module to OpenStackModule
|
||||
- Switch identity_group_info module to OpenStackModule
|
||||
- Switch identity_role module to OpenStackModule
|
||||
- Switch identity_user module to OpenStackModule
|
||||
- Switch lb_listener module to OpenStackModule
|
||||
- Switch lb_member module to OpenStackModule
|
||||
- Switch lb_pool module to OpenStackModule
|
||||
- Switch object module to OpenStackModule
|
||||
- Switch port module to OpenStackModule
|
||||
- Switch port_info module to OpenStackModule
|
||||
- Switch project and project_info module to OpenStackModule
|
||||
- Switch role_assignment module to OpenStackModule
|
||||
- Switch user_info module to OpenStackModule
|
||||
- image - Add support to setting image tags
|
||||
release_summary: New modules for DNS and FIPs and bugfixes.
|
||||
modules:
|
||||
- description: Getting information about dns zones
|
||||
name: dns_zone_info
|
||||
namespace: ''
|
||||
- description: Get information about floating ips
|
||||
name: floating_ip_info
|
||||
namespace: ''
|
||||
release_date: '2021-06-23'
|
||||
|
||||
6
ci/playbooks/get_amphora_tarball.yaml
Normal file
6
ci/playbooks/get_amphora_tarball.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
- hosts: all
|
||||
tasks:
|
||||
- name: Download amphora tarball
|
||||
get_url:
|
||||
url: "https://tarballs.openstack.org/octavia/test-images/test-only-amphora-x64-haproxy-ubuntu-bionic.qcow2"
|
||||
dest: /tmp/test-only-amphora-x64-haproxy-ubuntu-bionic.qcow2
|
||||
1
ci/roles/address_scope/defaults/main.yml
Normal file
1
ci/roles/address_scope/defaults/main.yml
Normal file
@@ -0,0 +1 @@
|
||||
address_scope_name: "adrdess_scope"
|
||||
40
ci/roles/address_scope/tasks/main.yml
Normal file
40
ci/roles/address_scope/tasks/main.yml
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
- name: Create address_scope
|
||||
openstack.cloud.address_scope:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ address_scope_name }}"
|
||||
shared: False
|
||||
ip_version: "4"
|
||||
register: create_address_scope
|
||||
|
||||
- name: Verify address scope
|
||||
assert:
|
||||
that:
|
||||
- create_address_scope is successful
|
||||
- create_address_scope is changed
|
||||
- create_address_scope.address_scope.name == address_scope_name
|
||||
- create_address_scope.address_scope.is_shared == False
|
||||
- create_address_scope.address_scope.ip_version == 4
|
||||
|
||||
- name: Update address scope
|
||||
openstack.cloud.address_scope:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ address_scope_name }}"
|
||||
shared: True
|
||||
ip_version: "4"
|
||||
register: update_address_scope
|
||||
|
||||
- name: Verify updated IPv4 address scope
|
||||
assert:
|
||||
that:
|
||||
- update_address_scope is successful
|
||||
- update_address_scope is changed
|
||||
- update_address_scope.address_scope.name == address_scope_name
|
||||
- update_address_scope.address_scope.is_shared == True
|
||||
- update_address_scope.address_scope.ip_version == 4
|
||||
|
||||
- name: Delete created address scope
|
||||
openstack.cloud.address_scope:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ address_scope_name }}"
|
||||
state: absent
|
||||
41
ci/roles/dns_zone_info/tasks/main.yml
Normal file
41
ci/roles/dns_zone_info/tasks/main.yml
Normal file
@@ -0,0 +1,41 @@
|
||||
---
|
||||
- name: Set random prefix
|
||||
set_fact:
|
||||
prefix: "{{ 99999999 | random | to_uuid | hash('md5') }}"
|
||||
|
||||
- name: Create dns zone
|
||||
openstack.cloud.dns_zone:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ (prefix + '.test.zone.') }}"
|
||||
email: test@example.net
|
||||
|
||||
- name: Getting info about dns zones
|
||||
openstack.cloud.dns_zone_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: zones
|
||||
|
||||
- name: assert result
|
||||
assert:
|
||||
that:
|
||||
- zones is success
|
||||
- zones is not changed
|
||||
- zones | length > 0
|
||||
|
||||
- name: Getting info about created zone
|
||||
openstack.cloud.dns_zone_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ (prefix + '.test.zone.') }}"
|
||||
register: zone
|
||||
|
||||
- name: assert result
|
||||
assert:
|
||||
that:
|
||||
- zone is success
|
||||
- zone is not changed
|
||||
- zone.zones | length == 1
|
||||
|
||||
- name: Drop created dns zone
|
||||
openstack.cloud.dns_zone:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ (prefix + '.test.zone.') }}"
|
||||
state: absent
|
||||
11
ci/roles/floating_ip_info/tasks/main.yml
Normal file
11
ci/roles/floating_ip_info/tasks/main.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
- 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
|
||||
@@ -1 +1,4 @@
|
||||
image_name: ansible_image
|
||||
image_tags:
|
||||
- test
|
||||
- ansible
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
name: "{{ image_name }}"
|
||||
filename: "{{ tmp_file.stdout }}"
|
||||
disk_format: raw
|
||||
tags: "{{ image_tags }}"
|
||||
register: image
|
||||
|
||||
- name: Get details of created image
|
||||
@@ -25,6 +26,7 @@
|
||||
assert:
|
||||
that:
|
||||
- "image_info_result.openstack_image.name == image_name"
|
||||
- "image_info_result.openstack_image.tags | sort == image_tags | sort"
|
||||
|
||||
- name: Delete raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
|
||||
3
ci/roles/loadbalancer/defaults/main.yml
Normal file
3
ci/roles/loadbalancer/defaults/main.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
network_name: network_lb
|
||||
subnet_name: subnet_lb
|
||||
lb_name: test_lb
|
||||
50
ci/roles/loadbalancer/tasks/main.yml
Normal file
50
ci/roles/loadbalancer/tasks/main.yml
Normal file
@@ -0,0 +1,50 @@
|
||||
|
||||
---
|
||||
- name: Create network {{ network_name }} for LB
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name }}"
|
||||
state: present
|
||||
|
||||
- name: Create subnet {{ subnet_name }} on network {{ network_name }} for LB
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
network_name: "{{ network_name }}"
|
||||
name: "{{ subnet_name }}"
|
||||
state: present
|
||||
enable_dhcp: true
|
||||
dns_nameservers:
|
||||
- 8.8.8.7
|
||||
- 8.8.8.8
|
||||
cidr: 192.168.0.0/24
|
||||
gateway_ip: 192.168.0.1
|
||||
allocation_pool_start: 192.168.0.2
|
||||
allocation_pool_end: 192.168.0.254
|
||||
|
||||
- name: Create loadbalancer - generic
|
||||
openstack.cloud.loadbalancer:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ lb_name }}"
|
||||
vip_subnet: "{{ subnet_name }}"
|
||||
timeout: 450
|
||||
|
||||
- name: Delete loadbalancer
|
||||
openstack.cloud.loadbalancer:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ lb_name }}"
|
||||
timeout: 150
|
||||
|
||||
- name: Delete subnet {{ subnet_name }} on network {{ network_name }}
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
network_name: "{{ network_name }}"
|
||||
name: "{{ subnet_name }}"
|
||||
state: absent
|
||||
|
||||
- name: Delete network {{ network_name }} of LB
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name }}"
|
||||
state: absent
|
||||
1
ci/roles/object_container/defaults/main.yml
Normal file
1
ci/roles/object_container/defaults/main.yml
Normal file
@@ -0,0 +1 @@
|
||||
container_name: "test-container"
|
||||
60
ci/roles/object_container/tasks/main.yml
Normal file
60
ci/roles/object_container/tasks/main.yml
Normal file
@@ -0,0 +1,60 @@
|
||||
---
|
||||
- module_defaults:
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
block:
|
||||
- name: Create an empty container
|
||||
openstack.cloud.object_container:
|
||||
container: "{{ container_name }}"
|
||||
register: container
|
||||
|
||||
- name: Verify container was created
|
||||
assert:
|
||||
that:
|
||||
- container is success
|
||||
- container is changed
|
||||
- container.container.name == container_name
|
||||
|
||||
- name: Set metadata for a container
|
||||
openstack.cloud.object_container:
|
||||
container: "{{ container_name }}"
|
||||
metadata: "Cache-Control='no-cache'"
|
||||
register: set_meta
|
||||
|
||||
- name: Verify container metadata was set
|
||||
assert:
|
||||
that:
|
||||
- set_meta is success
|
||||
- set_meta is changed
|
||||
|
||||
- name: Delete some keys from container metadata
|
||||
openstack.cloud.object_container:
|
||||
container: "{{ container_name }}"
|
||||
keys:
|
||||
- Cache-Control
|
||||
register: delete_meta
|
||||
|
||||
- name: Verify some keys from container metadata was deleted
|
||||
assert:
|
||||
that:
|
||||
- delete_meta is success
|
||||
- delete_meta is changed
|
||||
|
||||
- name: Delete container
|
||||
openstack.cloud.object_container:
|
||||
container: "{{ container_name }}"
|
||||
state: absent
|
||||
register: deleted
|
||||
|
||||
- name: Verify container was deleted
|
||||
assert:
|
||||
that:
|
||||
- deleted is success
|
||||
- deleted is changed
|
||||
|
||||
always:
|
||||
- name: Delete container
|
||||
openstack.cloud.object_container:
|
||||
container: "{{ container_name }}"
|
||||
state: absent
|
||||
ignore_errors: yes
|
||||
@@ -4,3 +4,6 @@ subnet_name: ansible_port_subnet
|
||||
port_name: ansible_port
|
||||
secgroup_name: ansible_port_secgroup
|
||||
no_security_groups: True
|
||||
binding_profile:
|
||||
"pci_slot": "0000:03:11.1"
|
||||
"physical_network": "provider"
|
||||
|
||||
@@ -88,6 +88,30 @@
|
||||
state: absent
|
||||
name: "{{ secgroup_name }}"
|
||||
|
||||
- name: Test port binding config (runs from train release sdk > 0.28)
|
||||
block:
|
||||
- name: Create port (with binding profile)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
binding_profile: "{{ binding_profile }}"
|
||||
register: port
|
||||
|
||||
- name: Assert binding:profile exists in created port
|
||||
assert:
|
||||
that: "port.port['binding:profile']"
|
||||
|
||||
- debug: var=port
|
||||
|
||||
- name: Delete port (with binding profile)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ port_name }}"
|
||||
when: sdk_version is version(0.28, '>')
|
||||
|
||||
- name: Delete subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
name: "{{ subnet_name }}"
|
||||
state: present
|
||||
cidr: 192.168.0.0/24
|
||||
gateway_ip: 192.168.0.1
|
||||
allocation_pool_start: 192.168.0.2
|
||||
allocation_pool_end: 192.168.0.8
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_volume_snapshot
|
||||
register: snap_info
|
||||
ignore_errors: sdk_version is version(0.49, '<')
|
||||
ignore_errors: sdk_version is version('0.49', '<')
|
||||
|
||||
- name: Create volume backup
|
||||
openstack.cloud.volume_backup:
|
||||
@@ -30,14 +30,14 @@
|
||||
display_name: ansible_volume_backup
|
||||
volume: ansible_volume
|
||||
register: vol_backup
|
||||
ignore_errors: sdk_version is version(0.49, '<')
|
||||
ignore_errors: sdk_version is version('0.49', '<')
|
||||
|
||||
- name: Get backup info
|
||||
openstack.cloud.volume_backup_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_volume_backup
|
||||
register: backup_info
|
||||
ignore_errors: sdk_version is version(0.49, '<')
|
||||
ignore_errors: sdk_version is version('0.49', '<')
|
||||
|
||||
- debug: var=vol
|
||||
|
||||
|
||||
@@ -106,6 +106,27 @@ then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# In case of Octavia enabled:
|
||||
_octavia_image_path="/tmp/test-only-amphora-x64-haproxy-ubuntu-bionic.qcow2"
|
||||
if systemctl list-units --full -all | grep -Fq "devstack@o-api.service" && \
|
||||
test -f "$_octavia_image_path"
|
||||
then
|
||||
# Upload apmhora image for Octavia to test load balancers
|
||||
OCTAVIA_AMP_IMAGE_FILE=${OCTAVIA_AMP_IMAGE_FILE:-"$_octavia_image_path"}
|
||||
OCTAVIA_AMP_IMAGE_NAME=${OCTAVIA_AMP_IMAGE_NAME:-"test-only-amphora-x64-haproxy-ubuntu-bionic"}
|
||||
OCTAVIA_AMP_IMAGE_SIZE=${OCTAVIA_AMP_IMAGE_SIZE:-3}
|
||||
openstack --os-cloud=${CLOUD} image create \
|
||||
--container-format bare \
|
||||
--disk-format qcow2 \
|
||||
--private \
|
||||
--file $OCTAVIA_AMP_IMAGE_FILE \
|
||||
--project service $OCTAVIA_AMP_IMAGE_NAME
|
||||
openstack --os-cloud=${CLOUD} image set --tag amphora $OCTAVIA_AMP_IMAGE_NAME
|
||||
# End of Octavia preparement
|
||||
else
|
||||
tag_opt="$tag_opt --skip-tags loadbalancer"
|
||||
fi
|
||||
|
||||
# Discover openstackSDK version
|
||||
SDK_VER=$(python -c "import openstack; print(openstack.version.__version__)")
|
||||
pushd ci/
|
||||
|
||||
@@ -4,12 +4,18 @@
|
||||
gather_facts: true
|
||||
|
||||
roles:
|
||||
- { role: address_scope, tags: address_scope }
|
||||
- { role: auth, tags: auth }
|
||||
- { role: client_config, tags: client_config }
|
||||
- { role: dns_zone_info, tags: dns_zone_info }
|
||||
- role: object_container
|
||||
tags: object_container
|
||||
when: sdk_version is version(0.18, '>=')
|
||||
- { role: group, tags: group }
|
||||
- role: dns
|
||||
tags: dns
|
||||
when: sdk_version is version(0.28, '>=')
|
||||
- { role: floating_ip_info, tags: floating_ip_info }
|
||||
- { role: image, tags: image }
|
||||
- { role: keypair, tags: keypair }
|
||||
- { role: keystone_domain, tags: keystone_domain }
|
||||
@@ -42,3 +48,5 @@
|
||||
- role: orchestration
|
||||
tags: orchestrate
|
||||
when: sdk_version is version("0.53.0", '>=')
|
||||
- role: loadbalancer
|
||||
tags: loadbalancer
|
||||
|
||||
@@ -33,4 +33,4 @@ build_ignore:
|
||||
- ansible_collections_openstack.egg-info
|
||||
- contrib
|
||||
- changelogs
|
||||
version: 1.3.0
|
||||
version: 1.5.0
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
action_groups:
|
||||
openstack:
|
||||
- address_scope
|
||||
- auth
|
||||
- baremetal_inspect
|
||||
- baremetal_inspect
|
||||
@@ -20,7 +21,7 @@ action_groups:
|
||||
- config
|
||||
- config
|
||||
- dns_zone
|
||||
- dns_zone
|
||||
- dns_zone_info
|
||||
- endpoint
|
||||
- endpoint
|
||||
- federation_idp
|
||||
@@ -32,6 +33,7 @@ action_groups:
|
||||
- federation_mapping_info
|
||||
- federation_mapping_info
|
||||
- floating_ip
|
||||
- floating_ip_info
|
||||
- group_assignment
|
||||
- group_assignment
|
||||
- host_aggregate
|
||||
@@ -66,6 +68,7 @@ action_groups:
|
||||
- network
|
||||
- networks_info
|
||||
- object
|
||||
- object_container
|
||||
- port
|
||||
- port_info
|
||||
- project
|
||||
@@ -163,6 +166,7 @@ action_groups:
|
||||
- network
|
||||
- networks_info
|
||||
- object
|
||||
- object_container
|
||||
- port
|
||||
- port_info
|
||||
- project
|
||||
|
||||
@@ -61,7 +61,6 @@ options:
|
||||
- Whether or not SSL API requests should be verified.
|
||||
- Before Ansible 2.3 this defaulted to C(yes).
|
||||
type: bool
|
||||
default: False
|
||||
aliases: [ verify ]
|
||||
ca_cert:
|
||||
description:
|
||||
|
||||
@@ -22,7 +22,7 @@ options:
|
||||
plugin:
|
||||
description: token that ensures this is a source file for the 'openstack' plugin.
|
||||
required: True
|
||||
choices: ['openstack']
|
||||
choices: ['openstack', 'openstack.cloud.openstack']
|
||||
show_all:
|
||||
description: toggles showing all vms vs only those with a working IP
|
||||
type: bool
|
||||
@@ -98,6 +98,10 @@ options:
|
||||
description: Add hosts to group based on Jinja2 conditionals.
|
||||
type: dictionary
|
||||
default: {}
|
||||
legacy_groups:
|
||||
description: Automatically create groups from host variables.
|
||||
type: bool
|
||||
default: true
|
||||
|
||||
extends_documentation_fragment:
|
||||
- inventory_cache
|
||||
@@ -108,7 +112,7 @@ extends_documentation_fragment:
|
||||
EXAMPLES = '''
|
||||
# file must be named openstack.yaml or openstack.yml
|
||||
# Make the plugin behave like the default behavior of the old script
|
||||
plugin: openstack
|
||||
plugin: openstack.cloud.openstack
|
||||
expand_hostvars: yes
|
||||
fail_on_errors: yes
|
||||
all_projects: yes
|
||||
@@ -155,7 +159,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||
msg = ''
|
||||
if not self._config_data:
|
||||
msg = 'File empty. this is not my config file'
|
||||
elif 'plugin' in self._config_data and self._config_data['plugin'] != self.NAME:
|
||||
elif 'plugin' in self._config_data and self._config_data['plugin'] not in (self.NAME, 'openstack'):
|
||||
msg = 'plugin config file, but not for us: %s' % self._config_data['plugin']
|
||||
elif 'plugin' not in self._config_data and 'clouds' not in self._config_data:
|
||||
msg = "it's not a plugin configuration nor a clouds.yaml file"
|
||||
@@ -361,8 +365,9 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||
openstack=server)
|
||||
self.inventory.add_host(current_host)
|
||||
|
||||
for group in self._get_groups_from_server(server, namegroup=namegroup):
|
||||
groups[group].append(current_host)
|
||||
if self.get_option('legacy_groups'):
|
||||
for group in self._get_groups_from_server(server, namegroup=namegroup):
|
||||
groups[group].append(current_host)
|
||||
|
||||
def verify_file(self, path):
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ def openstack_full_argument_spec(**kwargs):
|
||||
auth=dict(default=None, type='dict', no_log=True),
|
||||
region_name=dict(default=None),
|
||||
availability_zone=dict(default=None),
|
||||
validate_certs=dict(default=False, type='bool', aliases=['verify']),
|
||||
validate_certs=dict(default=None, type='bool', aliases=['verify']),
|
||||
ca_cert=dict(default=None, aliases=['cacert']),
|
||||
client_cert=dict(default=None, aliases=['cert']),
|
||||
client_key=dict(default=None, no_log=True, aliases=['key']),
|
||||
@@ -256,6 +256,7 @@ class OpenStackModule:
|
||||
**self.module_kwargs)
|
||||
self.params = self.ansible.params
|
||||
self.module_name = self.ansible._name
|
||||
self.check_mode = self.ansible.check_mode
|
||||
self.sdk_version = None
|
||||
self.results = {'changed': False}
|
||||
self.exit = self.exit_json = self.ansible.exit_json
|
||||
@@ -290,7 +291,7 @@ class OpenStackModule:
|
||||
"The '%s' module has been renamed to '%s' in openstack "
|
||||
"collection: openstack.cloud.%s" % (
|
||||
self.module_name, new_module_name, new_module_name),
|
||||
version='2.10')
|
||||
version='2.0.0', collection_name='openstack.cloud')
|
||||
|
||||
def openstack_cloud_from_module(self):
|
||||
"""Sets up connection to cloud using provided options. Checks if all
|
||||
|
||||
201
plugins/modules/address_scope.py
Normal file
201
plugins/modules/address_scope.py
Normal file
@@ -0,0 +1,201 @@
|
||||
#!/usr/bin/python
|
||||
# coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2021 by Uemit Seren <uemit.seren@gmail.com>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: address_scope
|
||||
short_description: Create or delete address scopes from OpenStack
|
||||
author: OpenStack Ansible SIG
|
||||
description:
|
||||
- Create or Delete address scopes from OpenStack.
|
||||
options:
|
||||
state:
|
||||
description:
|
||||
- Indicate desired state of the resource
|
||||
choices: ['present', 'absent']
|
||||
default: present
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Name to be give to the address scope
|
||||
required: true
|
||||
type: str
|
||||
project:
|
||||
description:
|
||||
- Unique name or ID of the project.
|
||||
type: str
|
||||
ip_version:
|
||||
description:
|
||||
- The IP version of the subnet 4 or 6
|
||||
default: 4
|
||||
type: str
|
||||
choices: ['4', '6']
|
||||
shared:
|
||||
description:
|
||||
- Whether this address scope is shared or not.
|
||||
type: bool
|
||||
default: 'no'
|
||||
extra_specs:
|
||||
description:
|
||||
- Dictionary with extra key/value pairs passed to the API
|
||||
required: false
|
||||
default: {}
|
||||
type: dict
|
||||
requirements:
|
||||
- "python >= 3.6"
|
||||
- "openstacksdk"
|
||||
|
||||
extends_documentation_fragment:
|
||||
- openstack.cloud.openstack
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# Create an IPv4 address scope.
|
||||
- openstack.cloud.address_scope:
|
||||
cloud: mycloud
|
||||
state: present
|
||||
name: my_adress_scope
|
||||
|
||||
# Create a shared IPv6 address scope for a given project.
|
||||
- openstack.cloud.address_scope:
|
||||
cloud: mycloud
|
||||
state: present
|
||||
ip_version: 6
|
||||
name: ipv6_address_scope
|
||||
project: myproj
|
||||
|
||||
# Delete address scope.
|
||||
- openstack.cloud.address_scope:
|
||||
cloud: mycloud
|
||||
state: absent
|
||||
name: my_adress_scope
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
address_scope:
|
||||
description: Dictionary describing the address scope.
|
||||
returned: On success when I(state) is 'present'
|
||||
type: complex
|
||||
contains:
|
||||
id:
|
||||
description: Address Scope ID.
|
||||
type: str
|
||||
sample: "474acfe5-be34-494c-b339-50f06aa143e4"
|
||||
name:
|
||||
description: Address Scope name.
|
||||
type: str
|
||||
sample: "my_address_scope"
|
||||
tenant_id:
|
||||
description: The tenant ID.
|
||||
type: str
|
||||
sample: "861174b82b43463c9edc5202aadc60ef"
|
||||
ip_version:
|
||||
description: The IP version of the subnet 4 or 6.
|
||||
type: str
|
||||
sample: "4"
|
||||
is_shared:
|
||||
description: Indicates whether this address scope is shared across all tenants.
|
||||
type: bool
|
||||
sample: false
|
||||
|
||||
'''
|
||||
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
class AddressScopeModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
name=dict(required=True),
|
||||
shared=dict(default=False, type='bool'),
|
||||
ip_version=dict(type='str', default='4', choices=['4', '6']),
|
||||
project=dict(default=None),
|
||||
extra_specs=dict(type='dict', default=dict())
|
||||
)
|
||||
|
||||
def _needs_update(self, address_scope, filters=None):
|
||||
"""Decide if the given address_scope needs an update.
|
||||
"""
|
||||
ip_version = int(self.params['ip_version'])
|
||||
if address_scope['is_shared'] != self.params['shared']:
|
||||
return True
|
||||
if ip_version and address_scope['ip_version'] != ip_version:
|
||||
self.fail_json(msg='Cannot update ip_version in existing address scope')
|
||||
return False
|
||||
|
||||
def _system_state_change(self, address_scope, filters=None):
|
||||
"""Check if the system state would be changed."""
|
||||
state = self.params['state']
|
||||
if state == 'absent' and address_scope:
|
||||
return True
|
||||
if state == 'present':
|
||||
if not address_scope:
|
||||
return True
|
||||
return self._needs_update(address_scope, filters)
|
||||
return False
|
||||
|
||||
def run(self):
|
||||
|
||||
state = self.params['state']
|
||||
name = self.params['name']
|
||||
shared = self.params['shared']
|
||||
ip_version = self.params['ip_version']
|
||||
project = self.params['project']
|
||||
extra_specs = self.params['extra_specs']
|
||||
|
||||
if project is not None:
|
||||
proj = self.conn.get_project(project)
|
||||
if proj is None:
|
||||
self.fail(msg='Project %s could not be found' % project)
|
||||
project_id = proj['id']
|
||||
else:
|
||||
project_id = self.conn.current_project_id
|
||||
|
||||
address_scope = self.conn.network.find_address_scope(name_or_id=name)
|
||||
if self.ansible.check_mode:
|
||||
self.exit_json(
|
||||
changed=self._system_state_change(address_scope)
|
||||
)
|
||||
|
||||
if state == 'present':
|
||||
changed = False
|
||||
|
||||
if not address_scope:
|
||||
kwargs = dict(
|
||||
name=name,
|
||||
ip_version=ip_version,
|
||||
is_shared=shared,
|
||||
tenant_id=project_id)
|
||||
dup_args = set(kwargs.keys()) & set(extra_specs.keys())
|
||||
if dup_args:
|
||||
raise ValueError('Duplicate key(s) {0} in extra_specs'
|
||||
.format(list(dup_args)))
|
||||
kwargs = dict(kwargs, **extra_specs)
|
||||
address_scope = self.conn.network.create_address_scope(**kwargs)
|
||||
changed = True
|
||||
else:
|
||||
if self._needs_update(address_scope):
|
||||
address_scope = self.conn.network.update_address_scope(address_scope['id'], is_shared=shared)
|
||||
changed = True
|
||||
else:
|
||||
changed = False
|
||||
self.exit_json(changed=changed, address_scope=address_scope, id=address_scope['id'])
|
||||
|
||||
elif state == 'absent':
|
||||
if not address_scope:
|
||||
self.exit(changed=False)
|
||||
else:
|
||||
self.conn.network.delete_address_scope(address_scope['id'])
|
||||
self.exit_json(changed=True)
|
||||
|
||||
|
||||
def main():
|
||||
module = AddressScopeModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -38,29 +38,24 @@ service_catalog:
|
||||
type: dict
|
||||
'''
|
||||
|
||||
import traceback
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
|
||||
class AuthModule(OpenStackModule):
|
||||
argument_spec = dict()
|
||||
module_kwargs = dict()
|
||||
|
||||
def run(self):
|
||||
self.exit_json(
|
||||
changed=False,
|
||||
ansible_facts=dict(
|
||||
auth_token=self.conn.auth_token,
|
||||
service_catalog=self.conn.service_catalog))
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
argument_spec = openstack_full_argument_spec()
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(argument_spec, **module_kwargs)
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
module.exit_json(
|
||||
changed=False,
|
||||
ansible_facts=dict(
|
||||
auth_token=cloud.auth_token,
|
||||
service_catalog=cloud.service_catalog))
|
||||
except Exception as e:
|
||||
module.fail_json(msg=str(e), exception=traceback.format_exc())
|
||||
module = AuthModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -242,7 +242,8 @@ def _parse_driver_info(sdk, module):
|
||||
info.update(info.pop(deprecated))
|
||||
module.deprecate("Suboption %s of the driver_info parameter of "
|
||||
"'openstack.cloud.baremetal_node' is deprecated"
|
||||
% deprecated, version='2.0.0')
|
||||
% deprecated, version='2.0.0',
|
||||
collection_name='openstack.cloud')
|
||||
return info
|
||||
|
||||
|
||||
|
||||
@@ -94,36 +94,11 @@ id:
|
||||
sample: "3292f020780b4d5baf27ff7e1d224c44"
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def _needs_update(module, service):
|
||||
if service.enabled != module.params['enabled']:
|
||||
return True
|
||||
if service.description is not None and \
|
||||
service.description != module.params['description']:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _system_state_change(module, service):
|
||||
state = module.params['state']
|
||||
if state == 'absent' and service:
|
||||
return True
|
||||
|
||||
if state == 'present':
|
||||
if service is None:
|
||||
return True
|
||||
return _needs_update(module, service)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class IdentityCatalogServiceModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
description=dict(default=None),
|
||||
enabled=dict(default=True, type='bool'),
|
||||
name=dict(required=True),
|
||||
@@ -131,58 +106,79 @@ def main():
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
)
|
||||
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(argument_spec,
|
||||
supports_check_mode=True,
|
||||
**module_kwargs)
|
||||
module_kwargs = dict(
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
description = module.params['description']
|
||||
enabled = module.params['enabled']
|
||||
name = module.params['name']
|
||||
state = module.params['state']
|
||||
service_type = module.params['service_type']
|
||||
def _needs_update(self, service):
|
||||
if service.enabled != self.params['enabled']:
|
||||
return True
|
||||
if service.description is not None and \
|
||||
service.description != self.params['description']:
|
||||
return True
|
||||
return False
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
services = cloud.search_services(name_or_id=name,
|
||||
filters=dict(type=service_type))
|
||||
def _system_state_change(self, service):
|
||||
state = self.params['state']
|
||||
if state == 'absent' and service:
|
||||
return True
|
||||
|
||||
if state == 'present':
|
||||
if service is None:
|
||||
return True
|
||||
return self._needs_update(service)
|
||||
|
||||
return False
|
||||
|
||||
def run(self):
|
||||
description = self.params['description']
|
||||
enabled = self.params['enabled']
|
||||
name = self.params['name']
|
||||
state = self.params['state']
|
||||
service_type = self.params['service_type']
|
||||
|
||||
services = self.conn.search_services(
|
||||
name_or_id=name, filters=dict(type=service_type))
|
||||
|
||||
if len(services) > 1:
|
||||
module.fail_json(msg='Service name %s and type %s are not unique' %
|
||||
(name, service_type))
|
||||
self.fail_json(
|
||||
msg='Service name %s and type %s are not unique'
|
||||
% (name, service_type))
|
||||
elif len(services) == 1:
|
||||
service = services[0]
|
||||
else:
|
||||
service = None
|
||||
|
||||
if module.check_mode:
|
||||
module.exit_json(changed=_system_state_change(module, service))
|
||||
if self.ansible.check_mode:
|
||||
self.exit_json(changed=self._system_state_change(service))
|
||||
|
||||
if state == 'present':
|
||||
if service is None:
|
||||
service = cloud.create_service(name=name, description=description,
|
||||
type=service_type, enabled=True)
|
||||
service = self.conn.create_service(
|
||||
name=name, description=description, type=service_type, enabled=True)
|
||||
changed = True
|
||||
else:
|
||||
if _needs_update(module, service):
|
||||
service = cloud.update_service(
|
||||
if self._needs_update(service):
|
||||
service = self.conn.update_service(
|
||||
service.id, name=name, type=service_type, enabled=enabled,
|
||||
description=description)
|
||||
changed = True
|
||||
else:
|
||||
changed = False
|
||||
module.exit_json(changed=changed, service=service, id=service.id)
|
||||
self.exit_json(changed=changed, service=service, id=service.id)
|
||||
|
||||
elif state == 'absent':
|
||||
if service is None:
|
||||
changed = False
|
||||
else:
|
||||
cloud.delete_service(service.id)
|
||||
self.conn.delete_service(service.id)
|
||||
changed = True
|
||||
module.exit_json(changed=changed)
|
||||
self.exit_json(changed=changed)
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
def main():
|
||||
module = IdentityCatalogServiceModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -206,31 +206,16 @@ EXAMPLES = '''
|
||||
node_count: 5
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def _parse_labels(labels):
|
||||
if isinstance(labels, str):
|
||||
labels_dict = {}
|
||||
for kv_str in labels.split(","):
|
||||
k, v = kv_str.split("=")
|
||||
labels_dict[k] = v
|
||||
return labels_dict
|
||||
if not labels:
|
||||
return {}
|
||||
return labels
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class CoeClusterModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
cluster_template_id=dict(required=True),
|
||||
discovery_url=dict(default=None),
|
||||
docker_volume_size=dict(type='int'),
|
||||
flavor_id=dict(default=None),
|
||||
keypair=dict(default=None),
|
||||
keypair=dict(default=None, no_log=False),
|
||||
labels=dict(default=None, type='raw'),
|
||||
master_count=dict(type='int', default=1),
|
||||
master_flavor_id=dict(default=None),
|
||||
@@ -239,35 +224,46 @@ def main():
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
timeout=dict(type='int', default=60),
|
||||
)
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(argument_spec, **module_kwargs)
|
||||
module_kwargs = dict()
|
||||
|
||||
params = module.params.copy()
|
||||
def _parse_labels(self, labels):
|
||||
if isinstance(labels, str):
|
||||
labels_dict = {}
|
||||
for kv_str in labels.split(","):
|
||||
k, v = kv_str.split("=")
|
||||
labels_dict[k] = v
|
||||
return labels_dict
|
||||
if not labels:
|
||||
return {}
|
||||
return labels
|
||||
|
||||
state = module.params['state']
|
||||
name = module.params['name']
|
||||
cluster_template_id = module.params['cluster_template_id']
|
||||
def run(self):
|
||||
params = self.params.copy()
|
||||
|
||||
kwargs = dict(
|
||||
discovery_url=module.params['discovery_url'],
|
||||
docker_volume_size=module.params['docker_volume_size'],
|
||||
flavor_id=module.params['flavor_id'],
|
||||
keypair=module.params['keypair'],
|
||||
labels=_parse_labels(params['labels']),
|
||||
master_count=module.params['master_count'],
|
||||
master_flavor_id=module.params['master_flavor_id'],
|
||||
node_count=module.params['node_count'],
|
||||
create_timeout=module.params['timeout'],
|
||||
)
|
||||
state = self.params['state']
|
||||
name = self.params['name']
|
||||
cluster_template_id = self.params['cluster_template_id']
|
||||
|
||||
kwargs = dict(
|
||||
discovery_url=self.params['discovery_url'],
|
||||
docker_volume_size=self.params['docker_volume_size'],
|
||||
flavor_id=self.params['flavor_id'],
|
||||
keypair=self.params['keypair'],
|
||||
labels=self._parse_labels(params['labels']),
|
||||
master_count=self.params['master_count'],
|
||||
master_flavor_id=self.params['master_flavor_id'],
|
||||
node_count=self.params['node_count'],
|
||||
create_timeout=self.params['timeout'],
|
||||
)
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
changed = False
|
||||
cluster = cloud.get_coe_cluster(name_or_id=name, filters={'cluster_template_id': cluster_template_id})
|
||||
cluster = self.conn.get_coe_cluster(
|
||||
name_or_id=name, filters={'cluster_template_id': cluster_template_id})
|
||||
|
||||
if state == 'present':
|
||||
if not cluster:
|
||||
cluster = cloud.create_coe_cluster(name, cluster_template_id=cluster_template_id, **kwargs)
|
||||
cluster = self.conn.create_coe_cluster(
|
||||
name, cluster_template_id=cluster_template_id, **kwargs)
|
||||
changed = True
|
||||
else:
|
||||
changed = False
|
||||
@@ -278,15 +274,18 @@ def main():
|
||||
# therefore try `id` first then `uuid`.
|
||||
cluster_id = cluster.get('id', cluster.get('uuid'))
|
||||
cluster['id'] = cluster['uuid'] = cluster_id
|
||||
module.exit_json(changed=changed, cluster=cluster, id=cluster_id)
|
||||
self.exit_json(changed=changed, cluster=cluster, id=cluster_id)
|
||||
elif state == 'absent':
|
||||
if not cluster:
|
||||
module.exit_json(changed=False)
|
||||
self.exit_json(changed=False)
|
||||
else:
|
||||
cloud.delete_coe_cluster(name)
|
||||
module.exit_json(changed=True)
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e), extra_data=e.extra_data)
|
||||
self.conn.delete_coe_cluster(name)
|
||||
self.exit_json(changed=True)
|
||||
|
||||
|
||||
def main():
|
||||
module = CoeClusterModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -281,26 +281,11 @@ EXAMPLES = '''
|
||||
public: no
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def _parse_labels(labels):
|
||||
if isinstance(labels, str):
|
||||
labels_dict = {}
|
||||
for kv_str in labels.split(","):
|
||||
k, v = kv_str.split("=")
|
||||
labels_dict[k] = v
|
||||
return labels_dict
|
||||
if not labels:
|
||||
return {}
|
||||
return labels
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class CoeClusterTemplateModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
coe=dict(required=True, choices=['kubernetes', 'swarm', 'mesos']),
|
||||
dns_nameserver=dict(default='8.8.8.8'),
|
||||
docker_storage_driver=dict(choices=['devicemapper', 'overlay', 'overlay2']),
|
||||
@@ -327,61 +312,76 @@ def main():
|
||||
tls_disabled=dict(type='bool', default=False),
|
||||
volume_driver=dict(choices=['cinder', 'rexray']),
|
||||
)
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(argument_spec, **module_kwargs)
|
||||
module_kwargs = dict()
|
||||
|
||||
params = module.params.copy()
|
||||
def _parse_labels(self, labels):
|
||||
if isinstance(labels, str):
|
||||
labels_dict = {}
|
||||
for kv_str in labels.split(","):
|
||||
k, v = kv_str.split("=")
|
||||
labels_dict[k] = v
|
||||
return labels_dict
|
||||
if not labels:
|
||||
return {}
|
||||
return labels
|
||||
|
||||
state = module.params['state']
|
||||
name = module.params['name']
|
||||
coe = module.params['coe']
|
||||
image_id = module.params['image_id']
|
||||
def run(self):
|
||||
params = self.params.copy()
|
||||
|
||||
kwargs = dict(
|
||||
dns_nameserver=module.params['dns_nameserver'],
|
||||
docker_storage_driver=module.params['docker_storage_driver'],
|
||||
docker_volume_size=module.params['docker_volume_size'],
|
||||
external_network_id=module.params['external_network_id'],
|
||||
fixed_network=module.params['fixed_network'],
|
||||
fixed_subnet=module.params['fixed_subnet'],
|
||||
flavor_id=module.params['flavor_id'],
|
||||
floating_ip_enabled=module.params['floating_ip_enabled'],
|
||||
keypair_id=module.params['keypair_id'],
|
||||
labels=_parse_labels(params['labels']),
|
||||
http_proxy=module.params['http_proxy'],
|
||||
https_proxy=module.params['https_proxy'],
|
||||
master_lb_enabled=module.params['master_lb_enabled'],
|
||||
master_flavor_id=module.params['master_flavor_id'],
|
||||
network_driver=module.params['network_driver'],
|
||||
no_proxy=module.params['no_proxy'],
|
||||
public=module.params['public'],
|
||||
registry_enabled=module.params['registry_enabled'],
|
||||
server_type=module.params['server_type'],
|
||||
tls_disabled=module.params['tls_disabled'],
|
||||
volume_driver=module.params['volume_driver'],
|
||||
)
|
||||
state = self.params['state']
|
||||
name = self.params['name']
|
||||
coe = self.params['coe']
|
||||
image_id = self.params['image_id']
|
||||
|
||||
kwargs = dict(
|
||||
dns_nameserver=self.params['dns_nameserver'],
|
||||
docker_storage_driver=self.params['docker_storage_driver'],
|
||||
docker_volume_size=self.params['docker_volume_size'],
|
||||
external_network_id=self.params['external_network_id'],
|
||||
fixed_network=self.params['fixed_network'],
|
||||
fixed_subnet=self.params['fixed_subnet'],
|
||||
flavor_id=self.params['flavor_id'],
|
||||
floating_ip_enabled=self.params['floating_ip_enabled'],
|
||||
keypair_id=self.params['keypair_id'],
|
||||
labels=self._parse_labels(params['labels']),
|
||||
http_proxy=self.params['http_proxy'],
|
||||
https_proxy=self.params['https_proxy'],
|
||||
master_lb_enabled=self.params['master_lb_enabled'],
|
||||
master_flavor_id=self.params['master_flavor_id'],
|
||||
network_driver=self.params['network_driver'],
|
||||
no_proxy=self.params['no_proxy'],
|
||||
public=self.params['public'],
|
||||
registry_enabled=self.params['registry_enabled'],
|
||||
server_type=self.params['server_type'],
|
||||
tls_disabled=self.params['tls_disabled'],
|
||||
volume_driver=self.params['volume_driver'],
|
||||
)
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
changed = False
|
||||
template = cloud.get_coe_cluster_template(name_or_id=name, filters={'coe': coe, 'image_id': image_id})
|
||||
template = self.conn.get_coe_cluster_template(
|
||||
name_or_id=name, filters={'coe': coe, 'image_id': image_id})
|
||||
|
||||
if state == 'present':
|
||||
if not template:
|
||||
template = cloud.create_coe_cluster_template(name, coe=coe, image_id=image_id, **kwargs)
|
||||
template = self.conn.create_coe_cluster_template(
|
||||
name, coe=coe, image_id=image_id, **kwargs)
|
||||
changed = True
|
||||
else:
|
||||
changed = False
|
||||
|
||||
module.exit_json(changed=changed, cluster_template=template, id=template['uuid'])
|
||||
self.exit_json(
|
||||
changed=changed, cluster_template=template, id=template['uuid'])
|
||||
elif state == 'absent':
|
||||
if not template:
|
||||
module.exit_json(changed=False)
|
||||
self.exit_json(changed=False)
|
||||
else:
|
||||
cloud.delete_coe_cluster_template(name)
|
||||
module.exit_json(changed=True)
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e), extra_data=e.extra_data)
|
||||
self.conn.delete_coe_cluster_template(name)
|
||||
self.exit_json(changed=True)
|
||||
|
||||
|
||||
def main():
|
||||
module = CoeClusterTemplateModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -160,23 +160,11 @@ flavor:
|
||||
"aggregate_instance_extra_specs:pinned": false
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def _system_state_change(module, flavor):
|
||||
state = module.params['state']
|
||||
if state == 'present' and not flavor:
|
||||
return True
|
||||
if state == 'absent' and flavor:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class ComputeFlavorModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
state=dict(required=False, default='present',
|
||||
choices=['absent', 'present']),
|
||||
name=dict(required=True),
|
||||
@@ -194,25 +182,30 @@ def main():
|
||||
extra_specs=dict(required=False, default=None, type='dict'),
|
||||
)
|
||||
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(
|
||||
argument_spec,
|
||||
supports_check_mode=True,
|
||||
module_kwargs = dict(
|
||||
required_if=[
|
||||
('state', 'present', ['ram', 'vcpus', 'disk'])
|
||||
],
|
||||
**module_kwargs)
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
state = module.params['state']
|
||||
name = module.params['name']
|
||||
extra_specs = module.params['extra_specs'] or {}
|
||||
def _system_state_change(self, flavor):
|
||||
state = self.params['state']
|
||||
if state == 'present' and not flavor:
|
||||
return True
|
||||
if state == 'absent' and flavor:
|
||||
return True
|
||||
return False
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
flavor = cloud.get_flavor(name)
|
||||
def run(self):
|
||||
state = self.params['state']
|
||||
name = self.params['name']
|
||||
extra_specs = self.params['extra_specs'] or {}
|
||||
|
||||
if module.check_mode:
|
||||
module.exit_json(changed=_system_state_change(module, flavor))
|
||||
flavor = self.conn.get_flavor(name)
|
||||
|
||||
if self.ansible.check_mode:
|
||||
self.exit_json(changed=self._system_state_change(flavor))
|
||||
|
||||
if state == 'present':
|
||||
old_extra_specs = {}
|
||||
@@ -220,26 +213,29 @@ def main():
|
||||
|
||||
if flavor:
|
||||
old_extra_specs = flavor['extra_specs']
|
||||
for param_key in ['ram', 'vcpus', 'disk', 'ephemeral', 'swap', 'rxtx_factor', 'is_public']:
|
||||
if module.params[param_key] != flavor[param_key]:
|
||||
if flavor['swap'] == "":
|
||||
flavor['swap'] = 0
|
||||
for param_key in ['ram', 'vcpus', 'disk', 'ephemeral',
|
||||
'swap', 'rxtx_factor', 'is_public']:
|
||||
if self.params[param_key] != flavor[param_key]:
|
||||
require_update = True
|
||||
break
|
||||
|
||||
if flavor and require_update:
|
||||
cloud.delete_flavor(name)
|
||||
self.conn.delete_flavor(name)
|
||||
flavor = None
|
||||
|
||||
if not flavor:
|
||||
flavor = cloud.create_flavor(
|
||||
flavor = self.conn.create_flavor(
|
||||
name=name,
|
||||
ram=module.params['ram'],
|
||||
vcpus=module.params['vcpus'],
|
||||
disk=module.params['disk'],
|
||||
flavorid=module.params['flavorid'],
|
||||
ephemeral=module.params['ephemeral'],
|
||||
swap=module.params['swap'],
|
||||
rxtx_factor=module.params['rxtx_factor'],
|
||||
is_public=module.params['is_public']
|
||||
ram=self.params['ram'],
|
||||
vcpus=self.params['vcpus'],
|
||||
disk=self.params['disk'],
|
||||
flavorid=self.params['flavorid'],
|
||||
ephemeral=self.params['ephemeral'],
|
||||
swap=self.params['swap'],
|
||||
rxtx_factor=self.params['rxtx_factor'],
|
||||
is_public=self.params['is_public']
|
||||
)
|
||||
changed = True
|
||||
else:
|
||||
@@ -249,25 +245,26 @@ def main():
|
||||
unset_keys = set(old_extra_specs.keys()) - set(extra_specs.keys())
|
||||
|
||||
if unset_keys and not require_update:
|
||||
cloud.unset_flavor_specs(flavor['id'], unset_keys)
|
||||
self.conn.unset_flavor_specs(flavor['id'], unset_keys)
|
||||
|
||||
if old_extra_specs != new_extra_specs:
|
||||
cloud.set_flavor_specs(flavor['id'], extra_specs)
|
||||
self.conn.set_flavor_specs(flavor['id'], extra_specs)
|
||||
|
||||
changed = (changed or old_extra_specs != new_extra_specs)
|
||||
|
||||
module.exit_json(changed=changed,
|
||||
flavor=flavor,
|
||||
id=flavor['id'])
|
||||
self.exit_json(
|
||||
changed=changed, flavor=flavor, id=flavor['id'])
|
||||
|
||||
elif state == 'absent':
|
||||
if flavor:
|
||||
cloud.delete_flavor(name)
|
||||
module.exit_json(changed=True)
|
||||
module.exit_json(changed=False)
|
||||
self.conn.delete_flavor(name)
|
||||
self.exit_json(changed=True)
|
||||
self.exit_json(changed=False)
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
def main():
|
||||
module = ComputeFlavorModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -158,70 +158,59 @@ openstack_flavors:
|
||||
sample: true
|
||||
'''
|
||||
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class ComputeFlavorInfoModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
name=dict(required=False, default=None),
|
||||
ram=dict(required=False, default=None),
|
||||
vcpus=dict(required=False, default=None),
|
||||
limit=dict(required=False, default=None, type='int'),
|
||||
ephemeral=dict(required=False, default=None),
|
||||
)
|
||||
module_kwargs = openstack_module_kwargs(
|
||||
module_kwargs = dict(
|
||||
mutually_exclusive=[
|
||||
['name', 'ram'],
|
||||
['name', 'vcpus'],
|
||||
['name', 'ephemeral']
|
||||
]
|
||||
)
|
||||
module = AnsibleModule(argument_spec, **module_kwargs)
|
||||
is_old_facts = module._name == 'openstack.cloud.compute_flavor_facts'
|
||||
if is_old_facts:
|
||||
module.deprecate("The 'openstack.cloud.compute_flavor_facts' module has been renamed to 'openstack.cloud.compute_flavor_info', "
|
||||
"and the renamed one no longer returns ansible_facts", version='2.13')
|
||||
|
||||
name = module.params['name']
|
||||
vcpus = module.params['vcpus']
|
||||
ram = module.params['ram']
|
||||
ephemeral = module.params['ephemeral']
|
||||
limit = module.params['limit']
|
||||
deprecated_names = ('openstack.cloud.compute_flavor_facts')
|
||||
|
||||
filters = {}
|
||||
if vcpus:
|
||||
filters['vcpus'] = vcpus
|
||||
if ram:
|
||||
filters['ram'] = ram
|
||||
if ephemeral:
|
||||
filters['ephemeral'] = ephemeral
|
||||
def run(self):
|
||||
name = self.params['name']
|
||||
vcpus = self.params['vcpus']
|
||||
ram = self.params['ram']
|
||||
ephemeral = self.params['ephemeral']
|
||||
limit = self.params['limit']
|
||||
|
||||
filters = {}
|
||||
if vcpus:
|
||||
filters['vcpus'] = vcpus
|
||||
if ram:
|
||||
filters['ram'] = ram
|
||||
if ephemeral:
|
||||
filters['ephemeral'] = ephemeral
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
if name:
|
||||
flavors = cloud.search_flavors(filters={'name': name})
|
||||
flavors = self.conn.search_flavors(filters={'name': name})
|
||||
|
||||
else:
|
||||
flavors = cloud.list_flavors()
|
||||
flavors = self.conn.list_flavors()
|
||||
if filters:
|
||||
flavors = cloud.range_search(flavors, filters)
|
||||
flavors = self.conn.range_search(flavors, filters)
|
||||
|
||||
if limit is not None:
|
||||
flavors = flavors[:limit]
|
||||
|
||||
if is_old_facts:
|
||||
module.exit_json(changed=False,
|
||||
ansible_facts=dict(openstack_flavors=flavors))
|
||||
else:
|
||||
module.exit_json(changed=False,
|
||||
openstack_flavors=flavors)
|
||||
self.exit_json(changed=False, openstack_flavors=flavors)
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
def main():
|
||||
module = ComputeFlavorInfoModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
1
plugins/modules/container.py
Symbolic link
1
plugins/modules/container.py
Symbolic link
@@ -0,0 +1 @@
|
||||
object_container.py
|
||||
177
plugins/modules/dns_zone_info.py
Normal file
177
plugins/modules/dns_zone_info.py
Normal file
@@ -0,0 +1,177 @@
|
||||
#!/usr/bin/python
|
||||
# coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2021 by Open Telekom Cloud, operated by T-Systems International GmbH
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: dns_zone_info
|
||||
short_description: Getting information about dns zones
|
||||
author: OpenStack Ansible SIG
|
||||
description:
|
||||
- Getting information about dns zones. Output can be filtered.
|
||||
options:
|
||||
name:
|
||||
description:
|
||||
- Zone name.
|
||||
type: str
|
||||
type:
|
||||
description:
|
||||
- Zone type.
|
||||
choices: [primary, secondary]
|
||||
type: str
|
||||
email:
|
||||
description:
|
||||
- Email of the zone owner (only applies if zone_type is primary).
|
||||
type: str
|
||||
description:
|
||||
description:
|
||||
- Zone description.
|
||||
type: str
|
||||
ttl:
|
||||
description:
|
||||
- TTL (Time To Live) value in seconds.
|
||||
type: int
|
||||
|
||||
requirements:
|
||||
- "python >= 3.6"
|
||||
- "openstacksdk"
|
||||
|
||||
extends_documentation_fragment:
|
||||
- openstack.cloud.openstack
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# Create a zone named "example.net"
|
||||
- openstack.cloud.dns_zones:
|
||||
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
zone:
|
||||
description: Dictionary describing the zone.
|
||||
returned: On success when I(state) is 'present'.
|
||||
type: complex
|
||||
contains:
|
||||
action:
|
||||
description: Current action in progress on the resource.
|
||||
type: str
|
||||
sample: "CREATE"
|
||||
attributes:
|
||||
description: Key:Value pairs of information about this zone, and the pool the user would like to place \
|
||||
the zone in. This information can be used by the scheduler to place zones on the correct pool.
|
||||
type: dict
|
||||
sample: {"tier": "gold", "ha": "true"}
|
||||
created_at:
|
||||
description: Date / Time when resource was created.
|
||||
type: str
|
||||
sample: "2014-07-07T18:25:31.275934"
|
||||
description:
|
||||
description: Description for this zone.
|
||||
type: str
|
||||
sample: "This is an example zone."
|
||||
email:
|
||||
description: E-mail for the zone. Used in SOA records for the zone.
|
||||
type: str
|
||||
sample: "test@example.org"
|
||||
id:
|
||||
description: ID for the resource.
|
||||
type: int
|
||||
sample: "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3"
|
||||
links:
|
||||
description: Links to the resource, and other related resources. When a response has been broken into\
|
||||
pages, we will include a next link that should be followed to retrieve all results.
|
||||
type: dict
|
||||
sample: {"self": "https://127.0.0.1:9001/v2/zones/a86dba58-0043-4cc6-a1bb-69d5e86f3ca3"}
|
||||
masters:
|
||||
description: Mandatory for secondary zones. The servers to slave from to get DNS information.
|
||||
type: list
|
||||
sample: "[]"
|
||||
name:
|
||||
description: DNS Name for the zone.
|
||||
type: str
|
||||
sample: "test.test."
|
||||
pool_id:
|
||||
description: ID for the pool hosting this zone.
|
||||
type: str
|
||||
sample: "a86dba58-0043-4cc6-a1bb-69d5e86f3ca3"
|
||||
project_id:
|
||||
description: ID for the project that owns the resource.
|
||||
type: str
|
||||
sample: "4335d1f0-f793-11e2-b778-0800200c9a66"
|
||||
serial:
|
||||
description: Current serial number for the zone.
|
||||
type: int
|
||||
sample: 1404757531
|
||||
status:
|
||||
description: Status of the resource.
|
||||
type: str
|
||||
sample: "ACTIVE"
|
||||
ttl:
|
||||
description: TTL (Time to Live) for the zone.
|
||||
type: int
|
||||
sample: 7200
|
||||
type:
|
||||
description: Type of zone. PRIMARY is controlled by Designate, SECONDARY zones are slaved from another\
|
||||
DNS Server. Defaults to PRIMARY
|
||||
type: str
|
||||
sample: "PRIMARY"
|
||||
updated_at:
|
||||
description: Date / Time when resource last updated.
|
||||
type: str
|
||||
sample: "2014-07-07T18:25:31.275934"
|
||||
'''
|
||||
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
class DnsZoneInfoModule(OpenStackModule):
|
||||
|
||||
argument_spec = dict(
|
||||
name=dict(required=False, type='str'),
|
||||
type=dict(required=False, choices=['primary', 'secondary'], type='str'),
|
||||
email=dict(required=False, type='str'),
|
||||
description=dict(required=False, type='str'),
|
||||
ttl=dict(required=False, type='int')
|
||||
)
|
||||
|
||||
def run(self):
|
||||
|
||||
name = self.params['name']
|
||||
type = self.params['type']
|
||||
email = self.params['email']
|
||||
description = self.params['description']
|
||||
ttl = self.params['ttl']
|
||||
|
||||
kwargs = {}
|
||||
|
||||
if name:
|
||||
kwargs['name'] = name
|
||||
if type:
|
||||
kwargs['type'] = type
|
||||
if email:
|
||||
kwargs['email'] = email
|
||||
if description:
|
||||
kwargs['description'] = description
|
||||
if ttl:
|
||||
kwargs['ttl'] = ttl
|
||||
|
||||
data = []
|
||||
|
||||
for raw in self.conn.dns.zones(**kwargs):
|
||||
dt = raw.to_dict()
|
||||
dt.pop('location')
|
||||
data.append(dt)
|
||||
|
||||
self.exit_json(zones=data, changed=False)
|
||||
|
||||
|
||||
def main():
|
||||
module = DnsZoneInfoModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -103,35 +103,11 @@ endpoint:
|
||||
sample: True
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def _needs_update(module, endpoint):
|
||||
if endpoint.enabled != module.params['enabled']:
|
||||
return True
|
||||
if endpoint.url != module.params['url']:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _system_state_change(module, endpoint):
|
||||
state = module.params['state']
|
||||
if state == 'absent' and endpoint:
|
||||
return True
|
||||
|
||||
if state == 'present':
|
||||
if endpoint is None:
|
||||
return True
|
||||
return _needs_update(module, endpoint)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class IdentityEndpointModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
service=dict(type='str', required=True),
|
||||
endpoint_interface=dict(type='str', required=True, choices=['admin', 'public', 'internal']),
|
||||
url=dict(type='str', required=True),
|
||||
@@ -140,71 +116,89 @@ def main():
|
||||
state=dict(type='str', default='present', choices=['absent', 'present']),
|
||||
)
|
||||
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(argument_spec,
|
||||
supports_check_mode=True,
|
||||
**module_kwargs)
|
||||
module_kwargs = dict(
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
service_name_or_id = module.params['service']
|
||||
interface = module.params['endpoint_interface']
|
||||
url = module.params['url']
|
||||
region = module.params['region']
|
||||
enabled = module.params['enabled']
|
||||
state = module.params['state']
|
||||
def _needs_update(self, endpoint):
|
||||
if endpoint.enabled != self.params['enabled']:
|
||||
return True
|
||||
if endpoint.url != self.params['url']:
|
||||
return True
|
||||
return False
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
def _system_state_change(self, endpoint):
|
||||
state = self.params['state']
|
||||
if state == 'absent' and endpoint:
|
||||
return True
|
||||
|
||||
service = cloud.get_service(service_name_or_id)
|
||||
if state == 'present':
|
||||
if endpoint is None:
|
||||
return True
|
||||
return self._needs_update(endpoint)
|
||||
|
||||
return False
|
||||
|
||||
def run(self):
|
||||
service_name_or_id = self.params['service']
|
||||
interface = self.params['endpoint_interface']
|
||||
url = self.params['url']
|
||||
region = self.params['region']
|
||||
enabled = self.params['enabled']
|
||||
state = self.params['state']
|
||||
|
||||
service = self.conn.get_service(service_name_or_id)
|
||||
if service is None and state == 'absent':
|
||||
module.exit_json(changed=False)
|
||||
self.exit_json(changed=False)
|
||||
|
||||
elif service is None and state == 'present':
|
||||
module.fail_json(msg='Service %s does not exist' % service_name_or_id)
|
||||
self.fail_json(msg='Service %s does not exist' % service_name_or_id)
|
||||
|
||||
filters = dict(service_id=service.id, interface=interface)
|
||||
if region is not None:
|
||||
filters['region'] = region
|
||||
endpoints = cloud.search_endpoints(filters=filters)
|
||||
endpoints = self.conn.search_endpoints(filters=filters)
|
||||
|
||||
if len(endpoints) > 1:
|
||||
module.fail_json(msg='Service %s, interface %s and region %s are '
|
||||
'not unique' %
|
||||
(service_name_or_id, interface, region))
|
||||
self.fail_json(msg='Service %s, interface %s and region %s are '
|
||||
'not unique' %
|
||||
(service_name_or_id, interface, region))
|
||||
elif len(endpoints) == 1:
|
||||
endpoint = endpoints[0]
|
||||
else:
|
||||
endpoint = None
|
||||
|
||||
if module.check_mode:
|
||||
module.exit_json(changed=_system_state_change(module, endpoint))
|
||||
if self.ansible.check_mode:
|
||||
self.exit_json(changed=self._system_state_change(endpoint))
|
||||
|
||||
if state == 'present':
|
||||
if endpoint is None:
|
||||
result = cloud.create_endpoint(service_name_or_id=service,
|
||||
url=url, interface=interface,
|
||||
region=region, enabled=enabled)
|
||||
result = self.conn.create_endpoint(
|
||||
service_name_or_id=service, url=url, interface=interface,
|
||||
region=region, enabled=enabled)
|
||||
endpoint = result[0]
|
||||
changed = True
|
||||
else:
|
||||
if _needs_update(module, endpoint):
|
||||
endpoint = cloud.update_endpoint(
|
||||
if self._needs_update(endpoint):
|
||||
endpoint = self.conn.update_endpoint(
|
||||
endpoint.id, url=url, enabled=enabled)
|
||||
changed = True
|
||||
else:
|
||||
changed = False
|
||||
module.exit_json(changed=changed, endpoint=endpoint)
|
||||
self.exit_json(changed=changed, endpoint=endpoint)
|
||||
|
||||
elif state == 'absent':
|
||||
if endpoint is None:
|
||||
changed = False
|
||||
else:
|
||||
cloud.delete_endpoint(endpoint.id)
|
||||
self.conn.delete_endpoint(endpoint.id)
|
||||
changed = True
|
||||
module.exit_json(changed=changed)
|
||||
self.exit_json(changed=changed)
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
def main():
|
||||
module = IdentityEndpointModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -72,124 +72,11 @@ EXAMPLES = '''
|
||||
RETURN = '''
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import openstack_full_argument_spec
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import openstack_module_kwargs
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import openstack_cloud_from_module
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def normalize_idp(idp):
|
||||
"""
|
||||
Normalizes the IDP definitions so that the outputs are consistent with the
|
||||
parameters
|
||||
|
||||
- "enabled" (parameter) == "is_enabled" (SDK)
|
||||
- "name" (parameter) == "id" (SDK)
|
||||
"""
|
||||
if idp is None:
|
||||
return None
|
||||
|
||||
_idp = idp.to_dict()
|
||||
_idp['enabled'] = idp['is_enabled']
|
||||
_idp['name'] = idp['id']
|
||||
return _idp
|
||||
|
||||
|
||||
def delete_identity_provider(module, sdk, cloud, idp):
|
||||
"""
|
||||
Delete an existing Identity Provider
|
||||
|
||||
returns: the "Changed" state
|
||||
"""
|
||||
|
||||
if idp is None:
|
||||
return False
|
||||
|
||||
if module.check_mode:
|
||||
return True
|
||||
|
||||
try:
|
||||
cloud.identity.delete_identity_provider(idp)
|
||||
except sdk.exceptions.OpenStackCloudException as ex:
|
||||
module.fail_json(msg='Failed to delete identity provider: {0}'.format(str(ex)))
|
||||
return True
|
||||
|
||||
|
||||
def create_identity_provider(module, sdk, cloud, name):
|
||||
"""
|
||||
Create a new Identity Provider
|
||||
|
||||
returns: the "Changed" state and the new identity provider
|
||||
"""
|
||||
|
||||
if module.check_mode:
|
||||
return True, None
|
||||
|
||||
description = module.params.get('description')
|
||||
enabled = module.params.get('enabled')
|
||||
domain_id = module.params.get('domain_id')
|
||||
remote_ids = module.params.get('remote_ids')
|
||||
|
||||
if enabled is None:
|
||||
enabled = True
|
||||
if remote_ids is None:
|
||||
remote_ids = []
|
||||
|
||||
attributes = {
|
||||
'domain_id': domain_id,
|
||||
'enabled': enabled,
|
||||
'remote_ids': remote_ids,
|
||||
}
|
||||
if description is not None:
|
||||
attributes['description'] = description
|
||||
|
||||
try:
|
||||
idp = cloud.identity.create_identity_provider(id=name, **attributes)
|
||||
except sdk.exceptions.OpenStackCloudException as ex:
|
||||
module.fail_json(msg='Failed to create identity provider: {0}'.format(str(ex)))
|
||||
return (True, idp)
|
||||
|
||||
|
||||
def update_identity_provider(module, sdk, cloud, idp):
|
||||
"""
|
||||
Update an existing Identity Provider
|
||||
|
||||
returns: the "Changed" state and the new identity provider
|
||||
"""
|
||||
|
||||
description = module.params.get('description')
|
||||
enabled = module.params.get('enabled')
|
||||
domain_id = module.params.get('domain_id')
|
||||
remote_ids = module.params.get('remote_ids')
|
||||
|
||||
attributes = {}
|
||||
|
||||
if (description is not None) and (description != idp.description):
|
||||
attributes['description'] = description
|
||||
if (enabled is not None) and (enabled != idp.is_enabled):
|
||||
attributes['enabled'] = enabled
|
||||
if (domain_id is not None) and (domain_id != idp.domain_id):
|
||||
attributes['domain_id'] = domain_id
|
||||
if (remote_ids is not None) and (remote_ids != idp.remote_ids):
|
||||
attributes['remote_ids'] = remote_ids
|
||||
|
||||
if not attributes:
|
||||
return False, idp
|
||||
|
||||
if module.check_mode:
|
||||
return True, None
|
||||
|
||||
try:
|
||||
new_idp = cloud.identity.update_identity_provider(idp, **attributes)
|
||||
except sdk.exceptions.OpenStackCloudException as ex:
|
||||
module.fail_json(msg='Failed to update identity provider: {0}'.format(str(ex)))
|
||||
return (True, new_idp)
|
||||
|
||||
|
||||
def main():
|
||||
""" Module entry point """
|
||||
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class IdentityFederationIdpModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
name=dict(required=True, aliases=['id']),
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
description=dict(),
|
||||
@@ -197,45 +84,136 @@ def main():
|
||||
enabled=dict(type='bool', aliases=['is_enabled']),
|
||||
remote_ids=dict(type='list', elements='str'),
|
||||
)
|
||||
module_kwargs = openstack_module_kwargs(
|
||||
)
|
||||
module = AnsibleModule(
|
||||
argument_spec,
|
||||
module_kwargs = dict(
|
||||
supports_check_mode=True,
|
||||
**module_kwargs
|
||||
)
|
||||
|
||||
name = module.params.get('name')
|
||||
state = module.params.get('state')
|
||||
changed = False
|
||||
def normalize_idp(self, idp):
|
||||
"""
|
||||
Normalizes the IDP definitions so that the outputs are consistent with the
|
||||
parameters
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module, min_version="0.44")
|
||||
|
||||
try:
|
||||
idp = cloud.identity.get_identity_provider(name)
|
||||
except sdk.exceptions.ResourceNotFound:
|
||||
idp = None
|
||||
except sdk.exceptions.OpenStackCloudException as ex:
|
||||
module.fail_json(msg='Failed to get identity provider: {0}'.format(str(ex)))
|
||||
|
||||
if state == 'absent':
|
||||
if idp is not None:
|
||||
changed = delete_identity_provider(module, sdk, cloud, idp)
|
||||
module.exit_json(changed=changed)
|
||||
|
||||
# state == 'present'
|
||||
else:
|
||||
- "enabled" (parameter) == "is_enabled" (SDK)
|
||||
- "name" (parameter) == "id" (SDK)
|
||||
"""
|
||||
if idp is None:
|
||||
if module.params.get('domain_id') is None:
|
||||
module.fail_json(msg='A domain_id must be passed when creating'
|
||||
' an identity provider')
|
||||
(changed, idp) = create_identity_provider(module, sdk, cloud, name)
|
||||
idp = normalize_idp(idp)
|
||||
module.exit_json(changed=changed, identity_provider=idp)
|
||||
return None
|
||||
|
||||
(changed, new_idp) = update_identity_provider(module, sdk, cloud, idp)
|
||||
new_idp = normalize_idp(new_idp)
|
||||
module.exit_json(changed=changed, identity_provider=new_idp)
|
||||
_idp = idp.to_dict()
|
||||
_idp['enabled'] = idp['is_enabled']
|
||||
_idp['name'] = idp['id']
|
||||
return _idp
|
||||
|
||||
def delete_identity_provider(self, idp):
|
||||
"""
|
||||
Delete an existing Identity Provider
|
||||
|
||||
returns: the "Changed" state
|
||||
"""
|
||||
if idp is None:
|
||||
return False
|
||||
|
||||
if self.ansible.check_mode:
|
||||
return True
|
||||
|
||||
self.conn.identity.delete_identity_provider(idp)
|
||||
return True
|
||||
|
||||
def create_identity_provider(self, name):
|
||||
"""
|
||||
Create a new Identity Provider
|
||||
|
||||
returns: the "Changed" state and the new identity provider
|
||||
"""
|
||||
|
||||
if self.ansible.check_mode:
|
||||
return True, None
|
||||
|
||||
description = self.params.get('description')
|
||||
enabled = self.params.get('enabled')
|
||||
domain_id = self.params.get('domain_id')
|
||||
remote_ids = self.params.get('remote_ids')
|
||||
|
||||
if enabled is None:
|
||||
enabled = True
|
||||
if remote_ids is None:
|
||||
remote_ids = []
|
||||
|
||||
attributes = {
|
||||
'domain_id': domain_id,
|
||||
'enabled': enabled,
|
||||
'remote_ids': remote_ids,
|
||||
}
|
||||
if description is not None:
|
||||
attributes['description'] = description
|
||||
|
||||
idp = self.conn.identity.create_identity_provider(id=name, **attributes)
|
||||
return (True, idp)
|
||||
|
||||
def update_identity_provider(self, idp):
|
||||
"""
|
||||
Update an existing Identity Provider
|
||||
|
||||
returns: the "Changed" state and the new identity provider
|
||||
"""
|
||||
|
||||
description = self.params.get('description')
|
||||
enabled = self.params.get('enabled')
|
||||
domain_id = self.params.get('domain_id')
|
||||
remote_ids = self.params.get('remote_ids')
|
||||
|
||||
attributes = {}
|
||||
|
||||
if (description is not None) and (description != idp.description):
|
||||
attributes['description'] = description
|
||||
if (enabled is not None) and (enabled != idp.is_enabled):
|
||||
attributes['enabled'] = enabled
|
||||
if (domain_id is not None) and (domain_id != idp.domain_id):
|
||||
attributes['domain_id'] = domain_id
|
||||
if (remote_ids is not None) and (remote_ids != idp.remote_ids):
|
||||
attributes['remote_ids'] = remote_ids
|
||||
|
||||
if not attributes:
|
||||
return False, idp
|
||||
|
||||
if self.ansible.check_mode:
|
||||
return True, None
|
||||
|
||||
new_idp = self.conn.identity.update_identity_provider(idp, **attributes)
|
||||
return (True, new_idp)
|
||||
|
||||
def run(self):
|
||||
""" Module entry point """
|
||||
|
||||
name = self.params.get('name')
|
||||
state = self.params.get('state')
|
||||
changed = False
|
||||
|
||||
idp = self.conn.identity.find_identity_provider(name)
|
||||
|
||||
if state == 'absent':
|
||||
if idp is not None:
|
||||
changed = self.delete_identity_provider(idp)
|
||||
self.exit_json(changed=changed)
|
||||
|
||||
# state == 'present'
|
||||
else:
|
||||
if idp is None:
|
||||
if self.params.get('domain_id') is None:
|
||||
self.fail_json(msg='A domain_id must be passed when creating'
|
||||
' an identity provider')
|
||||
(changed, idp) = self.create_identity_provider(name)
|
||||
idp = self.normalize_idp(idp)
|
||||
self.exit_json(changed=changed, identity_provider=idp)
|
||||
|
||||
(changed, new_idp) = self.update_identity_provider(idp)
|
||||
new_idp = self.normalize_idp(new_idp)
|
||||
self.exit_json(changed=changed, identity_provider=new_idp)
|
||||
|
||||
|
||||
def main():
|
||||
module = IdentityFederationIdpModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -39,62 +39,50 @@ EXAMPLES = '''
|
||||
RETURN = '''
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import openstack_full_argument_spec
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import openstack_module_kwargs
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import openstack_cloud_from_module
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def normalize_idp(idp):
|
||||
"""
|
||||
Normalizes the IDP definitions so that the outputs are consistent with the
|
||||
parameters
|
||||
class IdentityFederationIdpInfoModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
name=dict(aliases=['id']),
|
||||
)
|
||||
module_kwargs = dict(
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
- "enabled" (parameter) == "is_enabled" (SDK)
|
||||
- "name" (parameter) == "id" (SDK)
|
||||
"""
|
||||
if idp is None:
|
||||
return
|
||||
def normalize_idp(self, idp):
|
||||
"""
|
||||
Normalizes the IDP definitions so that the outputs are consistent with the
|
||||
parameters
|
||||
|
||||
_idp = idp.to_dict()
|
||||
_idp['enabled'] = idp['is_enabled']
|
||||
_idp['name'] = idp['id']
|
||||
return _idp
|
||||
- "enabled" (parameter) == "is_enabled" (SDK)
|
||||
- "name" (parameter) == "id" (SDK)
|
||||
"""
|
||||
if idp is None:
|
||||
return
|
||||
|
||||
_idp = idp.to_dict()
|
||||
_idp['enabled'] = idp['is_enabled']
|
||||
_idp['name'] = idp['id']
|
||||
return _idp
|
||||
|
||||
def run(self):
|
||||
""" Module entry point """
|
||||
|
||||
name = self.params.get('name')
|
||||
|
||||
if name:
|
||||
idp = self.normalize_idp(self.conn.identity.get_identity_provider(name))
|
||||
self.exit_json(changed=False, identity_providers=[idp])
|
||||
|
||||
else:
|
||||
providers = list(map(self.normalize_idp, self.conn.identity.identity_providers()))
|
||||
self.exit_json(changed=False, identity_providers=providers)
|
||||
|
||||
|
||||
def main():
|
||||
""" Module entry point """
|
||||
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
name=dict(aliases=['id']),
|
||||
)
|
||||
module_kwargs = openstack_module_kwargs(
|
||||
)
|
||||
module = AnsibleModule(
|
||||
argument_spec,
|
||||
supports_check_mode=True,
|
||||
**module_kwargs
|
||||
)
|
||||
|
||||
name = module.params.get('name')
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module, min_version="0.44")
|
||||
|
||||
if name:
|
||||
try:
|
||||
idp = normalize_idp(cloud.identity.get_identity_provider(name))
|
||||
except sdk.exceptions.ResourceNotFound:
|
||||
module.fail_json(msg='Failed to find identity provider')
|
||||
except sdk.exceptions.OpenStackCloudException as ex:
|
||||
module.fail_json(msg='Failed to get identity provider: {0}'.format(str(ex)))
|
||||
module.exit_json(changed=False, identity_providers=[idp])
|
||||
|
||||
else:
|
||||
try:
|
||||
providers = list(map(normalize_idp, cloud.identity.identity_providers()))
|
||||
except sdk.exceptions.OpenStackCloudException as ex:
|
||||
module.fail_json(msg='Failed to list identity providers: {0}'.format(str(ex)))
|
||||
module.exit_json(changed=False, identity_providers=providers)
|
||||
module = IdentityFederationIdpInfoModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -78,93 +78,11 @@ EXAMPLES = '''
|
||||
RETURN = '''
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import openstack_full_argument_spec
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import openstack_module_kwargs
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import openstack_cloud_from_module
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def normalize_mapping(mapping):
|
||||
"""
|
||||
Normalizes the mapping definitions so that the outputs are consistent with
|
||||
the parameters
|
||||
|
||||
- "name" (parameter) == "id" (SDK)
|
||||
"""
|
||||
if mapping is None:
|
||||
return None
|
||||
|
||||
_mapping = mapping.to_dict()
|
||||
_mapping['name'] = mapping['id']
|
||||
return _mapping
|
||||
|
||||
|
||||
def create_mapping(module, sdk, cloud, name):
|
||||
"""
|
||||
Attempt to create a Mapping
|
||||
|
||||
returns: A tuple containing the "Changed" state and the created mapping
|
||||
"""
|
||||
|
||||
if module.check_mode:
|
||||
return (True, None)
|
||||
|
||||
rules = module.params.get('rules')
|
||||
|
||||
try:
|
||||
mapping = cloud.identity.create_mapping(id=name, rules=rules)
|
||||
except sdk.exceptions.OpenStackCloudException as ex:
|
||||
module.fail_json(msg='Failed to create mapping: {0}'.format(str(ex)))
|
||||
return (True, mapping)
|
||||
|
||||
|
||||
def delete_mapping(module, sdk, cloud, mapping):
|
||||
"""
|
||||
Attempt to delete a Mapping
|
||||
|
||||
returns: the "Changed" state
|
||||
"""
|
||||
if mapping is None:
|
||||
return False
|
||||
|
||||
if module.check_mode:
|
||||
return True
|
||||
|
||||
try:
|
||||
cloud.identity.delete_mapping(mapping)
|
||||
except sdk.exceptions.OpenStackCloudException as ex:
|
||||
module.fail_json(msg='Failed to delete mapping: {0}'.format(str(ex)))
|
||||
return True
|
||||
|
||||
|
||||
def update_mapping(module, sdk, cloud, mapping):
|
||||
"""
|
||||
Attempt to delete a Mapping
|
||||
|
||||
returns: The "Changed" state and the the new mapping
|
||||
"""
|
||||
|
||||
current_rules = mapping.rules
|
||||
new_rules = module.params.get('rules')
|
||||
|
||||
# Nothing to do
|
||||
if current_rules == new_rules:
|
||||
return (False, mapping)
|
||||
|
||||
if module.check_mode:
|
||||
return (True, None)
|
||||
|
||||
try:
|
||||
new_mapping = cloud.identity.update_mapping(mapping, rules=new_rules)
|
||||
except sdk.exceptions.OpenStackCloudException as ex:
|
||||
module.fail_json(msg='Failed to update mapping: {0}'.format(str(ex)))
|
||||
return (True, new_mapping)
|
||||
|
||||
|
||||
def main():
|
||||
""" Module entry point """
|
||||
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class IdentityFederationMappingModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
name=dict(required=True, aliases=['id']),
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
rules=dict(type='list', elements='dict', options=dict(
|
||||
@@ -172,46 +90,107 @@ def main():
|
||||
remote=dict(required=True, type='list', elements='dict')
|
||||
)),
|
||||
)
|
||||
module_kwargs = openstack_module_kwargs(
|
||||
required_if=[('state', 'present', ['rules'])]
|
||||
)
|
||||
module = AnsibleModule(
|
||||
argument_spec,
|
||||
supports_check_mode=True,
|
||||
**module_kwargs
|
||||
module_kwargs = dict(
|
||||
required_if=[('state', 'present', ['rules'])],
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
name = module.params.get('name')
|
||||
state = module.params.get('state')
|
||||
changed = False
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module, min_version="0.44")
|
||||
|
||||
try:
|
||||
mapping = cloud.identity.get_mapping(name)
|
||||
except sdk.exceptions.ResourceNotFound:
|
||||
mapping = None
|
||||
except sdk.exceptions.OpenStackCloudException as ex:
|
||||
module.fail_json(msg='Failed to fetch mapping: {0}'.format(str(ex)))
|
||||
|
||||
if state == 'absent':
|
||||
if mapping is not None:
|
||||
changed = delete_mapping(module, sdk, cloud, mapping)
|
||||
module.exit_json(changed=changed)
|
||||
|
||||
# state == 'present'
|
||||
else:
|
||||
if len(module.params.get('rules')) < 1:
|
||||
module.fail_json(msg='At least one rule must be passed')
|
||||
def normalize_mapping(self, mapping):
|
||||
"""
|
||||
Normalizes the mapping definitions so that the outputs are consistent with
|
||||
the parameters
|
||||
|
||||
- "name" (parameter) == "id" (SDK)
|
||||
"""
|
||||
if mapping is None:
|
||||
(changed, mapping) = create_mapping(module, sdk, cloud, name)
|
||||
mapping = normalize_mapping(mapping)
|
||||
module.exit_json(changed=changed, mapping=mapping)
|
||||
return None
|
||||
|
||||
_mapping = mapping.to_dict()
|
||||
_mapping['name'] = mapping['id']
|
||||
return _mapping
|
||||
|
||||
def create_mapping(self, name):
|
||||
"""
|
||||
Attempt to create a Mapping
|
||||
|
||||
returns: A tuple containing the "Changed" state and the created mapping
|
||||
"""
|
||||
|
||||
if self.ansible.check_mode:
|
||||
return (True, None)
|
||||
|
||||
rules = self.params.get('rules')
|
||||
|
||||
mapping = self.conn.identity.create_mapping(id=name, rules=rules)
|
||||
return (True, mapping)
|
||||
|
||||
def delete_mapping(self, mapping):
|
||||
"""
|
||||
Attempt to delete a Mapping
|
||||
|
||||
returns: the "Changed" state
|
||||
"""
|
||||
if mapping is None:
|
||||
return False
|
||||
|
||||
if self.ansible.check_mode:
|
||||
return True
|
||||
|
||||
self.conn.identity.delete_mapping(mapping)
|
||||
return True
|
||||
|
||||
def update_mapping(self, mapping):
|
||||
"""
|
||||
Attempt to delete a Mapping
|
||||
|
||||
returns: The "Changed" state and the the new mapping
|
||||
"""
|
||||
|
||||
current_rules = mapping.rules
|
||||
new_rules = self.params.get('rules')
|
||||
|
||||
# Nothing to do
|
||||
if current_rules == new_rules:
|
||||
return (False, mapping)
|
||||
|
||||
if self.ansible.check_mode:
|
||||
return (True, None)
|
||||
|
||||
new_mapping = self.conn.identity.update_mapping(mapping, rules=new_rules)
|
||||
return (True, new_mapping)
|
||||
|
||||
def run(self):
|
||||
""" Module entry point """
|
||||
|
||||
name = self.params.get('name')
|
||||
state = self.params.get('state')
|
||||
changed = False
|
||||
|
||||
mapping = self.conn.identity.find_mapping(name)
|
||||
|
||||
if state == 'absent':
|
||||
if mapping is not None:
|
||||
changed = self.delete_mapping(mapping)
|
||||
self.exit_json(changed=changed)
|
||||
|
||||
# state == 'present'
|
||||
else:
|
||||
(changed, new_mapping) = update_mapping(module, sdk, cloud, mapping)
|
||||
new_mapping = normalize_mapping(new_mapping)
|
||||
module.exit_json(mapping=new_mapping, changed=changed)
|
||||
if len(self.params.get('rules')) < 1:
|
||||
self.fail_json(msg='At least one rule must be passed')
|
||||
|
||||
if mapping is None:
|
||||
(changed, mapping) = self.create_mapping(name)
|
||||
mapping = self.normalize_mapping(mapping)
|
||||
self.exit_json(changed=changed, mapping=mapping)
|
||||
else:
|
||||
(changed, new_mapping) = self.update_mapping(mapping)
|
||||
new_mapping = self.normalize_mapping(new_mapping)
|
||||
self.exit_json(mapping=new_mapping, changed=changed)
|
||||
|
||||
|
||||
def main():
|
||||
module = IdentityFederationMappingModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -38,60 +38,50 @@ EXAMPLES = '''
|
||||
RETURN = '''
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import openstack_full_argument_spec
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import openstack_module_kwargs
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import openstack_cloud_from_module
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def normalize_mapping(mapping):
|
||||
"""
|
||||
Normalizes the mapping definitions so that the outputs are consistent with the
|
||||
parameters
|
||||
class IdentityFederationMappingInfoModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
name=dict(aliases=['id']),
|
||||
)
|
||||
module_kwargs = dict(
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
- "name" (parameter) == "id" (SDK)
|
||||
"""
|
||||
if mapping is None:
|
||||
return None
|
||||
module_min_sdk_version = "0.44"
|
||||
|
||||
_mapping = mapping.to_dict()
|
||||
_mapping['name'] = mapping['id']
|
||||
return _mapping
|
||||
def normalize_mapping(self, mapping):
|
||||
"""
|
||||
Normalizes the mapping definitions so that the outputs are consistent with the
|
||||
parameters
|
||||
|
||||
- "name" (parameter) == "id" (SDK)
|
||||
"""
|
||||
if mapping is None:
|
||||
return None
|
||||
|
||||
_mapping = mapping.to_dict()
|
||||
_mapping['name'] = mapping['id']
|
||||
return _mapping
|
||||
|
||||
def run(self):
|
||||
""" Module entry point """
|
||||
name = self.params.get('name')
|
||||
|
||||
if name:
|
||||
mapping = self.normalize_mapping(
|
||||
self.conn.identity.get_mapping(name))
|
||||
self.exit_json(changed=False, mappings=[mapping])
|
||||
else:
|
||||
mappings = list(map(
|
||||
self.normalize_mapping, self.conn.identity.mappings()))
|
||||
self.exit_json(changed=False, mappings=mappings)
|
||||
|
||||
|
||||
def main():
|
||||
""" Module entry point """
|
||||
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
name=dict(aliases=['id']),
|
||||
)
|
||||
module_kwargs = openstack_module_kwargs(
|
||||
)
|
||||
module = AnsibleModule(
|
||||
argument_spec,
|
||||
supports_check_mode=True,
|
||||
**module_kwargs
|
||||
)
|
||||
|
||||
name = module.params.get('name')
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module, min_version="0.44")
|
||||
|
||||
if name:
|
||||
try:
|
||||
mapping = normalize_mapping(cloud.identity.get_mapping(name))
|
||||
except sdk.exceptions.ResourceNotFound:
|
||||
module.fail_json(msg='Failed to find mapping')
|
||||
except sdk.exceptions.OpenStackCloudException as ex:
|
||||
module.fail_json(msg='Failed to get mapping: {0}'.format(str(ex)))
|
||||
module.exit_json(changed=False, mappings=[mapping])
|
||||
|
||||
else:
|
||||
try:
|
||||
mappings = list(map(normalize_mapping, cloud.identity.mappings()))
|
||||
except sdk.exceptions.OpenStackCloudException as ex:
|
||||
module.fail_json(msg='Failed to list mappings: {0}'.format(str(ex)))
|
||||
module.exit_json(changed=False, mappings=mappings)
|
||||
module = IdentityFederationMappingInfoModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -118,23 +118,12 @@ EXAMPLES = '''
|
||||
server: cattle001
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, remove_values
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible.module_utils.basic import remove_values
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def _get_floating_ip(cloud, floating_ip_address):
|
||||
f_ips = cloud.search_floating_ips(
|
||||
filters={'floating_ip_address': floating_ip_address})
|
||||
if not f_ips:
|
||||
return None
|
||||
|
||||
return f_ips[0]
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class NetworkingFloatingIPModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
server=dict(required=True),
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
network=dict(required=False, default=None),
|
||||
@@ -148,107 +137,115 @@ def main():
|
||||
purge=dict(required=False, type='bool', default=False),
|
||||
)
|
||||
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(argument_spec, **module_kwargs)
|
||||
module_kwargs = dict()
|
||||
|
||||
server_name_or_id = module.params['server']
|
||||
state = module.params['state']
|
||||
network = module.params['network']
|
||||
floating_ip_address = module.params['floating_ip_address']
|
||||
reuse = module.params['reuse']
|
||||
fixed_address = module.params['fixed_address']
|
||||
nat_destination = module.params['nat_destination']
|
||||
wait = module.params['wait']
|
||||
timeout = module.params['timeout']
|
||||
purge = module.params['purge']
|
||||
def _get_floating_ip(self, floating_ip_address):
|
||||
f_ips = self.conn.search_floating_ips(
|
||||
filters={'floating_ip_address': floating_ip_address})
|
||||
if not f_ips:
|
||||
return None
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
return f_ips[0]
|
||||
|
||||
server = cloud.get_server(server_name_or_id)
|
||||
def run(self):
|
||||
server_name_or_id = self.params['server']
|
||||
state = self.params['state']
|
||||
network = self.params['network']
|
||||
floating_ip_address = self.params['floating_ip_address']
|
||||
reuse = self.params['reuse']
|
||||
fixed_address = self.params['fixed_address']
|
||||
nat_destination = self.params['nat_destination']
|
||||
wait = self.params['wait']
|
||||
timeout = self.params['timeout']
|
||||
purge = self.params['purge']
|
||||
|
||||
server = self.conn.get_server(server_name_or_id)
|
||||
if server is None:
|
||||
module.fail_json(
|
||||
self.fail_json(
|
||||
msg="server {0} not found".format(server_name_or_id))
|
||||
|
||||
if state == 'present':
|
||||
# If f_ip already assigned to server, check that it matches
|
||||
# requirements.
|
||||
public_ip = cloud.get_server_public_ip(server)
|
||||
f_ip = _get_floating_ip(cloud, public_ip) if public_ip else public_ip
|
||||
public_ip = self.conn.get_server_public_ip(server)
|
||||
f_ip = self._get_floating_ip(public_ip) if public_ip else public_ip
|
||||
if f_ip:
|
||||
if network:
|
||||
network_id = cloud.get_network(name_or_id=network)["id"]
|
||||
network_id = self.conn.get_network(name_or_id=network)["id"]
|
||||
else:
|
||||
network_id = None
|
||||
# check if we have floating ip on given nat_destination network
|
||||
if nat_destination:
|
||||
nat_floating_addrs = [
|
||||
addr for addr in server.addresses.get(
|
||||
cloud.get_network(nat_destination)['name'], [])
|
||||
self.conn.get_network(nat_destination)['name'], [])
|
||||
if addr['addr'] == public_ip
|
||||
and addr['OS-EXT-IPS:type'] == 'floating'
|
||||
]
|
||||
|
||||
if len(nat_floating_addrs) == 0:
|
||||
module.fail_json(msg="server {server} already has a "
|
||||
"floating-ip on a different "
|
||||
"nat-destination than '{nat_destination}'"
|
||||
.format(server=server_name_or_id,
|
||||
nat_destination=nat_destination))
|
||||
self.fail_json(
|
||||
msg="server {server} already has a "
|
||||
"floating-ip on a different "
|
||||
"nat-destination than '{nat_destination}'"
|
||||
.format(server=server_name_or_id,
|
||||
nat_destination=nat_destination))
|
||||
|
||||
if all([fixed_address, f_ip.fixed_ip_address == fixed_address,
|
||||
network, f_ip.network != network_id]):
|
||||
# Current state definitely conflicts with requirements
|
||||
module.fail_json(msg="server {server} already has a "
|
||||
"floating-ip on requested "
|
||||
"interface but it doesn't match "
|
||||
"requested network {network}: {fip}"
|
||||
.format(server=server_name_or_id,
|
||||
network=network,
|
||||
fip=remove_values(f_ip,
|
||||
module.no_log_values)))
|
||||
self.fail_json(
|
||||
msg="server {server} already has a "
|
||||
"floating-ip on requested "
|
||||
"interface but it doesn't match "
|
||||
"requested network {network}: {fip}"
|
||||
.format(server=server_name_or_id,
|
||||
network=network,
|
||||
fip=remove_values(f_ip, self.no_log_values)))
|
||||
if not network or f_ip.network == network_id:
|
||||
# Requirements are met
|
||||
module.exit_json(changed=False, floating_ip=f_ip)
|
||||
self.exit_json(changed=False, floating_ip=f_ip)
|
||||
|
||||
# Requirements are vague enough to ignore existing f_ip and try
|
||||
# to create a new f_ip to the server.
|
||||
|
||||
server = cloud.add_ips_to_server(
|
||||
server = self.conn.add_ips_to_server(
|
||||
server=server, ips=floating_ip_address, ip_pool=network,
|
||||
reuse=reuse, fixed_address=fixed_address, wait=wait,
|
||||
timeout=timeout, nat_destination=nat_destination)
|
||||
fip_address = cloud.get_server_public_ip(server)
|
||||
fip_address = self.conn.get_server_public_ip(server)
|
||||
# Update the floating IP status
|
||||
f_ip = _get_floating_ip(cloud, fip_address)
|
||||
module.exit_json(changed=True, floating_ip=f_ip)
|
||||
f_ip = self._get_floating_ip(fip_address)
|
||||
self.exit_json(changed=True, floating_ip=f_ip)
|
||||
|
||||
elif state == 'absent':
|
||||
if floating_ip_address is None:
|
||||
if not server_name_or_id:
|
||||
module.fail_json(msg="either server or floating_ip_address are required")
|
||||
server = cloud.get_server(server_name_or_id)
|
||||
floating_ip_address = cloud.get_server_public_ip(server)
|
||||
self.fail_json(msg="either server or floating_ip_address are required")
|
||||
server = self.conn.get_server(server_name_or_id)
|
||||
floating_ip_address = self.conn.get_server_public_ip(server)
|
||||
|
||||
f_ip = _get_floating_ip(cloud, floating_ip_address)
|
||||
f_ip = self._get_floating_ip(floating_ip_address)
|
||||
|
||||
if not f_ip:
|
||||
# Nothing to detach
|
||||
module.exit_json(changed=False)
|
||||
self.exit_json(changed=False)
|
||||
changed = False
|
||||
if f_ip["fixed_ip_address"]:
|
||||
cloud.detach_ip_from_server(
|
||||
self.conn.detach_ip_from_server(
|
||||
server_id=server['id'], floating_ip_id=f_ip['id'])
|
||||
# Update the floating IP status
|
||||
f_ip = cloud.get_floating_ip(id=f_ip['id'])
|
||||
f_ip = self.conn.get_floating_ip(id=f_ip['id'])
|
||||
changed = True
|
||||
if purge:
|
||||
cloud.delete_floating_ip(f_ip['id'])
|
||||
module.exit_json(changed=True)
|
||||
module.exit_json(changed=changed, floating_ip=f_ip)
|
||||
self.conn.delete_floating_ip(f_ip['id'])
|
||||
self.exit_json(changed=True)
|
||||
self.exit_json(changed=changed, floating_ip=f_ip)
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e), extra_data=e.extra_data)
|
||||
|
||||
def main():
|
||||
module = NetworkingFloatingIPModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
211
plugins/modules/floating_ip_info.py
Normal file
211
plugins/modules/floating_ip_info.py
Normal file
@@ -0,0 +1,211 @@
|
||||
#!/usr/bin/python
|
||||
# coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2021 by Open Telekom Cloud, operated by T-Systems International GmbH
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: floating_ip_info
|
||||
short_description: Get information about floating ips
|
||||
author: OpenStack Ansible SIG
|
||||
description:
|
||||
- Get a generator of floating ips.
|
||||
options:
|
||||
description:
|
||||
description:
|
||||
- The description of a floating IP.
|
||||
type: str
|
||||
fixed_ip_address:
|
||||
description:
|
||||
- The fixed IP address associated with a floating IP address.
|
||||
type: str
|
||||
floating_ip_address:
|
||||
description:
|
||||
- The IP address of a floating IP.
|
||||
type: str
|
||||
floating_network:
|
||||
description:
|
||||
- The name or id of the network associated with a floating IP.
|
||||
type: str
|
||||
port:
|
||||
description:
|
||||
- The name or id of the port to which a floating IP is associated.
|
||||
type: str
|
||||
project_id:
|
||||
description:
|
||||
- The ID of the project a floating IP is associated with.
|
||||
type: str
|
||||
router:
|
||||
description:
|
||||
- The name or id of an associated router.
|
||||
type: str
|
||||
status:
|
||||
description:
|
||||
- The status of a floating IP, which can be ``ACTIVE``or ``DOWN``.
|
||||
choices: ['active', 'down']
|
||||
type: str
|
||||
requirements:
|
||||
- "python >= 3.6"
|
||||
- "openstacksdk"
|
||||
|
||||
extends_documentation_fragment:
|
||||
- openstack.cloud.openstack
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
floating_ips:
|
||||
description: The floating ip objects list.
|
||||
type: complex
|
||||
returned: On Success.
|
||||
contains:
|
||||
created_at:
|
||||
description: Timestamp at which the floating IP was assigned.
|
||||
type: str
|
||||
description:
|
||||
description: The description of a floating IP.
|
||||
type: str
|
||||
dns_domain:
|
||||
description: The DNS domain.
|
||||
type: str
|
||||
dns_name:
|
||||
description: The DNS name.
|
||||
type: str
|
||||
fixed_ip_address:
|
||||
description: The fixed IP address associated with a floating IP address.
|
||||
type: str
|
||||
floating_ip_address:
|
||||
description: The IP address of a floating IP.
|
||||
type: str
|
||||
floating_network_id:
|
||||
description: The id of the network associated with a floating IP.
|
||||
type: str
|
||||
id:
|
||||
description: Id of the floating ip.
|
||||
type: str
|
||||
name:
|
||||
description: Name of the floating ip.
|
||||
type: str
|
||||
port_details:
|
||||
description: The details of the port that this floating IP associates \
|
||||
with. Present if ``fip-port-details`` extension is loaded.
|
||||
type: str
|
||||
port_id:
|
||||
description: The port ID floating ip associated with.
|
||||
type: str
|
||||
project_id:
|
||||
description: The ID of the project this floating IP is associated with.
|
||||
type: str
|
||||
qos_policy_id:
|
||||
description: The ID of the QoS policy attached to the floating IP.
|
||||
type: str
|
||||
revision_number:
|
||||
description: Revision number.
|
||||
type: str
|
||||
router_id:
|
||||
description: The id of the router floating ip associated with.
|
||||
type: str
|
||||
status:
|
||||
description: The status of a floating IP, which can be ``ACTIVE``or ``DOWN``.\
|
||||
Can be 'ACTIVE' and 'DOWN'.
|
||||
type: str
|
||||
subnet_id:
|
||||
description: The id of the subnet the floating ip associated with.
|
||||
type: str
|
||||
tags:
|
||||
description: List of tags.
|
||||
type: str
|
||||
updated_at:
|
||||
description: Timestamp at which the floating IP was last updated.
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# Getting all floating ips
|
||||
- openstack.cloud.floating_ip_info:
|
||||
register: fips
|
||||
|
||||
# Getting fip by associated fixed IP address.
|
||||
- openstack.cloud.floating_ip_info:
|
||||
fixed_ip_address: 192.168.10.8
|
||||
register: fip
|
||||
|
||||
# Getting fip by associated router.
|
||||
- openstack.cloud.floating_ip_info:
|
||||
router: my-router
|
||||
register: fip
|
||||
'''
|
||||
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
class FloatingIPInfoModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
description=dict(required=False),
|
||||
fixed_ip_address=dict(required=False),
|
||||
floating_ip_address=dict(required=False),
|
||||
floating_network=dict(required=False),
|
||||
port=dict(required=False),
|
||||
project_id=dict(required=False),
|
||||
router=dict(required=False),
|
||||
status=dict(required=False, choices=['active', 'down']),
|
||||
)
|
||||
|
||||
def run(self):
|
||||
|
||||
description = self.params['description']
|
||||
fixed_ip_address = self.params['fixed_ip_address']
|
||||
floating_ip_address = self.params['floating_ip_address']
|
||||
floating_network = self.params['floating_network']
|
||||
port = self.params['port']
|
||||
project_id = self.params['project_id']
|
||||
router = self.params['router']
|
||||
status = self.params['status']
|
||||
|
||||
data = []
|
||||
query = {}
|
||||
if description:
|
||||
query['description'] = description
|
||||
if fixed_ip_address:
|
||||
query['fixed_ip_address'] = fixed_ip_address
|
||||
if floating_ip_address:
|
||||
query['floating_ip_address'] = floating_ip_address
|
||||
if floating_network:
|
||||
try:
|
||||
query['floating_network_id'] = self.conn.network.find_network(name_or_id=floating_network,
|
||||
ignore_missing=False).id
|
||||
except self.sdk.exceptions.ResourceNotFound:
|
||||
self.fail_json(msg="floating_network not found")
|
||||
if port:
|
||||
try:
|
||||
query['port_id'] = self.conn.network.find_port(name_or_id=port, ignore_missing=False).id
|
||||
except self.sdk.exceptions.ResourceNotFound:
|
||||
self.fail_json(msg="port not found")
|
||||
if project_id:
|
||||
query['project_id'] = project_id
|
||||
if router:
|
||||
try:
|
||||
query['router_id'] = self.conn.network.find_router(name_or_id=router, ignore_missing=False).id
|
||||
except self.sdk.exceptions.ResourceNotFound:
|
||||
self.fail_json(msg="router not found")
|
||||
if status:
|
||||
query['status'] = status.upper()
|
||||
|
||||
for raw in self.conn.network.ips(**query):
|
||||
dt = raw.to_dict()
|
||||
dt.pop('location')
|
||||
data.append(dt)
|
||||
|
||||
self.exit_json(
|
||||
changed=False,
|
||||
floating_ips=data
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
module = FloatingIPInfoModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -42,58 +42,54 @@ EXAMPLES = '''
|
||||
group: demo
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def _system_state_change(state, in_group):
|
||||
if state == 'present' and not in_group:
|
||||
return True
|
||||
if state == 'absent' and in_group:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class IdentityGroupAssignment(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
user=dict(required=True),
|
||||
group=dict(required=True),
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
)
|
||||
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(argument_spec,
|
||||
supports_check_mode=True,
|
||||
**module_kwargs)
|
||||
module_kwargs = dict(
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
user = module.params['user']
|
||||
group = module.params['group']
|
||||
state = module.params['state']
|
||||
def _system_state_change(self, state, in_group):
|
||||
if state == 'present' and not in_group:
|
||||
return True
|
||||
if state == 'absent' and in_group:
|
||||
return True
|
||||
return False
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
in_group = cloud.is_user_in_group(user, group)
|
||||
def run(self):
|
||||
user = self.params['user']
|
||||
group = self.params['group']
|
||||
state = self.params['state']
|
||||
|
||||
if module.check_mode:
|
||||
module.exit_json(changed=_system_state_change(state, in_group))
|
||||
in_group = self.conn.is_user_in_group(user, group)
|
||||
|
||||
if self.ansible.check_mode:
|
||||
self.exit_json(changed=self._system_state_change(state, in_group))
|
||||
|
||||
changed = False
|
||||
if state == 'present':
|
||||
if not in_group:
|
||||
cloud.add_user_to_group(user, group)
|
||||
self.conn.add_user_to_group(user, group)
|
||||
changed = True
|
||||
|
||||
elif state == 'absent':
|
||||
if in_group:
|
||||
cloud.remove_user_from_group(user, group)
|
||||
self.conn.remove_user_from_group(user, group)
|
||||
changed = True
|
||||
|
||||
module.exit_json(changed=changed)
|
||||
self.exit_json(changed=changed)
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e), extra_data=e.extra_data)
|
||||
|
||||
def main():
|
||||
module = IdentityGroupAssignment()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -77,69 +77,11 @@ RETURN = '''
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def _needs_update(module, aggregate):
|
||||
new_metadata = (module.params['metadata'] or {})
|
||||
|
||||
if module.params['availability_zone'] is not None:
|
||||
new_metadata['availability_zone'] = module.params['availability_zone']
|
||||
|
||||
if module.params['name'] != aggregate.name:
|
||||
return True
|
||||
if module.params['hosts'] is not None:
|
||||
if module.params['purge_hosts']:
|
||||
if set(module.params['hosts']) != set(aggregate.hosts):
|
||||
return True
|
||||
else:
|
||||
intersection = set(module.params['hosts']).intersection(set(aggregate.hosts))
|
||||
if set(module.params['hosts']) != intersection:
|
||||
return True
|
||||
if module.params['availability_zone'] is not None:
|
||||
if module.params['availability_zone'] != aggregate.availability_zone:
|
||||
return True
|
||||
if module.params['metadata'] is not None:
|
||||
if new_metadata != aggregate.metadata:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def _system_state_change(module, aggregate):
|
||||
state = module.params['state']
|
||||
if state == 'absent' and aggregate:
|
||||
return True
|
||||
|
||||
if state == 'present':
|
||||
if aggregate is None:
|
||||
return True
|
||||
return _needs_update(module, aggregate)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def _update_hosts(cloud, aggregate, hosts, purge_hosts):
|
||||
if hosts is None:
|
||||
return
|
||||
|
||||
hosts_to_add = set(hosts) - set(aggregate.hosts)
|
||||
for i in hosts_to_add:
|
||||
cloud.add_host_to_aggregate(aggregate.id, i)
|
||||
|
||||
if not purge_hosts:
|
||||
return
|
||||
|
||||
hosts_to_remove = set(aggregate.hosts) - set(hosts)
|
||||
for i in hosts_to_remove:
|
||||
cloud.remove_host_from_aggregate(aggregate.id, i)
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class ComputeHostAggregateModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
name=dict(required=True),
|
||||
metadata=dict(required=False, default=None, type='dict'),
|
||||
availability_zone=dict(required=False, default=None),
|
||||
@@ -148,24 +90,74 @@ def main():
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
)
|
||||
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(argument_spec,
|
||||
supports_check_mode=True,
|
||||
**module_kwargs)
|
||||
module_kwargs = dict(
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
name = module.params['name']
|
||||
metadata = module.params['metadata']
|
||||
availability_zone = module.params['availability_zone']
|
||||
hosts = module.params['hosts']
|
||||
purge_hosts = module.params['purge_hosts']
|
||||
state = module.params['state']
|
||||
def _needs_update(self, aggregate):
|
||||
new_metadata = (self.params['metadata'] or {})
|
||||
|
||||
if metadata is not None:
|
||||
metadata.pop('availability_zone', None)
|
||||
if self.params['availability_zone'] is not None:
|
||||
new_metadata['availability_zone'] = self.params['availability_zone']
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
aggregates = cloud.search_aggregates(name_or_id=name)
|
||||
if self.params['name'] != aggregate.name:
|
||||
return True
|
||||
if self.params['hosts'] is not None:
|
||||
if self.params['purge_hosts']:
|
||||
if set(self.params['hosts']) != set(aggregate.hosts):
|
||||
return True
|
||||
else:
|
||||
intersection = set(self.params['hosts']).intersection(set(aggregate.hosts))
|
||||
if set(self.params['hosts']) != intersection:
|
||||
return True
|
||||
if self.params['availability_zone'] is not None:
|
||||
if self.params['availability_zone'] != aggregate.availability_zone:
|
||||
return True
|
||||
if self.params['metadata'] is not None:
|
||||
if new_metadata != aggregate.metadata:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def _system_state_change(self, aggregate):
|
||||
state = self.params['state']
|
||||
if state == 'absent' and aggregate:
|
||||
return True
|
||||
|
||||
if state == 'present':
|
||||
if aggregate is None:
|
||||
return True
|
||||
return self._needs_update(aggregate)
|
||||
|
||||
return False
|
||||
|
||||
def _update_hosts(self, aggregate, hosts, purge_hosts):
|
||||
if hosts is None:
|
||||
return
|
||||
|
||||
hosts_to_add = set(hosts) - set(aggregate.get("hosts", []))
|
||||
for i in hosts_to_add:
|
||||
self.conn.add_host_to_aggregate(aggregate.id, i)
|
||||
|
||||
if not purge_hosts:
|
||||
return
|
||||
|
||||
hosts_to_remove = set(aggregate.get("hosts", [])) - set(hosts)
|
||||
for i in hosts_to_remove:
|
||||
self.conn.remove_host_from_aggregate(aggregate.id, i)
|
||||
|
||||
def run(self):
|
||||
name = self.params['name']
|
||||
metadata = self.params['metadata']
|
||||
availability_zone = self.params['availability_zone']
|
||||
hosts = self.params['hosts']
|
||||
purge_hosts = self.params['purge_hosts']
|
||||
state = self.params['state']
|
||||
|
||||
if metadata is not None:
|
||||
metadata.pop('availability_zone', None)
|
||||
|
||||
aggregates = self.conn.search_aggregates(name_or_id=name)
|
||||
|
||||
if len(aggregates) == 1:
|
||||
aggregate = aggregates[0]
|
||||
@@ -174,45 +166,48 @@ def main():
|
||||
else:
|
||||
raise Exception("Should not happen")
|
||||
|
||||
if module.check_mode:
|
||||
module.exit_json(changed=_system_state_change(module, aggregate))
|
||||
if self.ansible.check_mode:
|
||||
self.exit_json(changed=self._system_state_change(aggregate))
|
||||
|
||||
if state == 'present':
|
||||
if aggregate is None:
|
||||
aggregate = cloud.create_aggregate(name=name,
|
||||
availability_zone=availability_zone)
|
||||
_update_hosts(cloud, aggregate, hosts, False)
|
||||
aggregate = self.conn.create_aggregate(
|
||||
name=name, availability_zone=availability_zone)
|
||||
self._update_hosts(aggregate, hosts, False)
|
||||
if metadata:
|
||||
cloud.set_aggregate_metadata(aggregate.id, metadata)
|
||||
self.conn.set_aggregate_metadata(aggregate.id, metadata)
|
||||
changed = True
|
||||
else:
|
||||
if _needs_update(module, aggregate):
|
||||
if self._needs_update(aggregate):
|
||||
if availability_zone is not None:
|
||||
aggregate = cloud.update_aggregate(aggregate.id, name=name,
|
||||
availability_zone=availability_zone)
|
||||
aggregate = self.conn.update_aggregate(
|
||||
aggregate.id, name=name,
|
||||
availability_zone=availability_zone)
|
||||
if metadata is not None:
|
||||
metas = metadata
|
||||
for i in (set(aggregate.metadata.keys()) - set(metadata.keys())):
|
||||
if i != 'availability_zone':
|
||||
metas[i] = None
|
||||
cloud.set_aggregate_metadata(aggregate.id, metas)
|
||||
_update_hosts(cloud, aggregate, hosts, purge_hosts)
|
||||
self.conn.set_aggregate_metadata(aggregate.id, metas)
|
||||
self._update_hosts(aggregate, hosts, purge_hosts)
|
||||
changed = True
|
||||
else:
|
||||
changed = False
|
||||
module.exit_json(changed=changed)
|
||||
self.exit_json(changed=changed)
|
||||
|
||||
elif state == 'absent':
|
||||
if aggregate is None:
|
||||
changed = False
|
||||
else:
|
||||
_update_hosts(cloud, aggregate, [], True)
|
||||
cloud.delete_aggregate(aggregate.id)
|
||||
self._update_hosts(aggregate, [], True)
|
||||
self.conn.delete_aggregate(aggregate.id)
|
||||
changed = True
|
||||
module.exit_json(changed=changed)
|
||||
self.exit_json(changed=changed)
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
def main():
|
||||
module = ComputeHostAggregateModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -85,92 +85,86 @@ id:
|
||||
sample: "474acfe5-be34-494c-b339-50f06aa143e4"
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def _needs_update(module, domain):
|
||||
if module.params['description'] is not None and \
|
||||
domain.description != module.params['description']:
|
||||
return True
|
||||
if domain.enabled != module.params['enabled']:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _system_state_change(module, domain):
|
||||
state = module.params['state']
|
||||
if state == 'absent' and domain:
|
||||
return True
|
||||
|
||||
if state == 'present':
|
||||
if domain is None:
|
||||
return True
|
||||
return _needs_update(module, domain)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class IdentityDomainModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
name=dict(required=True),
|
||||
description=dict(default=None),
|
||||
enabled=dict(default=True, type='bool'),
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
)
|
||||
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(argument_spec,
|
||||
supports_check_mode=True,
|
||||
**module_kwargs)
|
||||
module_kwargs = dict(
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
name = module.params['name']
|
||||
description = module.params['description']
|
||||
enabled = module.params['enabled']
|
||||
state = module.params['state']
|
||||
def _needs_update(self, domain):
|
||||
if self.params['description'] is not None and \
|
||||
domain.description != self.params['description']:
|
||||
return True
|
||||
if domain.enabled != self.params['enabled']:
|
||||
return True
|
||||
return False
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
def _system_state_change(self, domain):
|
||||
state = self.params['state']
|
||||
if state == 'absent' and domain:
|
||||
return True
|
||||
|
||||
domains = cloud.search_domains(filters=dict(name=name))
|
||||
if state == 'present':
|
||||
if domain is None:
|
||||
return True
|
||||
return self._needs_update(domain)
|
||||
|
||||
return False
|
||||
|
||||
def run(self):
|
||||
name = self.params['name']
|
||||
description = self.params['description']
|
||||
enabled = self.params['enabled']
|
||||
state = self.params['state']
|
||||
|
||||
domains = self.conn.search_domains(filters=dict(name=name))
|
||||
|
||||
if len(domains) > 1:
|
||||
module.fail_json(msg='Domain name %s is not unique' % name)
|
||||
self.fail_json(msg='Domain name %s is not unique' % name)
|
||||
elif len(domains) == 1:
|
||||
domain = domains[0]
|
||||
else:
|
||||
domain = None
|
||||
|
||||
if module.check_mode:
|
||||
module.exit_json(changed=_system_state_change(module, domain))
|
||||
if self.ansible.check_mode:
|
||||
self.exit_json(changed=self._system_state_change(domain))
|
||||
|
||||
if state == 'present':
|
||||
if domain is None:
|
||||
domain = cloud.create_domain(
|
||||
domain = self.conn.create_domain(
|
||||
name=name, description=description, enabled=enabled)
|
||||
changed = True
|
||||
else:
|
||||
if _needs_update(module, domain):
|
||||
domain = cloud.update_domain(
|
||||
if self._needs_update(domain):
|
||||
domain = self.conn.update_domain(
|
||||
domain.id, name=name, description=description,
|
||||
enabled=enabled)
|
||||
changed = True
|
||||
else:
|
||||
changed = False
|
||||
module.exit_json(changed=changed, domain=domain, id=domain.id)
|
||||
self.exit_json(changed=changed, domain=domain, id=domain.id)
|
||||
|
||||
elif state == 'absent':
|
||||
if domain is None:
|
||||
changed = False
|
||||
else:
|
||||
cloud.delete_domain(domain.id)
|
||||
self.conn.delete_domain(domain.id)
|
||||
changed = True
|
||||
module.exit_json(changed=changed)
|
||||
self.exit_json(changed=changed)
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
def main():
|
||||
module = IdentityDomainModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -81,52 +81,42 @@ openstack_domains:
|
||||
type: bool
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class IdentityDomainInfoModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
name=dict(required=False, default=None),
|
||||
filters=dict(required=False, type='dict', default=None),
|
||||
)
|
||||
module_kwargs = openstack_module_kwargs(
|
||||
module_kwargs = dict(
|
||||
mutually_exclusive=[
|
||||
['name', 'filters'],
|
||||
]
|
||||
)
|
||||
module = AnsibleModule(argument_spec, **module_kwargs)
|
||||
is_old_facts = module._name == 'openstack.cloud.identity_domain_facts'
|
||||
if is_old_facts:
|
||||
module.deprecate("The 'openstack.cloud.identity_domain_facts' module has been renamed to 'openstack.cloud.identity_domain_info', "
|
||||
"and the renamed one no longer returns ansible_facts", version='2.13')
|
||||
|
||||
sdk, opcloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
name = module.params['name']
|
||||
filters = module.params['filters']
|
||||
deprecated_names = ('openstack.cloud.identity_domain_facts')
|
||||
|
||||
def run(self):
|
||||
name = self.params['name']
|
||||
filters = self.params['filters']
|
||||
|
||||
if name:
|
||||
# Let's suppose user is passing domain ID
|
||||
try:
|
||||
domains = opcloud.get_domain(name)
|
||||
domains = self.conn.get_domain(name)
|
||||
except Exception:
|
||||
domains = opcloud.search_domains(filters={'name': name})
|
||||
domains = self.conn.search_domains(filters={'name': name})
|
||||
|
||||
else:
|
||||
domains = opcloud.search_domains(filters)
|
||||
domains = self.conn.search_domains(filters)
|
||||
|
||||
if is_old_facts:
|
||||
module.exit_json(changed=False, ansible_facts=dict(
|
||||
openstack_domains=domains))
|
||||
else:
|
||||
module.exit_json(changed=False, openstack_domains=domains)
|
||||
self.exit_json(changed=False, openstack_domains=domains)
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
def main():
|
||||
module = IdentityDomainInfoModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -86,75 +86,71 @@ group:
|
||||
sample: "default"
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def _system_state_change(state, description, group):
|
||||
if state == 'present' and not group:
|
||||
return True
|
||||
if state == 'present' and description is not None and group.description != description:
|
||||
return True
|
||||
if state == 'absent' and group:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class IdentityGroupModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
name=dict(required=True),
|
||||
description=dict(required=False, default=None),
|
||||
domain_id=dict(required=False, default=None),
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
)
|
||||
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(argument_spec,
|
||||
supports_check_mode=True,
|
||||
**module_kwargs)
|
||||
module_kwargs = dict(
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
name = module.params.get('name')
|
||||
description = module.params.get('description')
|
||||
state = module.params.get('state')
|
||||
def _system_state_change(self, state, description, group):
|
||||
if state == 'present' and not group:
|
||||
return True
|
||||
if state == 'present' and description is not None and group.description != description:
|
||||
return True
|
||||
if state == 'absent' and group:
|
||||
return True
|
||||
return False
|
||||
|
||||
domain_id = module.params.pop('domain_id')
|
||||
def run(self):
|
||||
name = self.params.get('name')
|
||||
description = self.params.get('description')
|
||||
state = self.params.get('state')
|
||||
|
||||
domain_id = self.params.pop('domain_id')
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
if domain_id:
|
||||
group = cloud.get_group(name, filters={'domain_id': domain_id})
|
||||
group = self.conn.get_group(name, filters={'domain_id': domain_id})
|
||||
else:
|
||||
group = cloud.get_group(name)
|
||||
group = self.conn.get_group(name)
|
||||
|
||||
if module.check_mode:
|
||||
module.exit_json(changed=_system_state_change(state, description, group))
|
||||
if self.ansible.check_mode:
|
||||
self.exit_json(changed=self._system_state_change(state, description, group))
|
||||
|
||||
if state == 'present':
|
||||
if group is None:
|
||||
group = cloud.create_group(
|
||||
group = self.conn.create_group(
|
||||
name=name, description=description, domain=domain_id)
|
||||
changed = True
|
||||
else:
|
||||
if description is not None and group.description != description:
|
||||
group = cloud.update_group(
|
||||
group = self.conn.update_group(
|
||||
group.id, description=description)
|
||||
changed = True
|
||||
else:
|
||||
changed = False
|
||||
module.exit_json(changed=changed, group=group)
|
||||
self.exit_json(changed=changed, group=group)
|
||||
|
||||
elif state == 'absent':
|
||||
if group is None:
|
||||
changed = False
|
||||
else:
|
||||
cloud.delete_group(group.id)
|
||||
self.conn.delete_group(group.id)
|
||||
changed = True
|
||||
module.exit_json(changed=changed)
|
||||
self.exit_json(changed=changed)
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
def main():
|
||||
module = IdentityGroupModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -110,48 +110,45 @@ openstack_groups:
|
||||
type: bool
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import openstack_full_argument_spec, openstack_cloud_from_module
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class IdentityGroupInfoModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
name=dict(required=False, default=None),
|
||||
domain=dict(required=False, default=None),
|
||||
filters=dict(required=False, type='dict', default=None),
|
||||
)
|
||||
|
||||
module = AnsibleModule(argument_spec)
|
||||
|
||||
sdk, opcloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
name = module.params['name']
|
||||
domain = module.params['domain']
|
||||
filters = module.params['filters']
|
||||
def run(self):
|
||||
name = self.params['name']
|
||||
domain = self.params['domain']
|
||||
filters = self.params['filters']
|
||||
|
||||
if domain:
|
||||
try:
|
||||
# We assume admin is passing domain id
|
||||
dom = opcloud.get_domain(domain)['id']
|
||||
dom = self.conn.get_domain(domain)['id']
|
||||
domain = dom
|
||||
except Exception:
|
||||
# If we fail, maybe admin is passing a domain name.
|
||||
# Note that domains have unique names, just like id.
|
||||
dom = opcloud.search_domains(filters={'name': domain})
|
||||
dom = self.conn.search_domains(filters={'name': domain})
|
||||
if dom:
|
||||
domain = dom[0]['id']
|
||||
else:
|
||||
module.fail_json(msg='Domain name or ID does not exist')
|
||||
self.fail_json(msg='Domain name or ID does not exist')
|
||||
|
||||
if not filters:
|
||||
filters = {}
|
||||
|
||||
groups = opcloud.search_groups(name, filters, domain_id=domain)
|
||||
module.exit_json(changed=False, groups=groups)
|
||||
groups = self.conn.search_groups(name, filters, domain_id=domain)
|
||||
self.exit_json(changed=False, groups=groups)
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
def main():
|
||||
module = IdentityGroupInfoModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -59,58 +59,54 @@ role:
|
||||
sample: "demo"
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def _system_state_change(state, role):
|
||||
if state == 'present' and not role:
|
||||
return True
|
||||
if state == 'absent' and role:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class IdentityRoleModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
name=dict(required=True),
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
)
|
||||
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(argument_spec,
|
||||
supports_check_mode=True,
|
||||
**module_kwargs)
|
||||
module_kwargs = dict(
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
name = module.params.get('name')
|
||||
state = module.params.get('state')
|
||||
def _system_state_change(self, state, role):
|
||||
if state == 'present' and not role:
|
||||
return True
|
||||
if state == 'absent' and role:
|
||||
return True
|
||||
return False
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
role = cloud.get_role(name)
|
||||
def run(self):
|
||||
name = self.params.get('name')
|
||||
state = self.params.get('state')
|
||||
|
||||
if module.check_mode:
|
||||
module.exit_json(changed=_system_state_change(state, role))
|
||||
role = self.conn.get_role(name)
|
||||
|
||||
if self.ansible.check_mode:
|
||||
self.exit_json(changed=self._system_state_change(state, role))
|
||||
|
||||
if state == 'present':
|
||||
if role is None:
|
||||
role = cloud.create_role(name)
|
||||
role = self.conn.create_role(name)
|
||||
changed = True
|
||||
else:
|
||||
changed = False
|
||||
module.exit_json(changed=changed, role=role)
|
||||
self.exit_json(changed=changed, role=role)
|
||||
elif state == 'absent':
|
||||
if role is None:
|
||||
changed = False
|
||||
else:
|
||||
cloud.delete_role(name)
|
||||
self.conn.delete_role(name)
|
||||
changed = True
|
||||
module.exit_json(changed=changed)
|
||||
self.exit_json(changed=changed)
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
def main():
|
||||
module = IdentityRoleModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -131,54 +131,12 @@ user:
|
||||
type: str
|
||||
sample: "demouser"
|
||||
'''
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def _needs_update(params_dict, user):
|
||||
for k in params_dict:
|
||||
if k not in ('password', 'update_password') and user[k] != params_dict[k]:
|
||||
return True
|
||||
|
||||
# We don't get password back in the user object, so assume any supplied
|
||||
# password is a change.
|
||||
if (
|
||||
params_dict['password'] is not None
|
||||
and params_dict['update_password'] == 'always'
|
||||
):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def _get_domain_id(cloud, domain):
|
||||
try:
|
||||
# We assume admin is passing domain id
|
||||
domain_id = cloud.get_domain(domain)['id']
|
||||
except Exception:
|
||||
# If we fail, maybe admin is passing a domain name.
|
||||
# Note that domains have unique names, just like id.
|
||||
try:
|
||||
domain_id = cloud.search_domains(filters={'name': domain})[0]['id']
|
||||
except Exception:
|
||||
# Ok, let's hope the user is non-admin and passing a sane id
|
||||
domain_id = domain
|
||||
|
||||
return domain_id
|
||||
|
||||
|
||||
def _get_default_project_id(cloud, default_project, domain_id, module):
|
||||
project = cloud.get_project(default_project, domain_id=domain_id)
|
||||
if not project:
|
||||
module.fail_json(msg='Default project %s is not valid' % default_project)
|
||||
|
||||
return project['id']
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class IdentityUserModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
name=dict(required=True),
|
||||
password=dict(required=False, default=None, no_log=True),
|
||||
email=dict(required=False, default=None),
|
||||
@@ -190,47 +148,81 @@ def main():
|
||||
update_password=dict(default=None, choices=['always', 'on_create']),
|
||||
)
|
||||
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(
|
||||
argument_spec,
|
||||
**module_kwargs)
|
||||
module_kwargs = dict()
|
||||
|
||||
name = module.params['name']
|
||||
password = module.params.get('password')
|
||||
email = module.params['email']
|
||||
default_project = module.params['default_project']
|
||||
domain = module.params['domain']
|
||||
enabled = module.params['enabled']
|
||||
state = module.params['state']
|
||||
update_password = module.params['update_password']
|
||||
description = module.params['description']
|
||||
def _needs_update(self, params_dict, user):
|
||||
for k in params_dict:
|
||||
if k not in ('password', 'update_password') and user[k] != params_dict[k]:
|
||||
return True
|
||||
|
||||
# We don't get password back in the user object, so assume any supplied
|
||||
# password is a change.
|
||||
if (
|
||||
params_dict['password'] is not None
|
||||
and params_dict['update_password'] == 'always'
|
||||
):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def _get_domain_id(self, domain):
|
||||
try:
|
||||
# We assume admin is passing domain id
|
||||
domain_id = self.conn.get_domain(domain)['id']
|
||||
except Exception:
|
||||
# If we fail, maybe admin is passing a domain name.
|
||||
# Note that domains have unique names, just like id.
|
||||
try:
|
||||
domain_id = self.conn.search_domains(filters={'name': domain})[0]['id']
|
||||
except Exception:
|
||||
# Ok, let's hope the user is non-admin and passing a sane id
|
||||
domain_id = domain
|
||||
|
||||
return domain_id
|
||||
|
||||
def _get_default_project_id(self, default_project, domain_id):
|
||||
project = self.conn.get_project(default_project, domain_id=domain_id)
|
||||
if not project:
|
||||
self.fail_json(msg='Default project %s is not valid' % default_project)
|
||||
|
||||
return project['id']
|
||||
|
||||
def run(self):
|
||||
name = self.params['name']
|
||||
password = self.params.get('password')
|
||||
email = self.params['email']
|
||||
default_project = self.params['default_project']
|
||||
domain = self.params['domain']
|
||||
enabled = self.params['enabled']
|
||||
state = self.params['state']
|
||||
update_password = self.params['update_password']
|
||||
description = self.params['description']
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
domain_id = None
|
||||
if domain:
|
||||
domain_id = _get_domain_id(cloud, domain)
|
||||
user = cloud.get_user(name, domain_id=domain_id)
|
||||
domain_id = self._get_domain_id(domain)
|
||||
user = self.conn.get_user(name, domain_id=domain_id)
|
||||
else:
|
||||
user = cloud.get_user(name)
|
||||
user = self.conn.get_user(name)
|
||||
|
||||
if state == 'present':
|
||||
if update_password in ('always', 'on_create'):
|
||||
if not password:
|
||||
msg = "update_password is %s but a password value is missing" % update_password
|
||||
module.fail_json(msg=msg)
|
||||
self.fail_json(msg=msg)
|
||||
default_project_id = None
|
||||
if default_project:
|
||||
default_project_id = _get_default_project_id(cloud, default_project, domain_id, module)
|
||||
default_project_id = self._get_default_project_id(
|
||||
default_project, domain_id)
|
||||
|
||||
if user is None:
|
||||
if description is not None:
|
||||
user = cloud.create_user(
|
||||
user = self.conn.create_user(
|
||||
name=name, password=password, email=email,
|
||||
default_project=default_project_id, domain_id=domain_id,
|
||||
enabled=enabled, description=description)
|
||||
else:
|
||||
user = cloud.create_user(
|
||||
user = self.conn.create_user(
|
||||
name=name, password=password, email=email,
|
||||
default_project=default_project_id, domain_id=domain_id,
|
||||
enabled=enabled)
|
||||
@@ -246,47 +238,49 @@ def main():
|
||||
if default_project_id is not None:
|
||||
params_dict['default_project_id'] = default_project_id
|
||||
|
||||
if _needs_update(params_dict, user):
|
||||
if self._needs_update(params_dict, user):
|
||||
if update_password == 'always':
|
||||
if description is not None:
|
||||
user = cloud.update_user(
|
||||
user = self.conn.update_user(
|
||||
user['id'], password=password, email=email,
|
||||
default_project=default_project_id,
|
||||
domain_id=domain_id, enabled=enabled, description=description)
|
||||
else:
|
||||
user = cloud.update_user(
|
||||
user = self.conn.update_user(
|
||||
user['id'], password=password, email=email,
|
||||
default_project=default_project_id,
|
||||
domain_id=domain_id, enabled=enabled)
|
||||
else:
|
||||
if description is not None:
|
||||
user = cloud.update_user(
|
||||
user = self.conn.update_user(
|
||||
user['id'], email=email,
|
||||
default_project=default_project_id,
|
||||
domain_id=domain_id, enabled=enabled, description=description)
|
||||
else:
|
||||
user = cloud.update_user(
|
||||
user = self.conn.update_user(
|
||||
user['id'], email=email,
|
||||
default_project=default_project_id,
|
||||
domain_id=domain_id, enabled=enabled)
|
||||
changed = True
|
||||
else:
|
||||
changed = False
|
||||
module.exit_json(changed=changed, user=user)
|
||||
self.exit_json(changed=changed, user=user)
|
||||
|
||||
elif state == 'absent':
|
||||
if user is None:
|
||||
changed = False
|
||||
else:
|
||||
if domain:
|
||||
cloud.delete_user(user['id'], domain_id=domain_id)
|
||||
self.conn.delete_user(user['id'], domain_id=domain_id)
|
||||
else:
|
||||
cloud.delete_user(user['id'])
|
||||
self.conn.delete_user(user['id'])
|
||||
changed = True
|
||||
module.exit_json(changed=changed)
|
||||
self.exit_json(changed=changed)
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e), extra_data=e.extra_data)
|
||||
|
||||
def main():
|
||||
module = IdentityUserModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -107,61 +107,49 @@ openstack_users:
|
||||
type: str
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (
|
||||
openstack_full_argument_spec,
|
||||
openstack_cloud_from_module,
|
||||
)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class IdentityUserInfoModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
name=dict(required=False, default=None),
|
||||
domain=dict(required=False, default=None),
|
||||
filters=dict(required=False, type='dict', default=None),
|
||||
)
|
||||
|
||||
module = AnsibleModule(argument_spec)
|
||||
is_old_facts = module._name == 'openstack.cloud.identity_user_facts'
|
||||
if is_old_facts:
|
||||
module.deprecate("The 'openstack.cloud.identity_user_facts' module has been renamed to 'openstack.cloud.identity_user_info', "
|
||||
"and the renamed one no longer returns ansible_facts", version='2.13')
|
||||
deprecated_names = ('openstack.cloud.identity_user_facts')
|
||||
|
||||
sdk, opcloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
name = module.params['name']
|
||||
domain = module.params['domain']
|
||||
filters = module.params['filters']
|
||||
def run(self):
|
||||
name = self.params['name']
|
||||
domain = self.params['domain']
|
||||
filters = self.params['filters']
|
||||
|
||||
if domain:
|
||||
try:
|
||||
# We assume admin is passing domain id
|
||||
dom = opcloud.get_domain(domain)['id']
|
||||
dom = self.conn.get_domain(domain)['id']
|
||||
domain = dom
|
||||
except Exception:
|
||||
# If we fail, maybe admin is passing a domain name.
|
||||
# Note that domains have unique names, just like id.
|
||||
dom = opcloud.search_domains(filters={'name': domain})
|
||||
dom = self.conn.search_domains(filters={'name': domain})
|
||||
if dom:
|
||||
domain = dom[0]['id']
|
||||
else:
|
||||
module.fail_json(msg='Domain name or ID does not exist')
|
||||
self.fail_json(msg='Domain name or ID does not exist')
|
||||
|
||||
if not filters:
|
||||
filters = {}
|
||||
|
||||
filters['domain_id'] = domain
|
||||
|
||||
users = opcloud.search_users(name, filters)
|
||||
if is_old_facts:
|
||||
module.exit_json(changed=False, ansible_facts=dict(
|
||||
openstack_users=users))
|
||||
else:
|
||||
module.exit_json(changed=False, openstack_users=users)
|
||||
users = self.conn.search_users(name, filters)
|
||||
self.exit_json(changed=False, openstack_users=users)
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
def main():
|
||||
module = IdentityUserInfoModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -85,6 +85,12 @@ options:
|
||||
choices: [present, absent]
|
||||
default: present
|
||||
type: str
|
||||
tags:
|
||||
description:
|
||||
- List of tags to be applied to the image
|
||||
default: []
|
||||
type: list
|
||||
elements: str
|
||||
volume:
|
||||
description:
|
||||
- ID of a volume to create an image from.
|
||||
@@ -115,6 +121,8 @@ EXAMPLES = '''
|
||||
filename: cirros-0.3.0-x86_64-disk.img
|
||||
kernel: cirros-vmlinuz
|
||||
ramdisk: cirros-initrd
|
||||
tags:
|
||||
- custom
|
||||
properties:
|
||||
cpu_arch: x86_64
|
||||
distro: ubuntu
|
||||
@@ -147,95 +155,99 @@ EXAMPLES = '''
|
||||
name: myvol_image
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def main():
|
||||
class ImageModule(OpenStackModule):
|
||||
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
name=dict(required=True),
|
||||
id=dict(default=None),
|
||||
checksum=dict(default=None),
|
||||
disk_format=dict(default='qcow2', choices=['ami', 'ari', 'aki', 'vhd', 'vmdk', 'raw', 'qcow2', 'vdi', 'iso', 'vhdx', 'ploop']),
|
||||
deprecated_names = ('os_image', 'openstack.cloud.os_image')
|
||||
|
||||
argument_spec = dict(
|
||||
name=dict(required=True, type='str'),
|
||||
id=dict(type='str'),
|
||||
checksum=dict(type='str'),
|
||||
disk_format=dict(default='qcow2',
|
||||
choices=['ami', 'ari', 'aki', 'vhd', 'vmdk', 'raw', 'qcow2', 'vdi', 'iso', 'vhdx', 'ploop']),
|
||||
container_format=dict(default='bare', choices=['ami', 'aki', 'ari', 'bare', 'ovf', 'ova', 'docker']),
|
||||
owner=dict(default=None),
|
||||
owner=dict(type='str'),
|
||||
min_disk=dict(type='int', default=0),
|
||||
min_ram=dict(type='int', default=0),
|
||||
is_public=dict(type='bool', default=False),
|
||||
protected=dict(type='bool', default=False),
|
||||
filename=dict(default=None),
|
||||
ramdisk=dict(default=None),
|
||||
kernel=dict(default=None),
|
||||
filename=dict(type='str'),
|
||||
ramdisk=dict(type='str'),
|
||||
kernel=dict(type='str'),
|
||||
properties=dict(type='dict', default={}),
|
||||
volume=dict(default=None),
|
||||
volume=dict(type='str'),
|
||||
tags=dict(type='list', default=[], elements='str'),
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
)
|
||||
|
||||
module_kwargs = openstack_module_kwargs(
|
||||
module_kwargs = dict(
|
||||
mutually_exclusive=[['filename', 'volume']],
|
||||
)
|
||||
module = AnsibleModule(argument_spec, **module_kwargs)
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
def run(self):
|
||||
|
||||
changed = False
|
||||
if module.params['id']:
|
||||
image = cloud.get_image(name_or_id=module.params['id'])
|
||||
elif module.params['checksum']:
|
||||
image = cloud.get_image(name_or_id=module.params['name'], filters={'checksum': module.params['checksum']})
|
||||
if self.params['id']:
|
||||
image = self.conn.get_image(name_or_id=self.params['id'])
|
||||
elif self.params['checksum']:
|
||||
image = self.conn.get_image(name_or_id=self.params['name'], filters={'checksum': self.params['checksum']})
|
||||
else:
|
||||
image = cloud.get_image(name_or_id=module.params['name'])
|
||||
image = self.conn.get_image(name_or_id=self.params['name'])
|
||||
|
||||
if module.params['state'] == 'present':
|
||||
if self.params['state'] == 'present':
|
||||
if not image:
|
||||
kwargs = {}
|
||||
if module.params['id'] is not None:
|
||||
kwargs['id'] = module.params['id']
|
||||
image = cloud.create_image(
|
||||
name=module.params['name'],
|
||||
filename=module.params['filename'],
|
||||
disk_format=module.params['disk_format'],
|
||||
container_format=module.params['container_format'],
|
||||
wait=module.params['wait'],
|
||||
timeout=module.params['timeout'],
|
||||
is_public=module.params['is_public'],
|
||||
protected=module.params['protected'],
|
||||
min_disk=module.params['min_disk'],
|
||||
min_ram=module.params['min_ram'],
|
||||
volume=module.params['volume'],
|
||||
if self.params['id'] is not None:
|
||||
kwargs['id'] = self.params['id']
|
||||
image = self.conn.create_image(
|
||||
name=self.params['name'],
|
||||
filename=self.params['filename'],
|
||||
disk_format=self.params['disk_format'],
|
||||
container_format=self.params['container_format'],
|
||||
wait=self.params['wait'],
|
||||
timeout=self.params['timeout'],
|
||||
is_public=self.params['is_public'],
|
||||
protected=self.params['protected'],
|
||||
min_disk=self.params['min_disk'],
|
||||
min_ram=self.params['min_ram'],
|
||||
volume=self.params['volume'],
|
||||
tags=self.params['tags'],
|
||||
**kwargs
|
||||
)
|
||||
changed = True
|
||||
if not module.params['wait']:
|
||||
module.exit_json(changed=changed, image=image, id=image.id)
|
||||
if not self.params['wait']:
|
||||
self.exit(changed=changed, image=image, id=image.id)
|
||||
|
||||
cloud.update_image_properties(
|
||||
self.conn.update_image_properties(
|
||||
image=image,
|
||||
kernel=module.params['kernel'],
|
||||
ramdisk=module.params['ramdisk'],
|
||||
protected=module.params['protected'],
|
||||
**module.params['properties'])
|
||||
image = cloud.get_image(name_or_id=image.id)
|
||||
module.exit_json(changed=changed, image=image, id=image.id)
|
||||
kernel=self.params['kernel'],
|
||||
ramdisk=self.params['ramdisk'],
|
||||
protected=self.params['protected'],
|
||||
**self.params['properties'])
|
||||
if self.params['tags']:
|
||||
self.conn.image.update_image(image.id, tags=self.params['tags'])
|
||||
image = self.conn.get_image(name_or_id=image.id)
|
||||
self.exit(changed=changed, image=image, id=image.id)
|
||||
|
||||
elif module.params['state'] == 'absent':
|
||||
elif self.params['state'] == 'absent':
|
||||
if not image:
|
||||
changed = False
|
||||
else:
|
||||
cloud.delete_image(
|
||||
name_or_id=module.params['name'],
|
||||
wait=module.params['wait'],
|
||||
timeout=module.params['timeout'])
|
||||
self.conn.delete_image(
|
||||
name_or_id=self.params['name'],
|
||||
wait=self.params['wait'],
|
||||
timeout=self.params['timeout'])
|
||||
changed = True
|
||||
module.exit_json(changed=changed)
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e), extra_data=e.extra_data)
|
||||
self.exit(changed=changed)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
def main():
|
||||
module = ImageModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@@ -140,6 +140,10 @@ openstack_image:
|
||||
description: Size of the image.
|
||||
returned: success
|
||||
type: int
|
||||
tags:
|
||||
description: List of tags assigned to the image
|
||||
returned: success
|
||||
type: list
|
||||
'''
|
||||
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
@@ -60,151 +60,127 @@ EXAMPLES = '''
|
||||
RETURN = '''
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import openstack_full_argument_spec
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import openstack_module_kwargs
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import openstack_cloud_from_module
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def normalize_protocol(protocol):
|
||||
"""
|
||||
Normalizes the protocol definitions so that the outputs are consistent with the
|
||||
parameters
|
||||
|
||||
- "name" (parameter) == "id" (SDK)
|
||||
"""
|
||||
if protocol is None:
|
||||
return None
|
||||
|
||||
_protocol = protocol.to_dict()
|
||||
_protocol['name'] = protocol['id']
|
||||
# As of 0.44 SDK doesn't copy the URI parameters over, so let's add them
|
||||
_protocol['idp_id'] = protocol['idp_id']
|
||||
return _protocol
|
||||
|
||||
|
||||
def delete_protocol(module, sdk, cloud, protocol):
|
||||
"""
|
||||
Delete an existing Protocol
|
||||
|
||||
returns: the "Changed" state
|
||||
"""
|
||||
|
||||
if protocol is None:
|
||||
return False
|
||||
|
||||
if module.check_mode:
|
||||
return True
|
||||
|
||||
try:
|
||||
cloud.identity.delete_federation_protocol(None, protocol)
|
||||
except sdk.exceptions.OpenStackCloudException as ex:
|
||||
module.fail_json(msg='Failed to delete protocol: {0}'.format(str(ex)))
|
||||
return True
|
||||
|
||||
|
||||
def create_protocol(module, sdk, cloud, name):
|
||||
"""
|
||||
Create a new Protocol
|
||||
|
||||
returns: the "Changed" state and the new protocol
|
||||
"""
|
||||
|
||||
if module.check_mode:
|
||||
return True, None
|
||||
|
||||
idp_name = module.params.get('idp_id')
|
||||
mapping_id = module.params.get('mapping_id')
|
||||
|
||||
attributes = {
|
||||
'idp_id': idp_name,
|
||||
'mapping_id': mapping_id,
|
||||
}
|
||||
|
||||
try:
|
||||
protocol = cloud.identity.create_federation_protocol(id=name, **attributes)
|
||||
except sdk.exceptions.OpenStackCloudException as ex:
|
||||
module.fail_json(msg='Failed to create protocol: {0}'.format(str(ex)))
|
||||
return (True, protocol)
|
||||
|
||||
|
||||
def update_protocol(module, sdk, cloud, protocol):
|
||||
"""
|
||||
Update an existing Protocol
|
||||
|
||||
returns: the "Changed" state and the new protocol
|
||||
"""
|
||||
|
||||
mapping_id = module.params.get('mapping_id')
|
||||
|
||||
attributes = {}
|
||||
|
||||
if (mapping_id is not None) and (mapping_id != protocol.mapping_id):
|
||||
attributes['mapping_id'] = mapping_id
|
||||
|
||||
if not attributes:
|
||||
return False, protocol
|
||||
|
||||
if module.check_mode:
|
||||
return True, None
|
||||
|
||||
try:
|
||||
new_protocol = cloud.identity.update_federation_protocol(None, protocol, **attributes)
|
||||
except sdk.exceptions.OpenStackCloudException as ex:
|
||||
module.fail_json(msg='Failed to update protocol: {0}'.format(str(ex)))
|
||||
return (True, new_protocol)
|
||||
|
||||
|
||||
def main():
|
||||
""" Module entry point """
|
||||
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class IdentityFederationProtocolModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
name=dict(required=True, aliases=['id']),
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
idp_id=dict(required=True, aliases=['idp_name']),
|
||||
mapping_id=dict(aliases=['mapping_name']),
|
||||
)
|
||||
module_kwargs = openstack_module_kwargs(
|
||||
)
|
||||
module = AnsibleModule(
|
||||
argument_spec,
|
||||
supports_check_mode=True,
|
||||
**module_kwargs
|
||||
module_kwargs = dict(
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
name = module.params.get('name')
|
||||
state = module.params.get('state')
|
||||
idp = module.params.get('idp_id')
|
||||
changed = False
|
||||
def normalize_protocol(self, protocol):
|
||||
"""
|
||||
Normalizes the protocol definitions so that the outputs are consistent with the
|
||||
parameters
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module, min_version="0.44")
|
||||
|
||||
try:
|
||||
protocol = cloud.identity.get_federation_protocol(idp, name)
|
||||
except sdk.exceptions.ResourceNotFound:
|
||||
protocol = None
|
||||
except sdk.exceptions.OpenStackCloudException as ex:
|
||||
module.fail_json(msg='Failed to get protocol: {0}'.format(str(ex)))
|
||||
|
||||
if state == 'absent':
|
||||
if protocol is not None:
|
||||
changed = delete_protocol(module, sdk, cloud, protocol)
|
||||
module.exit_json(changed=changed)
|
||||
|
||||
# state == 'present'
|
||||
else:
|
||||
- "name" (parameter) == "id" (SDK)
|
||||
"""
|
||||
if protocol is None:
|
||||
if module.params.get('mapping_id') is None:
|
||||
module.fail_json(msg='A mapping_id must be passed when creating'
|
||||
' a protocol')
|
||||
(changed, protocol) = create_protocol(module, sdk, cloud, name)
|
||||
protocol = normalize_protocol(protocol)
|
||||
module.exit_json(changed=changed, protocol=protocol)
|
||||
return None
|
||||
|
||||
_protocol = protocol.to_dict()
|
||||
_protocol['name'] = protocol['id']
|
||||
# As of 0.44 SDK doesn't copy the URI parameters over, so let's add them
|
||||
_protocol['idp_id'] = protocol['idp_id']
|
||||
return _protocol
|
||||
|
||||
def delete_protocol(self, protocol):
|
||||
"""
|
||||
Delete an existing Protocol
|
||||
|
||||
returns: the "Changed" state
|
||||
"""
|
||||
if protocol is None:
|
||||
return False
|
||||
|
||||
if self.ansible.check_mode:
|
||||
return True
|
||||
|
||||
self.conn.identity.delete_federation_protocol(None, protocol)
|
||||
return True
|
||||
|
||||
def create_protocol(self, name):
|
||||
"""
|
||||
Create a new Protocol
|
||||
|
||||
returns: the "Changed" state and the new protocol
|
||||
"""
|
||||
if self.ansible.check_mode:
|
||||
return True, None
|
||||
|
||||
idp_name = self.params.get('idp_id')
|
||||
mapping_id = self.params.get('mapping_id')
|
||||
|
||||
attributes = {
|
||||
'idp_id': idp_name,
|
||||
'mapping_id': mapping_id,
|
||||
}
|
||||
|
||||
protocol = self.conn.identity.create_federation_protocol(id=name, **attributes)
|
||||
return (True, protocol)
|
||||
|
||||
def update_protocol(self, protocol):
|
||||
"""
|
||||
Update an existing Protocol
|
||||
|
||||
returns: the "Changed" state and the new protocol
|
||||
"""
|
||||
mapping_id = self.params.get('mapping_id')
|
||||
|
||||
attributes = {}
|
||||
|
||||
if (mapping_id is not None) and (mapping_id != protocol.mapping_id):
|
||||
attributes['mapping_id'] = mapping_id
|
||||
|
||||
if not attributes:
|
||||
return False, protocol
|
||||
|
||||
if self.ansible.check_mode:
|
||||
return True, None
|
||||
|
||||
new_protocol = self.conn.identity.update_federation_protocol(None, protocol, **attributes)
|
||||
return (True, new_protocol)
|
||||
|
||||
def run(self):
|
||||
""" Module entry point """
|
||||
name = self.params.get('name')
|
||||
state = self.params.get('state')
|
||||
idp = self.params.get('idp_id')
|
||||
changed = False
|
||||
|
||||
protocol = self.conn.identity.find_federation_protocol(idp, name)
|
||||
|
||||
if state == 'absent':
|
||||
if protocol is not None:
|
||||
changed = self.delete_protocol(protocol)
|
||||
self.exit_json(changed=changed)
|
||||
|
||||
# state == 'present'
|
||||
else:
|
||||
(changed, new_protocol) = update_protocol(module, sdk, cloud, protocol)
|
||||
new_protocol = normalize_protocol(new_protocol)
|
||||
module.exit_json(changed=changed, protocol=new_protocol)
|
||||
if protocol is None:
|
||||
if self.params.get('mapping_id') is None:
|
||||
self.fail_json(
|
||||
msg='A mapping_id must be passed when creating'
|
||||
' a protocol')
|
||||
(changed, protocol) = self.create_protocol(name)
|
||||
protocol = self.normalize_protocol(protocol)
|
||||
self.exit_json(changed=changed, protocol=protocol)
|
||||
|
||||
else:
|
||||
(changed, new_protocol) = self.update_protocol(protocol)
|
||||
new_protocol = self.normalize_protocol(new_protocol)
|
||||
self.exit_json(changed=changed, protocol=new_protocol)
|
||||
|
||||
|
||||
def main():
|
||||
module = IdentityFederationProtocolModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -45,65 +45,53 @@ EXAMPLES = '''
|
||||
RETURN = '''
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import openstack_full_argument_spec
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import openstack_module_kwargs
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import openstack_cloud_from_module
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def normalize_protocol(protocol):
|
||||
"""
|
||||
Normalizes the protocol definitions so that the outputs are consistent with the
|
||||
parameters
|
||||
|
||||
- "name" (parameter) == "id" (SDK)
|
||||
"""
|
||||
if protocol is None:
|
||||
return None
|
||||
|
||||
_protocol = protocol.to_dict()
|
||||
_protocol['name'] = protocol['id']
|
||||
# As of 0.44 SDK doesn't copy the URI parameters over, so let's add them
|
||||
_protocol['idp_id'] = protocol['idp_id']
|
||||
return _protocol
|
||||
|
||||
|
||||
def main():
|
||||
""" Module entry point """
|
||||
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class IdentityFederationProtocolInfoModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
name=dict(aliases=['id']),
|
||||
idp_id=dict(required=True, aliases=['idp_name']),
|
||||
)
|
||||
module_kwargs = openstack_module_kwargs(
|
||||
)
|
||||
module = AnsibleModule(
|
||||
argument_spec,
|
||||
supports_check_mode=True,
|
||||
**module_kwargs
|
||||
module_kwargs = dict(
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
name = module.params.get('name')
|
||||
idp = module.params.get('idp_id')
|
||||
def normalize_protocol(self, protocol):
|
||||
"""
|
||||
Normalizes the protocol definitions so that the outputs are consistent with the
|
||||
parameters
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module, min_version="0.44")
|
||||
- "name" (parameter) == "id" (SDK)
|
||||
"""
|
||||
if protocol is None:
|
||||
return None
|
||||
|
||||
if name:
|
||||
try:
|
||||
protocol = cloud.identity.get_federation_protocol(idp, name)
|
||||
protocol = normalize_protocol(protocol)
|
||||
except sdk.exceptions.ResourceNotFound:
|
||||
module.fail_json(msg='Failed to find protocol')
|
||||
except sdk.exceptions.OpenStackCloudException as ex:
|
||||
module.fail_json(msg='Failed to get protocol: {0}'.format(str(ex)))
|
||||
module.exit_json(changed=False, protocols=[protocol])
|
||||
_protocol = protocol.to_dict()
|
||||
_protocol['name'] = protocol['id']
|
||||
# As of 0.44 SDK doesn't copy the URI parameters over, so let's add them
|
||||
_protocol['idp_id'] = protocol['idp_id']
|
||||
return _protocol
|
||||
|
||||
else:
|
||||
try:
|
||||
protocols = list(map(normalize_protocol, cloud.identity.federation_protocols(idp)))
|
||||
except sdk.exceptions.OpenStackCloudException as ex:
|
||||
module.fail_json(msg='Failed to list protocols: {0}'.format(str(ex)))
|
||||
module.exit_json(changed=False, protocols=protocols)
|
||||
def run(self):
|
||||
""" Module entry point """
|
||||
|
||||
name = self.params.get('name')
|
||||
idp = self.params.get('idp_id')
|
||||
|
||||
if name:
|
||||
protocol = self.conn.identity.get_federation_protocol(idp, name)
|
||||
protocol = self.normalize_protocol(protocol)
|
||||
self.exit_json(changed=False, protocols=[protocol])
|
||||
|
||||
else:
|
||||
protocols = list(map(self.normalize_protocol, self.conn.identity.federation_protocols(idp)))
|
||||
self.exit_json(changed=False, protocols=protocols)
|
||||
|
||||
|
||||
def main():
|
||||
module = IdentityFederationProtocolInfoModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -143,41 +143,11 @@ EXAMPLES = '''
|
||||
|
||||
import time
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def _lb_wait_for_status(module, cloud, lb, status, failures, interval=5):
|
||||
"""Wait for load balancer to be in a particular provisioning status."""
|
||||
timeout = module.params['timeout']
|
||||
|
||||
total_sleep = 0
|
||||
if failures is None:
|
||||
failures = []
|
||||
|
||||
while total_sleep < timeout:
|
||||
lb = cloud.load_balancer.get_load_balancer(lb.id)
|
||||
if lb.provisioning_status == status:
|
||||
return None
|
||||
if lb.provisioning_status in failures:
|
||||
module.fail_json(
|
||||
msg="Load Balancer %s transitioned to failure state %s" %
|
||||
(lb.id, lb.provisioning_status)
|
||||
)
|
||||
|
||||
time.sleep(interval)
|
||||
total_sleep += interval
|
||||
|
||||
module.fail_json(
|
||||
msg="Timeout waiting for Load Balancer %s to transition to %s" %
|
||||
(lb.id, status)
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class LoadbalancerListenerModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
name=dict(required=True),
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
loadbalancer=dict(required=True),
|
||||
@@ -185,70 +155,98 @@ def main():
|
||||
choices=['HTTP', 'HTTPS', 'TCP', 'TERMINATED_HTTPS']),
|
||||
protocol_port=dict(default=80, type='int', required=False),
|
||||
)
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(argument_spec, **module_kwargs)
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
loadbalancer = module.params['loadbalancer']
|
||||
loadbalancer_id = None
|
||||
module_kwargs = dict()
|
||||
|
||||
def _lb_wait_for_status(self, lb, status, failures, interval=5):
|
||||
"""Wait for load balancer to be in a particular provisioning status."""
|
||||
timeout = self.params['timeout']
|
||||
|
||||
total_sleep = 0
|
||||
if failures is None:
|
||||
failures = []
|
||||
|
||||
while total_sleep < timeout:
|
||||
lb = self.conn.load_balancer.get_load_balancer(lb.id)
|
||||
if lb.provisioning_status == status:
|
||||
return None
|
||||
if lb.provisioning_status in failures:
|
||||
self.fail_json(
|
||||
msg="Load Balancer %s transitioned to failure state %s" %
|
||||
(lb.id, lb.provisioning_status)
|
||||
)
|
||||
|
||||
time.sleep(interval)
|
||||
total_sleep += interval
|
||||
|
||||
self.fail_json(
|
||||
msg="Timeout waiting for Load Balancer %s to transition to %s" %
|
||||
(lb.id, status)
|
||||
)
|
||||
|
||||
def run(self):
|
||||
loadbalancer = self.params['loadbalancer']
|
||||
loadbalancer_id = None
|
||||
|
||||
try:
|
||||
changed = False
|
||||
listener = cloud.load_balancer.find_listener(
|
||||
name_or_id=module.params['name'])
|
||||
listener = self.conn.load_balancer.find_listener(
|
||||
name_or_id=self.params['name'])
|
||||
|
||||
if module.params['state'] == 'present':
|
||||
if self.params['state'] == 'present':
|
||||
if not listener:
|
||||
lb = cloud.load_balancer.find_load_balancer(loadbalancer)
|
||||
lb = self.conn.load_balancer.find_load_balancer(loadbalancer)
|
||||
if not lb:
|
||||
module.fail_json(
|
||||
self.fail_json(
|
||||
msg='load balancer %s is not found' % loadbalancer
|
||||
)
|
||||
loadbalancer_id = lb.id
|
||||
|
||||
listener = cloud.load_balancer.create_listener(
|
||||
name=module.params['name'],
|
||||
listener = self.conn.load_balancer.create_listener(
|
||||
name=self.params['name'],
|
||||
loadbalancer_id=loadbalancer_id,
|
||||
protocol=module.params['protocol'],
|
||||
protocol_port=module.params['protocol_port'],
|
||||
protocol=self.params['protocol'],
|
||||
protocol_port=self.params['protocol_port'],
|
||||
)
|
||||
changed = True
|
||||
|
||||
if not module.params['wait']:
|
||||
module.exit_json(changed=changed,
|
||||
listener=listener.to_dict(),
|
||||
id=listener.id)
|
||||
if not self.params['wait']:
|
||||
self.exit_json(
|
||||
changed=changed, listener=listener.to_dict(),
|
||||
id=listener.id)
|
||||
|
||||
if module.params['wait']:
|
||||
if self.params['wait']:
|
||||
# Check in case the listener already exists.
|
||||
lb = cloud.load_balancer.find_load_balancer(loadbalancer)
|
||||
lb = self.conn.load_balancer.find_load_balancer(loadbalancer)
|
||||
if not lb:
|
||||
module.fail_json(
|
||||
self.fail_json(
|
||||
msg='load balancer %s is not found' % loadbalancer
|
||||
)
|
||||
_lb_wait_for_status(module, cloud, lb, "ACTIVE", ["ERROR"])
|
||||
self._lb_wait_for_status(lb, "ACTIVE", ["ERROR"])
|
||||
|
||||
module.exit_json(changed=changed, listener=listener.to_dict(),
|
||||
id=listener.id)
|
||||
elif module.params['state'] == 'absent':
|
||||
self.exit_json(
|
||||
changed=changed, listener=listener.to_dict(), id=listener.id)
|
||||
elif self.params['state'] == 'absent':
|
||||
if not listener:
|
||||
changed = False
|
||||
else:
|
||||
cloud.load_balancer.delete_listener(listener)
|
||||
self.conn.load_balancer.delete_listener(listener)
|
||||
changed = True
|
||||
|
||||
if module.params['wait']:
|
||||
if self.params['wait']:
|
||||
# Wait for the load balancer to be active after deleting
|
||||
# the listener.
|
||||
lb = cloud.load_balancer.find_load_balancer(loadbalancer)
|
||||
lb = self.conn.load_balancer.find_load_balancer(loadbalancer)
|
||||
if not lb:
|
||||
module.fail_json(
|
||||
self.fail_json(
|
||||
msg='load balancer %s is not found' % loadbalancer
|
||||
)
|
||||
_lb_wait_for_status(module, cloud, lb, "ACTIVE", ["ERROR"])
|
||||
self._lb_wait_for_status(lb, "ACTIVE", ["ERROR"])
|
||||
|
||||
module.exit_json(changed=changed)
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e), extra_data=e.extra_data)
|
||||
self.exit_json(changed=changed)
|
||||
|
||||
|
||||
def main():
|
||||
module = LoadbalancerListenerModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -130,42 +130,11 @@ EXAMPLES = '''
|
||||
|
||||
import time
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def _wait_for_member_status(module, cloud, pool_id, member_id, status,
|
||||
failures, interval=5):
|
||||
timeout = module.params['timeout']
|
||||
|
||||
total_sleep = 0
|
||||
if failures is None:
|
||||
failures = []
|
||||
|
||||
while total_sleep < timeout:
|
||||
member = cloud.load_balancer.get_member(member_id, pool_id)
|
||||
provisioning_status = member.provisioning_status
|
||||
if provisioning_status == status:
|
||||
return member
|
||||
if provisioning_status in failures:
|
||||
module.fail_json(
|
||||
msg="Member %s transitioned to failure state %s" %
|
||||
(member_id, provisioning_status)
|
||||
)
|
||||
|
||||
time.sleep(interval)
|
||||
total_sleep += interval
|
||||
|
||||
module.fail_json(
|
||||
msg="Timeout waiting for member %s to transition to %s" %
|
||||
(member_id, status)
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class LoadbalancerMemberModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
name=dict(required=True),
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
pool=dict(required=True),
|
||||
@@ -173,54 +142,81 @@ def main():
|
||||
protocol_port=dict(default=80, type='int'),
|
||||
subnet_id=dict(default=None),
|
||||
)
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(argument_spec, **module_kwargs)
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
name = module.params['name']
|
||||
pool = module.params['pool']
|
||||
module_kwargs = dict()
|
||||
|
||||
def _wait_for_member_status(self, pool_id, member_id, status,
|
||||
failures, interval=5):
|
||||
timeout = self.params['timeout']
|
||||
|
||||
total_sleep = 0
|
||||
if failures is None:
|
||||
failures = []
|
||||
|
||||
while total_sleep < timeout:
|
||||
member = self.conn.load_balancer.get_member(member_id, pool_id)
|
||||
provisioning_status = member.provisioning_status
|
||||
if provisioning_status == status:
|
||||
return member
|
||||
if provisioning_status in failures:
|
||||
self.fail_json(
|
||||
msg="Member %s transitioned to failure state %s" %
|
||||
(member_id, provisioning_status)
|
||||
)
|
||||
|
||||
time.sleep(interval)
|
||||
total_sleep += interval
|
||||
|
||||
self.fail_json(
|
||||
msg="Timeout waiting for member %s to transition to %s" %
|
||||
(member_id, status)
|
||||
)
|
||||
|
||||
def run(self):
|
||||
name = self.params['name']
|
||||
pool = self.params['pool']
|
||||
|
||||
try:
|
||||
changed = False
|
||||
|
||||
pool_ret = cloud.load_balancer.find_pool(name_or_id=pool)
|
||||
pool_ret = self.conn.load_balancer.find_pool(name_or_id=pool)
|
||||
if not pool_ret:
|
||||
module.fail_json(msg='pool %s is not found' % pool)
|
||||
self.fail_json(msg='pool %s is not found' % pool)
|
||||
|
||||
pool_id = pool_ret.id
|
||||
member = cloud.load_balancer.find_member(name, pool_id)
|
||||
member = self.conn.load_balancer.find_member(name, pool_id)
|
||||
|
||||
if module.params['state'] == 'present':
|
||||
if self.params['state'] == 'present':
|
||||
if not member:
|
||||
member = cloud.load_balancer.create_member(
|
||||
member = self.conn.load_balancer.create_member(
|
||||
pool_ret,
|
||||
address=module.params['address'],
|
||||
address=self.params['address'],
|
||||
name=name,
|
||||
protocol_port=module.params['protocol_port'],
|
||||
subnet_id=module.params['subnet_id']
|
||||
protocol_port=self.params['protocol_port'],
|
||||
subnet_id=self.params['subnet_id']
|
||||
)
|
||||
changed = True
|
||||
|
||||
if not module.params['wait']:
|
||||
module.exit_json(changed=changed,
|
||||
member=member.to_dict(),
|
||||
id=member.id)
|
||||
if not self.params['wait']:
|
||||
self.exit_json(
|
||||
changed=changed, member=member.to_dict(), id=member.id)
|
||||
|
||||
if module.params['wait']:
|
||||
member = _wait_for_member_status(module, cloud, pool_id,
|
||||
member.id, "ACTIVE",
|
||||
["ERROR"])
|
||||
if self.params['wait']:
|
||||
member = self._wait_for_member_status(
|
||||
pool_id, member.id, "ACTIVE", ["ERROR"])
|
||||
|
||||
module.exit_json(changed=changed, member=member.to_dict(),
|
||||
id=member.id)
|
||||
self.exit_json(
|
||||
changed=changed, member=member.to_dict(), id=member.id)
|
||||
|
||||
elif module.params['state'] == 'absent':
|
||||
elif self.params['state'] == 'absent':
|
||||
if member:
|
||||
cloud.load_balancer.delete_member(member, pool_ret)
|
||||
self.conn.load_balancer.delete_member(member, pool_ret)
|
||||
changed = True
|
||||
|
||||
module.exit_json(changed=changed)
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e), extra_data=e.extra_data)
|
||||
self.exit_json(changed=changed)
|
||||
|
||||
|
||||
def main():
|
||||
module = LoadbalancerMemberModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -149,41 +149,11 @@ EXAMPLES = '''
|
||||
|
||||
import time
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import openstack_full_argument_spec, \
|
||||
openstack_module_kwargs, openstack_cloud_from_module
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def _wait_for_pool_status(module, cloud, pool_id, status, failures,
|
||||
interval=5):
|
||||
timeout = module.params['timeout']
|
||||
|
||||
total_sleep = 0
|
||||
if failures is None:
|
||||
failures = []
|
||||
|
||||
while total_sleep < timeout:
|
||||
pool = cloud.load_balancer.get_pool(pool_id)
|
||||
provisioning_status = pool.provisioning_status
|
||||
if provisioning_status == status:
|
||||
return pool
|
||||
if provisioning_status in failures:
|
||||
module.fail_json(
|
||||
msg="pool %s transitioned to failure state %s" %
|
||||
(pool_id, provisioning_status)
|
||||
)
|
||||
|
||||
time.sleep(interval)
|
||||
total_sleep += interval
|
||||
|
||||
module.fail_json(
|
||||
msg="timeout waiting for pool %s to transition to %s" %
|
||||
(pool_id, status)
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class LoadbalancerPoolModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
name=dict(required=True),
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
loadbalancer=dict(default=None),
|
||||
@@ -195,71 +165,98 @@ def main():
|
||||
choices=['ROUND_ROBIN', 'LEAST_CONNECTIONS', 'SOURCE_IP']
|
||||
)
|
||||
)
|
||||
module_kwargs = openstack_module_kwargs(
|
||||
module_kwargs = dict(
|
||||
mutually_exclusive=[['loadbalancer', 'listener']]
|
||||
)
|
||||
module = AnsibleModule(argument_spec, **module_kwargs)
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
|
||||
loadbalancer = module.params['loadbalancer']
|
||||
listener = module.params['listener']
|
||||
def _wait_for_pool_status(self, pool_id, status, failures,
|
||||
interval=5):
|
||||
timeout = self.params['timeout']
|
||||
|
||||
total_sleep = 0
|
||||
if failures is None:
|
||||
failures = []
|
||||
|
||||
while total_sleep < timeout:
|
||||
pool = self.conn.load_balancer.get_pool(pool_id)
|
||||
provisioning_status = pool.provisioning_status
|
||||
if provisioning_status == status:
|
||||
return pool
|
||||
if provisioning_status in failures:
|
||||
self.fail_json(
|
||||
msg="pool %s transitioned to failure state %s" %
|
||||
(pool_id, provisioning_status)
|
||||
)
|
||||
|
||||
time.sleep(interval)
|
||||
total_sleep += interval
|
||||
|
||||
self.fail_json(
|
||||
msg="timeout waiting for pool %s to transition to %s" %
|
||||
(pool_id, status)
|
||||
)
|
||||
|
||||
def run(self):
|
||||
loadbalancer = self.params['loadbalancer']
|
||||
listener = self.params['listener']
|
||||
|
||||
try:
|
||||
changed = False
|
||||
pool = cloud.load_balancer.find_pool(name_or_id=module.params['name'])
|
||||
pool = self.conn.load_balancer.find_pool(name_or_id=self.params['name'])
|
||||
|
||||
if module.params['state'] == 'present':
|
||||
if self.params['state'] == 'present':
|
||||
if not pool:
|
||||
loadbalancer_id = None
|
||||
if not (loadbalancer or listener):
|
||||
module.fail_json(
|
||||
self.fail_json(
|
||||
msg="either loadbalancer or listener must be provided"
|
||||
)
|
||||
|
||||
if loadbalancer:
|
||||
lb = cloud.load_balancer.find_load_balancer(loadbalancer)
|
||||
lb = self.conn.load_balancer.find_load_balancer(loadbalancer)
|
||||
if not lb:
|
||||
module.fail_json(msg='load balancer %s is not '
|
||||
'found' % loadbalancer)
|
||||
self.fail_json(
|
||||
msg='load balancer %s is not found' % loadbalancer)
|
||||
loadbalancer_id = lb.id
|
||||
|
||||
listener_id = None
|
||||
if listener:
|
||||
listener_ret = cloud.load_balancer.find_listener(listener)
|
||||
listener_ret = self.conn.load_balancer.find_listener(listener)
|
||||
if not listener_ret:
|
||||
module.fail_json(msg='listener %s is not found'
|
||||
% listener)
|
||||
self.fail_json(
|
||||
msg='listener %s is not found' % listener)
|
||||
listener_id = listener_ret.id
|
||||
|
||||
pool = cloud.load_balancer.create_pool(
|
||||
name=module.params['name'],
|
||||
pool = self.conn.load_balancer.create_pool(
|
||||
name=self.params['name'],
|
||||
loadbalancer_id=loadbalancer_id,
|
||||
listener_id=listener_id,
|
||||
protocol=module.params['protocol'],
|
||||
lb_algorithm=module.params['lb_algorithm']
|
||||
protocol=self.params['protocol'],
|
||||
lb_algorithm=self.params['lb_algorithm']
|
||||
)
|
||||
changed = True
|
||||
|
||||
if not module.params['wait']:
|
||||
module.exit_json(changed=changed,
|
||||
pool=pool.to_dict(),
|
||||
id=pool.id)
|
||||
if not self.params['wait']:
|
||||
self.exit_json(
|
||||
changed=changed, pool=pool.to_dict(), id=pool.id)
|
||||
|
||||
if module.params['wait']:
|
||||
pool = _wait_for_pool_status(module, cloud, pool.id, "ACTIVE",
|
||||
["ERROR"])
|
||||
if self.params['wait']:
|
||||
pool = self._wait_for_pool_status(
|
||||
pool.id, "ACTIVE", ["ERROR"])
|
||||
|
||||
module.exit_json(changed=changed, pool=pool.to_dict(),
|
||||
id=pool.id)
|
||||
self.exit_json(
|
||||
changed=changed, pool=pool.to_dict(), id=pool.id)
|
||||
|
||||
elif module.params['state'] == 'absent':
|
||||
elif self.params['state'] == 'absent':
|
||||
if pool:
|
||||
cloud.load_balancer.delete_pool(pool)
|
||||
self.conn.load_balancer.delete_pool(pool)
|
||||
changed = True
|
||||
|
||||
module.exit_json(changed=changed)
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e), extra_data=e.extra_data)
|
||||
self.exit_json(changed=changed)
|
||||
|
||||
|
||||
def main():
|
||||
module = LoadbalancerPoolModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -65,58 +65,55 @@ EXAMPLES = '''
|
||||
container: config
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def process_object(
|
||||
cloud_obj, container, name, filename, container_access, **kwargs):
|
||||
|
||||
changed = False
|
||||
container_obj = cloud_obj.get_container(container)
|
||||
if kwargs['state'] == 'present':
|
||||
if not container_obj:
|
||||
container_obj = cloud_obj.create_container(container)
|
||||
changed = True
|
||||
if cloud_obj.get_container_access(container) != container_access:
|
||||
cloud_obj.set_container_access(container, container_access)
|
||||
changed = True
|
||||
if name:
|
||||
if cloud_obj.is_object_stale(container, name, filename):
|
||||
cloud_obj.create_object(container, name, filename)
|
||||
changed = True
|
||||
else:
|
||||
if container_obj:
|
||||
if name:
|
||||
if cloud_obj.get_object_metadata(container, name):
|
||||
cloud_obj.delete_object(container, name)
|
||||
changed = True
|
||||
else:
|
||||
cloud_obj.delete_container(container)
|
||||
changed = True
|
||||
return changed
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class SwiftObjectModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
name=dict(required=False, default=None),
|
||||
container=dict(required=True),
|
||||
filename=dict(required=False, default=None),
|
||||
container_access=dict(default='private', choices=['private', 'public']),
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
)
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(argument_spec, **module_kwargs)
|
||||
module_kwargs = dict()
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
changed = process_object(cloud, **module.params)
|
||||
def process_object(
|
||||
self, container, name, filename, container_access, **kwargs
|
||||
):
|
||||
changed = False
|
||||
container_obj = self.conn.get_container(container)
|
||||
if kwargs['state'] == 'present':
|
||||
if not container_obj:
|
||||
container_obj = self.conn.create_container(container)
|
||||
changed = True
|
||||
if self.conn.get_container_access(container) != container_access:
|
||||
self.conn.set_container_access(container, container_access)
|
||||
changed = True
|
||||
if name:
|
||||
if self.conn.is_object_stale(container, name, filename):
|
||||
self.conn.create_object(container, name, filename)
|
||||
changed = True
|
||||
else:
|
||||
if container_obj:
|
||||
if name:
|
||||
if self.conn.get_object_metadata(container, name):
|
||||
self.conn.delete_object(container, name)
|
||||
changed = True
|
||||
else:
|
||||
self.conn.delete_container(container)
|
||||
changed = True
|
||||
return changed
|
||||
|
||||
module.exit_json(changed=changed)
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e))
|
||||
def run(self):
|
||||
changed = self.process_object(**self.params)
|
||||
|
||||
self.exit_json(changed=changed)
|
||||
|
||||
|
||||
def main():
|
||||
module = SwiftObjectModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
207
plugins/modules/object_container.py
Normal file
207
plugins/modules/object_container.py
Normal file
@@ -0,0 +1,207 @@
|
||||
#!/usr/bin/python
|
||||
# coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2021 by Open Telekom Cloud, operated by T-Systems International GmbH
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: object_container
|
||||
short_description: Manage Swift container.
|
||||
author: OpenStack Ansible SIG
|
||||
description:
|
||||
- Manage Swift container.
|
||||
options:
|
||||
container:
|
||||
description: Name of a container in Swift.
|
||||
type: str
|
||||
required: true
|
||||
metadata:
|
||||
description:
|
||||
- Key/value pairs to be set as metadata on the container.
|
||||
- If a container doesn't exist, it will be created.
|
||||
- Both custom and system metadata can be set.
|
||||
- Custom metadata are keys and values defined by the user.
|
||||
- The system metadata keys are content_type, content_encoding, content_disposition, delete_after,\
|
||||
delete_at, is_content_type_detected
|
||||
type: dict
|
||||
required: false
|
||||
keys:
|
||||
description: Keys from 'metadata' to be deleted.
|
||||
type: list
|
||||
elements: str
|
||||
required: false
|
||||
delete_with_all_objects:
|
||||
description:
|
||||
- Whether the container should be deleted with all objects or not.
|
||||
- Without this parameter set to "true", an attempt to delete a container that contains objects will fail.
|
||||
type: bool
|
||||
default: False
|
||||
required: false
|
||||
state:
|
||||
description: Whether resource should be present or absent.
|
||||
default: 'present'
|
||||
choices: ['present', 'absent']
|
||||
type: str
|
||||
requirements:
|
||||
- "python >= 3.6"
|
||||
- "openstacksdk"
|
||||
|
||||
extends_documentation_fragment:
|
||||
- openstack.cloud.openstack
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
container:
|
||||
description: Specifies the container.
|
||||
returned: On success when C(state=present)
|
||||
type: dict
|
||||
sample:
|
||||
{
|
||||
"bytes": 5449,
|
||||
"bytes_used": 5449,
|
||||
"content_type": null,
|
||||
"count": 1,
|
||||
"id": "otc",
|
||||
"if_none_match": null,
|
||||
"is_content_type_detected": null,
|
||||
"is_newest": null,
|
||||
"meta_temp_url_key": null,
|
||||
"meta_temp_url_key_2": null,
|
||||
"name": "otc",
|
||||
"object_count": 1,
|
||||
"read_ACL": null,
|
||||
"sync_key": null,
|
||||
"sync_to": null,
|
||||
"timestamp": null,
|
||||
"versions_location": null,
|
||||
"write_ACL": null
|
||||
}
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# Create empty container
|
||||
- openstack.cloud.object_container:
|
||||
container: "new-container"
|
||||
state: present
|
||||
|
||||
# Set metadata for container
|
||||
- openstack.cloud.object_container:
|
||||
container: "new-container"
|
||||
metadata: "Cache-Control='no-cache'"
|
||||
|
||||
# Delete some keys from metadata of a container
|
||||
- openstack.cloud.object_container:
|
||||
container: "new-container"
|
||||
keys:
|
||||
- content_type
|
||||
|
||||
# Delete container
|
||||
- openstack.cloud.object_container:
|
||||
container: "new-container"
|
||||
state: absent
|
||||
|
||||
# Delete container and its objects
|
||||
- openstack.cloud.object_container:
|
||||
container: "new-container"
|
||||
delete_with_all_objects: true
|
||||
state: absent
|
||||
'''
|
||||
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
class ContainerModule(OpenStackModule):
|
||||
|
||||
argument_spec = dict(
|
||||
container=dict(type='str', required=True),
|
||||
metadata=dict(type='dict', required=False),
|
||||
keys=dict(type='list', required=False, elements='str', no_log=False),
|
||||
state=dict(type='str', required=False, default='present', choices=['present', 'absent']),
|
||||
delete_with_all_objects=dict(type='bool', default=False, required=False)
|
||||
)
|
||||
|
||||
def create(self, container):
|
||||
|
||||
data = {}
|
||||
if self._container_exist(container):
|
||||
self.exit_json(changed=False)
|
||||
|
||||
container_data = self.conn.object_store.create_container(name=container).to_dict()
|
||||
container_data.pop('location')
|
||||
data['container'] = container_data
|
||||
self.exit_json(changed=True, **data)
|
||||
|
||||
def delete(self, container):
|
||||
|
||||
delete_with_all_objects = self.params['delete_with_all_objects']
|
||||
|
||||
changed = False
|
||||
if self._container_exist(container):
|
||||
objects = []
|
||||
for raw in self.conn.object_store.objects(container):
|
||||
dt = raw.to_dict()
|
||||
dt.pop('location')
|
||||
objects.append(dt)
|
||||
if len(objects) > 0:
|
||||
if delete_with_all_objects:
|
||||
for obj in objects:
|
||||
self.conn.object_store.delete_object(container=container, obj=obj['id'])
|
||||
else:
|
||||
self.fail_json(msg="Container has objects")
|
||||
self.conn.object_store.delete_container(container=container)
|
||||
changed = True
|
||||
|
||||
self.exit(changed=changed)
|
||||
|
||||
def set_metadata(self, container, metadata):
|
||||
|
||||
data = {}
|
||||
|
||||
if not self._container_exist(container):
|
||||
new_container = self.conn.object_store.create_container(name=container).to_dict()
|
||||
|
||||
new_container = self.conn.object_store.set_container_metadata(container, **metadata).to_dict()
|
||||
new_container.pop('location')
|
||||
data['container'] = new_container
|
||||
self.exit(changed=True, **data)
|
||||
|
||||
def delete_metadata(self, container, keys):
|
||||
|
||||
if not self._container_exist(container):
|
||||
self.fail_json(msg="Container doesn't exist")
|
||||
|
||||
self.conn.object_store.delete_container_metadata(container=container, keys=keys)
|
||||
self.exit(changed=True)
|
||||
|
||||
def _container_exist(self, container):
|
||||
try:
|
||||
self.conn.object_store.get_container_metadata(container)
|
||||
return True
|
||||
except self.sdk.exceptions.ResourceNotFound:
|
||||
return False
|
||||
|
||||
def run(self):
|
||||
|
||||
container = self.params['container']
|
||||
state = self.params['state']
|
||||
metadata = self.params['metadata']
|
||||
keys = self.params['keys']
|
||||
|
||||
if state == 'absent':
|
||||
self.delete(container)
|
||||
if metadata:
|
||||
self.set_metadata(container, metadata)
|
||||
if keys:
|
||||
self.delete_metadata(container, keys)
|
||||
|
||||
self.create(container)
|
||||
|
||||
|
||||
def main():
|
||||
module = ContainerModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -119,6 +119,10 @@ options:
|
||||
description:
|
||||
- Whether to enable or disable the port security on the network.
|
||||
type: bool
|
||||
binding_profile:
|
||||
description:
|
||||
- Binding profile dict that the port should be created with.
|
||||
type: dict
|
||||
requirements:
|
||||
- "python >= 3.6"
|
||||
- "openstacksdk"
|
||||
@@ -199,6 +203,20 @@ EXAMPLES = '''
|
||||
name: port1
|
||||
network: foo
|
||||
vnic_type: direct
|
||||
|
||||
# Create a port with binding profile
|
||||
- openstack.cloud.port:
|
||||
state: present
|
||||
auth:
|
||||
auth_url: https://identity.example.com
|
||||
username: admin
|
||||
password: admin
|
||||
project_name: admin
|
||||
name: port1
|
||||
network: foo
|
||||
binding_profile:
|
||||
"pci_slot": "0000:03:11.1"
|
||||
"physical_network": "provider"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
@@ -246,12 +264,14 @@ port_security_enabled:
|
||||
description: Port security state on the network.
|
||||
returned: success
|
||||
type: bool
|
||||
binding:profile:
|
||||
description: Port binded profile
|
||||
returned: success
|
||||
type: dict
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible.module_utils.basic import missing_required_lib
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
try:
|
||||
from collections import OrderedDict
|
||||
@@ -264,120 +284,8 @@ except ImportError:
|
||||
HAS_ORDEREDDICT = False
|
||||
|
||||
|
||||
def _needs_update(module, port, cloud):
|
||||
"""Check for differences in the updatable values.
|
||||
|
||||
NOTE: We don't currently allow name updates.
|
||||
"""
|
||||
compare_simple = ['admin_state_up',
|
||||
'mac_address',
|
||||
'device_owner',
|
||||
'device_id',
|
||||
'binding:vnic_type',
|
||||
'port_security_enabled']
|
||||
compare_list_dict = ['allowed_address_pairs',
|
||||
'extra_dhcp_opts']
|
||||
compare_list = ['security_groups']
|
||||
|
||||
for key in compare_simple:
|
||||
if module.params[key] is not None and module.params[key] != port[key]:
|
||||
return True
|
||||
for key in compare_list:
|
||||
if (
|
||||
module.params[key] is not None
|
||||
and set(module.params[key]) != set(port[key])
|
||||
):
|
||||
return True
|
||||
|
||||
for key in compare_list_dict:
|
||||
if module.params[key]:
|
||||
if not port[key]:
|
||||
return True
|
||||
|
||||
# sort dicts in list
|
||||
port_ordered = [OrderedDict(sorted(d.items())) for d in port[key]]
|
||||
param_ordered = [OrderedDict(sorted(d.items())) for d in module.params[key]]
|
||||
|
||||
for d in param_ordered:
|
||||
if d not in port_ordered:
|
||||
return True
|
||||
|
||||
for d in port_ordered:
|
||||
if d not in param_ordered:
|
||||
return True
|
||||
|
||||
# NOTE: if port was created or updated with 'no_security_groups=True',
|
||||
# subsequent updates without 'no_security_groups' flag or
|
||||
# 'no_security_groups=False' and no specified 'security_groups', will not
|
||||
# result in an update to the port where the default security group is
|
||||
# applied.
|
||||
if module.params['no_security_groups'] and port['security_groups'] != []:
|
||||
return True
|
||||
|
||||
if module.params['fixed_ips'] is not None:
|
||||
for item in module.params['fixed_ips']:
|
||||
if 'ip_address' in item:
|
||||
# if ip_address in request does not match any in existing port,
|
||||
# update is required.
|
||||
if not any(match['ip_address'] == item['ip_address']
|
||||
for match in port['fixed_ips']):
|
||||
return True
|
||||
if 'subnet_id' in item:
|
||||
return True
|
||||
for item in port['fixed_ips']:
|
||||
# if ip_address in existing port does not match any in request,
|
||||
# update is required.
|
||||
if not any(match.get('ip_address') == item['ip_address']
|
||||
for match in module.params['fixed_ips']):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def _system_state_change(module, port, cloud):
|
||||
state = module.params['state']
|
||||
if state == 'present':
|
||||
if not port:
|
||||
return True
|
||||
return _needs_update(module, port, cloud)
|
||||
if state == 'absent' and port:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _compose_port_args(module, cloud):
|
||||
port_kwargs = {}
|
||||
optional_parameters = ['name',
|
||||
'fixed_ips',
|
||||
'admin_state_up',
|
||||
'mac_address',
|
||||
'security_groups',
|
||||
'allowed_address_pairs',
|
||||
'extra_dhcp_opts',
|
||||
'device_owner',
|
||||
'device_id',
|
||||
'binding:vnic_type',
|
||||
'port_security_enabled']
|
||||
for optional_param in optional_parameters:
|
||||
if module.params[optional_param] is not None:
|
||||
port_kwargs[optional_param] = module.params[optional_param]
|
||||
|
||||
if module.params['no_security_groups']:
|
||||
port_kwargs['security_groups'] = []
|
||||
|
||||
return port_kwargs
|
||||
|
||||
|
||||
def get_security_group_id(module, cloud, security_group_name_or_id):
|
||||
security_group = cloud.get_security_group(security_group_name_or_id)
|
||||
if not security_group:
|
||||
module.fail_json(msg="Security group: %s, was not found"
|
||||
% security_group_name_or_id)
|
||||
return security_group['id']
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class NetworkPortModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
network=dict(required=False),
|
||||
name=dict(required=False),
|
||||
fixed_ips=dict(type='list', default=None, elements='dict'),
|
||||
@@ -393,81 +301,197 @@ def main():
|
||||
vnic_type=dict(default=None,
|
||||
choices=['normal', 'direct', 'direct-physical',
|
||||
'macvtap', 'baremetal', 'virtio-forwarder']),
|
||||
port_security_enabled=dict(default=None, type='bool')
|
||||
port_security_enabled=dict(default=None, type='bool'),
|
||||
binding_profile=dict(default=None, type='dict')
|
||||
)
|
||||
|
||||
module_kwargs = openstack_module_kwargs(
|
||||
module_kwargs = dict(
|
||||
mutually_exclusive=[
|
||||
['no_security_groups', 'security_groups'],
|
||||
]
|
||||
],
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
module = AnsibleModule(argument_spec,
|
||||
supports_check_mode=True,
|
||||
**module_kwargs)
|
||||
def _needs_update(self, port):
|
||||
"""Check for differences in the updatable values.
|
||||
|
||||
if not HAS_ORDEREDDICT:
|
||||
module.fail_json(msg=missing_required_lib('ordereddict'))
|
||||
NOTE: We don't currently allow name updates.
|
||||
"""
|
||||
compare_simple = ['admin_state_up',
|
||||
'mac_address',
|
||||
'device_owner',
|
||||
'device_id',
|
||||
'binding:vnic_type',
|
||||
'port_security_enabled',
|
||||
'binding:profile']
|
||||
compare_list_dict = ['allowed_address_pairs',
|
||||
'extra_dhcp_opts']
|
||||
compare_list = ['security_groups']
|
||||
|
||||
name = module.params['name']
|
||||
state = module.params['state']
|
||||
for key in compare_simple:
|
||||
if self.params[key] is not None and self.params[key] != port[key]:
|
||||
return True
|
||||
for key in compare_list:
|
||||
if (
|
||||
self.params[key] is not None
|
||||
and set(self.params[key]) != set(port[key])
|
||||
):
|
||||
return True
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
if module.params['security_groups']:
|
||||
for key in compare_list_dict:
|
||||
if not self.params[key]:
|
||||
if port[key]:
|
||||
return True
|
||||
|
||||
if self.params[key]:
|
||||
if not port[key]:
|
||||
return True
|
||||
|
||||
# sort dicts in list
|
||||
port_ordered = [OrderedDict(sorted(d.items())) for d in port[key]]
|
||||
param_ordered = [OrderedDict(sorted(d.items())) for d in self.params[key]]
|
||||
|
||||
for d in param_ordered:
|
||||
if d not in port_ordered:
|
||||
return True
|
||||
|
||||
for d in port_ordered:
|
||||
if d not in param_ordered:
|
||||
return True
|
||||
|
||||
# NOTE: if port was created or updated with 'no_security_groups=True',
|
||||
# subsequent updates without 'no_security_groups' flag or
|
||||
# 'no_security_groups=False' and no specified 'security_groups', will not
|
||||
# result in an update to the port where the default security group is
|
||||
# applied.
|
||||
if self.params['no_security_groups'] and port['security_groups'] != []:
|
||||
return True
|
||||
|
||||
if self.params['fixed_ips'] is not None:
|
||||
for item in self.params['fixed_ips']:
|
||||
if 'ip_address' in item:
|
||||
# if ip_address in request does not match any in existing port,
|
||||
# update is required.
|
||||
if not any(match['ip_address'] == item['ip_address']
|
||||
for match in port['fixed_ips']):
|
||||
return True
|
||||
if 'subnet_id' in item:
|
||||
return True
|
||||
for item in port['fixed_ips']:
|
||||
# if ip_address in existing port does not match any in request,
|
||||
# update is required.
|
||||
if not any(match.get('ip_address') == item['ip_address']
|
||||
for match in self.params['fixed_ips']):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def _system_state_change(self, port):
|
||||
state = self.params['state']
|
||||
if state == 'present':
|
||||
if not port:
|
||||
return True
|
||||
return self._needs_update(port)
|
||||
if state == 'absent' and port:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _compose_port_args(self):
|
||||
port_kwargs = {}
|
||||
optional_parameters = ['name',
|
||||
'fixed_ips',
|
||||
'admin_state_up',
|
||||
'mac_address',
|
||||
'security_groups',
|
||||
'allowed_address_pairs',
|
||||
'extra_dhcp_opts',
|
||||
'device_owner',
|
||||
'device_id',
|
||||
'binding:vnic_type',
|
||||
'port_security_enabled',
|
||||
'binding:profile']
|
||||
for optional_param in optional_parameters:
|
||||
if self.params[optional_param] is not None:
|
||||
port_kwargs[optional_param] = self.params[optional_param]
|
||||
|
||||
if self.params['no_security_groups']:
|
||||
port_kwargs['security_groups'] = []
|
||||
|
||||
return port_kwargs
|
||||
|
||||
def get_security_group_id(self, security_group_name_or_id):
|
||||
security_group = self.conn.get_security_group(security_group_name_or_id)
|
||||
if not security_group:
|
||||
self.fail_json(msg="Security group: %s, was not found"
|
||||
% security_group_name_or_id)
|
||||
return security_group['id']
|
||||
|
||||
def run(self):
|
||||
if not HAS_ORDEREDDICT:
|
||||
self.fail_json(msg=missing_required_lib('ordereddict'))
|
||||
|
||||
name = self.params['name']
|
||||
state = self.params['state']
|
||||
|
||||
if self.params['security_groups']:
|
||||
# translate security_groups to UUID's if names where provided
|
||||
module.params['security_groups'] = [
|
||||
get_security_group_id(module, cloud, v)
|
||||
for v in module.params['security_groups']
|
||||
self.params['security_groups'] = [
|
||||
self.get_security_group_id(v)
|
||||
for v in self.params['security_groups']
|
||||
]
|
||||
|
||||
# Neutron API accept 'binding:vnic_type' as an argument
|
||||
# for the port type.
|
||||
module.params['binding:vnic_type'] = module.params.pop('vnic_type')
|
||||
self.params['binding:vnic_type'] = self.params.pop('vnic_type')
|
||||
# Neutron API accept 'binding:profile' as an argument
|
||||
# for the port binding profile type.
|
||||
self.params['binding:profile'] = self.params.pop('binding_profile')
|
||||
|
||||
port = None
|
||||
network_id = None
|
||||
if name:
|
||||
port = cloud.get_port(name)
|
||||
port = self.conn.get_port(name)
|
||||
|
||||
if module.check_mode:
|
||||
module.exit_json(changed=_system_state_change(module, port, cloud))
|
||||
if self.ansible.check_mode:
|
||||
self.exit_json(changed=self._system_state_change(port))
|
||||
|
||||
changed = False
|
||||
if state == 'present':
|
||||
if not port:
|
||||
network = module.params['network']
|
||||
network = self.params['network']
|
||||
if not network:
|
||||
module.fail_json(
|
||||
self.fail_json(
|
||||
msg="Parameter 'network' is required in Port Create"
|
||||
)
|
||||
port_kwargs = _compose_port_args(module, cloud)
|
||||
network_object = cloud.get_network(network)
|
||||
port_kwargs = self._compose_port_args()
|
||||
network_object = self.conn.get_network(network)
|
||||
|
||||
if network_object:
|
||||
network_id = network_object['id']
|
||||
else:
|
||||
module.fail_json(
|
||||
self.fail_json(
|
||||
msg="Specified network was not found."
|
||||
)
|
||||
|
||||
port = cloud.create_port(network_id, **port_kwargs)
|
||||
port = self.conn.create_port(network_id, **port_kwargs)
|
||||
changed = True
|
||||
else:
|
||||
if _needs_update(module, port, cloud):
|
||||
port_kwargs = _compose_port_args(module, cloud)
|
||||
port = cloud.update_port(port['id'], **port_kwargs)
|
||||
if self._needs_update(port):
|
||||
port_kwargs = self._compose_port_args()
|
||||
port = self.conn.update_port(port['id'], **port_kwargs)
|
||||
changed = True
|
||||
module.exit_json(changed=changed, id=port['id'], port=port)
|
||||
self.exit_json(changed=changed, id=port['id'], port=port)
|
||||
|
||||
if state == 'absent':
|
||||
if port:
|
||||
cloud.delete_port(port['id'])
|
||||
self.conn.delete_port(port['id'])
|
||||
changed = True
|
||||
module.exit_json(changed=changed)
|
||||
self.exit_json(changed=changed)
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
def main():
|
||||
module = NetworkPortModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -179,38 +179,30 @@ openstack_ports:
|
||||
sample: "51fce036d7984ba6af4f6c849f65ef00"
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class NetworkPortInfoModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
port=dict(required=False),
|
||||
filters=dict(type='dict', required=False),
|
||||
)
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(argument_spec, **module_kwargs)
|
||||
is_old_facts = module._name == 'openstack.cloud.port_facts'
|
||||
if is_old_facts:
|
||||
module.deprecate("The 'openstack.cloud.port_facts' module has been renamed to 'openstack.cloud.port_info', "
|
||||
"and the renamed one no longer returns ansible_facts", version='2.13')
|
||||
module_kwargs = dict(
|
||||
)
|
||||
|
||||
port = module.params.get('port')
|
||||
filters = module.params.get('filters')
|
||||
deprecated_names = ('openstack.cloud.port_facts')
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
ports = cloud.search_ports(port, filters)
|
||||
if is_old_facts:
|
||||
module.exit_json(changed=False, ansible_facts=dict(
|
||||
openstack_ports=ports))
|
||||
else:
|
||||
module.exit_json(changed=False, openstack_ports=ports)
|
||||
def run(self):
|
||||
port = self.params.get('port')
|
||||
filters = self.params.get('filters')
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e))
|
||||
ports = self.conn.search_ports(port, filters)
|
||||
self.exit_json(changed=False, openstack_ports=ports)
|
||||
|
||||
|
||||
def main():
|
||||
module = NetworkPortInfoModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -38,7 +38,7 @@ options:
|
||||
- Additional properties to be associated with this project. Requires
|
||||
openstacksdk>0.45.
|
||||
type: dict
|
||||
default: {}
|
||||
required: false
|
||||
state:
|
||||
description:
|
||||
- Should the resource be present or absent.
|
||||
@@ -99,133 +99,121 @@ project:
|
||||
sample: True
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def _needs_update(module, project):
|
||||
keys = ('description', 'enabled')
|
||||
for key in keys:
|
||||
if module.params[key] is not None and module.params[key] != project.get(key):
|
||||
return True
|
||||
|
||||
properties = module.params['properties']
|
||||
if properties:
|
||||
project_properties = project.get('properties')
|
||||
for k, v in properties.items():
|
||||
if v is not None and (k not in project_properties or v != project_properties[k]):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def _system_state_change(module, project):
|
||||
state = module.params['state']
|
||||
if state == 'present':
|
||||
if project is None:
|
||||
changed = True
|
||||
else:
|
||||
if _needs_update(module, project):
|
||||
changed = True
|
||||
else:
|
||||
changed = False
|
||||
|
||||
elif state == 'absent':
|
||||
if project is None:
|
||||
changed = False
|
||||
else:
|
||||
changed = True
|
||||
|
||||
return changed
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class IdentityProjectModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
name=dict(required=True),
|
||||
description=dict(required=False, default=None),
|
||||
domain_id=dict(required=False, default=None, aliases=['domain']),
|
||||
properties=dict(type='dict', default={}),
|
||||
description=dict(required=False),
|
||||
domain_id=dict(required=False, aliases=['domain']),
|
||||
properties=dict(required=False, type='dict', min_ver='0.45.1'),
|
||||
enabled=dict(default=True, type='bool'),
|
||||
state=dict(default='present', choices=['absent', 'present'])
|
||||
)
|
||||
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(
|
||||
argument_spec,
|
||||
supports_check_mode=True,
|
||||
**module_kwargs
|
||||
module_kwargs = dict(
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
name = module.params['name']
|
||||
description = module.params['description']
|
||||
domain = module.params.get('domain_id')
|
||||
enabled = module.params['enabled']
|
||||
properties = module.params['properties']
|
||||
state = module.params['state']
|
||||
def _needs_update(self, project):
|
||||
keys = ('description', 'enabled')
|
||||
for key in keys:
|
||||
if self.params[key] is not None and self.params[key] != project.get(key):
|
||||
return True
|
||||
|
||||
min_version = None
|
||||
properties = self.params['properties']
|
||||
if properties:
|
||||
project_properties = project.get('properties')
|
||||
for k, v in properties.items():
|
||||
if v is not None and (k not in project_properties or v != project_properties[k]):
|
||||
return True
|
||||
|
||||
if properties:
|
||||
min_version = '0.45.1'
|
||||
return False
|
||||
|
||||
def _system_state_change(self, project):
|
||||
state = self.params['state']
|
||||
if state == 'present':
|
||||
if project is None:
|
||||
changed = True
|
||||
else:
|
||||
if self._needs_update(project):
|
||||
changed = True
|
||||
else:
|
||||
changed = False
|
||||
|
||||
elif state == 'absent':
|
||||
changed = project is not None
|
||||
|
||||
return changed
|
||||
|
||||
def run(self):
|
||||
name = self.params['name']
|
||||
description = self.params['description']
|
||||
domain = self.params['domain_id']
|
||||
enabled = self.params['enabled']
|
||||
properties = self.params['properties'] or {}
|
||||
state = self.params['state']
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module, min_version)
|
||||
try:
|
||||
if domain:
|
||||
try:
|
||||
# We assume admin is passing domain id
|
||||
dom = cloud.get_domain(domain)['id']
|
||||
dom = self.conn.get_domain(domain)['id']
|
||||
domain = dom
|
||||
except Exception:
|
||||
# If we fail, maybe admin is passing a domain name.
|
||||
# Note that domains have unique names, just like id.
|
||||
try:
|
||||
dom = cloud.search_domains(filters={'name': domain})[0]['id']
|
||||
dom = self.conn.search_domains(filters={'name': domain})[0]['id']
|
||||
domain = dom
|
||||
except Exception:
|
||||
# Ok, let's hope the user is non-admin and passing a sane id
|
||||
pass
|
||||
|
||||
if domain:
|
||||
project = cloud.get_project(name, domain_id=domain)
|
||||
project = self.conn.get_project(name, domain_id=domain)
|
||||
else:
|
||||
project = cloud.get_project(name)
|
||||
project = self.conn.get_project(name)
|
||||
|
||||
if module.check_mode:
|
||||
module.exit_json(changed=_system_state_change(module, project))
|
||||
if self.ansible.check_mode:
|
||||
self.exit_json(changed=self._system_state_change(project))
|
||||
|
||||
if state == 'present':
|
||||
if project is None:
|
||||
project = cloud.create_project(
|
||||
project = self.conn.create_project(
|
||||
name=name, description=description,
|
||||
domain_id=domain,
|
||||
enabled=enabled)
|
||||
changed = True
|
||||
|
||||
project = cloud.update_project(
|
||||
project['id'], description=description,
|
||||
enabled=enabled, **properties)
|
||||
project = self.conn.update_project(
|
||||
project['id'],
|
||||
description=description,
|
||||
enabled=enabled,
|
||||
**properties)
|
||||
else:
|
||||
if _needs_update(module, project):
|
||||
project = cloud.update_project(
|
||||
project['id'], description=description,
|
||||
enabled=enabled, **properties)
|
||||
if self._needs_update(project):
|
||||
project = self.conn.update_project(
|
||||
project['id'],
|
||||
description=description,
|
||||
enabled=enabled,
|
||||
**properties)
|
||||
changed = True
|
||||
else:
|
||||
changed = False
|
||||
module.exit_json(changed=changed, project=project)
|
||||
self.exit_json(changed=changed, project=project)
|
||||
|
||||
elif state == 'absent':
|
||||
if project is None:
|
||||
changed = False
|
||||
else:
|
||||
cloud.delete_project(project['id'])
|
||||
self.conn.delete_project(project['id'])
|
||||
changed = True
|
||||
module.exit_json(changed=changed)
|
||||
self.exit_json(changed=changed)
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=e.message, extra_data=e.extra_data)
|
||||
|
||||
def main():
|
||||
module = IdentityProjectModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -91,49 +91,41 @@ flavor:
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class IdentityProjectAccess(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
state=dict(required=False, default='present',
|
||||
choices=['absent', 'present']),
|
||||
|
||||
target_project_id=dict(required=True, type='str'),
|
||||
resource_type=dict(required=True, type='str'),
|
||||
resource_name=dict(required=True, type='str'),
|
||||
)
|
||||
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(
|
||||
argument_spec,
|
||||
module_kwargs = dict(
|
||||
supports_check_mode=True,
|
||||
required_if=[
|
||||
('state', 'present', ['target_project_id'])
|
||||
],
|
||||
**module_kwargs)
|
||||
]
|
||||
)
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
def run(self):
|
||||
state = self.params['state']
|
||||
resource_name = self.params['resource_name']
|
||||
resource_type = self.params['resource_type']
|
||||
target_project_id = self.params['target_project_id']
|
||||
|
||||
state = module.params['state']
|
||||
resource_name = module.params['resource_name']
|
||||
resource_type = module.params['resource_type']
|
||||
target_project_id = module.params['target_project_id']
|
||||
|
||||
try:
|
||||
if resource_type == 'nova_flavor':
|
||||
# returns Munch({'NAME_ATTR': 'name',
|
||||
# 'tenant_id': u'37e55da59ec842649d84230f3a24eed5',
|
||||
# 'HUMAN_ID': False,
|
||||
# 'flavor_id': u'6d4d37b9-0480-4a8c-b8c9-f77deaad73f9',
|
||||
# 'request_ids': [], 'human_id': None}),
|
||||
_get_resource = cloud.get_flavor
|
||||
_list_resource_access = cloud.list_flavor_access
|
||||
_add_resource_access = cloud.add_flavor_access
|
||||
_remove_resource_access = cloud.remove_flavor_access
|
||||
_get_resource = self.conn.get_flavor
|
||||
_list_resource_access = self.conn.list_flavor_access
|
||||
_add_resource_access = self.conn.add_flavor_access
|
||||
_remove_resource_access = self.conn.remove_flavor_access
|
||||
elif resource_type == 'cinder_volume_type':
|
||||
# returns [Munch({
|
||||
# 'project_id': u'178cdb9955b047eea7afbe582038dc94',
|
||||
@@ -141,41 +133,43 @@ def main():
|
||||
# 'human_id': None,
|
||||
# 'HUMAN_ID': False},
|
||||
# 'id': u'd5573023-b290-42c8-b232-7c5ca493667f'}),
|
||||
_get_resource = cloud.get_volume_type
|
||||
_list_resource_access = cloud.get_volume_type_access
|
||||
_add_resource_access = cloud.add_volume_type_access
|
||||
_remove_resource_access = cloud.remove_volume_type_access
|
||||
_get_resource = self.conn.get_volume_type
|
||||
_list_resource_access = self.conn.get_volume_type_access
|
||||
_add_resource_access = self.conn.add_volume_type_access
|
||||
_remove_resource_access = self.conn.remove_volume_type_access
|
||||
else:
|
||||
module.exit_json(changed=False,
|
||||
resource_name=resource_name,
|
||||
resource_type=resource_type,
|
||||
error="Not implemented.")
|
||||
self.exit_json(
|
||||
changed=False,
|
||||
resource_name=resource_name,
|
||||
resource_type=resource_type,
|
||||
error="Not implemented.")
|
||||
|
||||
resource = _get_resource(resource_name)
|
||||
if not resource:
|
||||
module.exit_json(changed=False,
|
||||
resource_name=resource_name,
|
||||
resource_type=resource_type,
|
||||
error="Not found.")
|
||||
self.exit_json(
|
||||
changed=False,
|
||||
resource_name=resource_name,
|
||||
resource_type=resource_type,
|
||||
error="Not found.")
|
||||
resource_id = getattr(resource, 'id', resource['id'])
|
||||
# _list_resource_access returns a list of dicts containing 'project_id'
|
||||
acls = _list_resource_access(resource_id)
|
||||
|
||||
if not all(acl.get('project_id') for acl in acls):
|
||||
module.exit_json(changed=False,
|
||||
resource_name=resource_name,
|
||||
resource_type=resource_type,
|
||||
error="Missing project_id in resource output.")
|
||||
self.exit_json(
|
||||
changed=False,
|
||||
resource_name=resource_name,
|
||||
resource_type=resource_type,
|
||||
error="Missing project_id in resource output.")
|
||||
allowed_tenants = [acl['project_id'] for acl in acls]
|
||||
|
||||
changed_access = any((
|
||||
state == 'present' and target_project_id not in allowed_tenants,
|
||||
state == 'absent' and target_project_id in allowed_tenants
|
||||
))
|
||||
if module.check_mode or not changed_access:
|
||||
module.exit_json(changed=changed_access,
|
||||
resource=resource,
|
||||
id=resource_id)
|
||||
if self.ansible.check_mode or not changed_access:
|
||||
self.exit_json(
|
||||
changed=changed_access, resource=resource, id=resource_id)
|
||||
|
||||
if state == 'present':
|
||||
_add_resource_access(
|
||||
@@ -186,12 +180,13 @@ def main():
|
||||
resource_id, target_project_id
|
||||
)
|
||||
|
||||
module.exit_json(changed=True,
|
||||
resource=resource,
|
||||
id=resource_id)
|
||||
self.exit_json(
|
||||
changed=True, resource=resource, id=resource_id)
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e), **module.params)
|
||||
|
||||
def main():
|
||||
module = IdentityProjectAccess()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -99,58 +99,57 @@ openstack_projects:
|
||||
type: bool
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import openstack_full_argument_spec, openstack_cloud_from_module
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def main():
|
||||
class IdentityProjectInfoModule(OpenStackModule):
|
||||
deprecated_names = ('project_facts', 'openstack.cloud.project_facts')
|
||||
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
name=dict(required=False, default=None),
|
||||
domain=dict(required=False, default=None),
|
||||
filters=dict(required=False, type='dict', default=None),
|
||||
argument_spec = dict(
|
||||
name=dict(required=False),
|
||||
domain=dict(required=False),
|
||||
filters=dict(required=False, type='dict'),
|
||||
)
|
||||
module_kwargs = dict(
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
module = AnsibleModule(argument_spec)
|
||||
is_old_facts = module._name == 'openstack.cloud.project_facts'
|
||||
if is_old_facts:
|
||||
module.deprecate("The 'openstack.cloud.project_facts' module has been renamed to 'openstack.cloud.project_info', "
|
||||
"and the renamed one no longer returns ansible_facts", version='2.13')
|
||||
|
||||
sdk, opcloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
name = module.params['name']
|
||||
domain = module.params['domain']
|
||||
filters = module.params['filters']
|
||||
def run(self):
|
||||
name = self.params['name']
|
||||
domain = self.params['domain']
|
||||
filters = self.params['filters']
|
||||
is_old_facts = self.module_name == 'openstack.cloud.project_facts'
|
||||
|
||||
if domain:
|
||||
try:
|
||||
# We assume admin is passing domain id
|
||||
dom = opcloud.get_domain(domain)['id']
|
||||
dom = self.conn.get_domain(domain)['id']
|
||||
domain = dom
|
||||
except Exception:
|
||||
# If we fail, maybe admin is passing a domain name.
|
||||
# Note that domains have unique names, just like id.
|
||||
dom = opcloud.search_domains(filters={'name': domain})
|
||||
dom = self.conn.search_domains(filters={'name': domain})
|
||||
if dom:
|
||||
domain = dom[0]['id']
|
||||
else:
|
||||
module.fail_json(msg='Domain name or ID does not exist')
|
||||
self.fail_json(msg='Domain name or ID does not exist')
|
||||
|
||||
if not filters:
|
||||
filters = {}
|
||||
|
||||
filters['domain_id'] = domain
|
||||
|
||||
projects = opcloud.search_projects(name, filters)
|
||||
projects = self.conn.search_projects(name, filters)
|
||||
if is_old_facts:
|
||||
module.exit_json(changed=False, ansible_facts=dict(
|
||||
self.exit_json(changed=False, ansible_facts=dict(
|
||||
openstack_projects=projects))
|
||||
else:
|
||||
module.exit_json(changed=False, openstack_projects=projects)
|
||||
self.exit_json(changed=False, openstack_projects=projects)
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
def main():
|
||||
module = IdentityProjectInfoModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -256,117 +256,11 @@ openstack_quotas:
|
||||
|
||||
'''
|
||||
|
||||
import traceback
|
||||
|
||||
KEYSTONEAUTH1_IMP_ERR = None
|
||||
try:
|
||||
from keystoneauth1 import exceptions as ksa_exceptions
|
||||
HAS_KEYSTONEAUTH1 = True
|
||||
except ImportError:
|
||||
KEYSTONEAUTH1_IMP_ERR = traceback.format_exc()
|
||||
HAS_KEYSTONEAUTH1 = False
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (
|
||||
openstack_full_argument_spec,
|
||||
openstack_cloud_from_module,
|
||||
)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def _get_volume_quotas(cloud, project):
|
||||
|
||||
return cloud.get_volume_quotas(project)
|
||||
|
||||
|
||||
def _get_network_quotas(cloud, project):
|
||||
|
||||
return cloud.get_network_quotas(project)
|
||||
|
||||
|
||||
def _get_compute_quotas(cloud, project):
|
||||
|
||||
return cloud.get_compute_quotas(project)
|
||||
|
||||
|
||||
def _get_quotas(sdk, module, cloud, project):
|
||||
|
||||
quota = {}
|
||||
try:
|
||||
quota['volume'] = _get_volume_quotas(cloud, project)
|
||||
except ksa_exceptions.EndpointNotFound:
|
||||
module.warn("No public endpoint for volumev2 service was found. Ignoring volume quotas.")
|
||||
|
||||
try:
|
||||
quota['network'] = _get_network_quotas(cloud, project)
|
||||
except ksa_exceptions.EndpointNotFound:
|
||||
module.warn("No public endpoint for network service was found. Ignoring network quotas.")
|
||||
|
||||
quota['compute'] = _get_compute_quotas(cloud, project)
|
||||
|
||||
for quota_type in quota.keys():
|
||||
quota[quota_type] = _scrub_results(quota[quota_type])
|
||||
|
||||
return quota
|
||||
|
||||
|
||||
def _scrub_results(quota):
|
||||
|
||||
filter_attr = [
|
||||
'HUMAN_ID',
|
||||
'NAME_ATTR',
|
||||
'human_id',
|
||||
'request_ids',
|
||||
'x_openstack_request_ids',
|
||||
]
|
||||
|
||||
for attr in filter_attr:
|
||||
if attr in quota:
|
||||
del quota[attr]
|
||||
|
||||
return quota
|
||||
|
||||
|
||||
def _system_state_change_details(module, project_quota_output):
|
||||
|
||||
quota_change_request = {}
|
||||
changes_required = False
|
||||
|
||||
for quota_type in project_quota_output.keys():
|
||||
for quota_option in project_quota_output[quota_type].keys():
|
||||
if quota_option in module.params and module.params[quota_option] is not None:
|
||||
if project_quota_output[quota_type][quota_option] != module.params[quota_option]:
|
||||
changes_required = True
|
||||
|
||||
if quota_type not in quota_change_request:
|
||||
quota_change_request[quota_type] = {}
|
||||
|
||||
quota_change_request[quota_type][quota_option] = module.params[quota_option]
|
||||
|
||||
return (changes_required, quota_change_request)
|
||||
|
||||
|
||||
def _system_state_change(module, project_quota_output):
|
||||
"""
|
||||
Determine if changes are required to the current project quota.
|
||||
|
||||
This is done by comparing the current project_quota_output against
|
||||
the desired quota settings set on the module params.
|
||||
"""
|
||||
|
||||
changes_required, quota_change_request = _system_state_change_details(
|
||||
module,
|
||||
project_quota_output
|
||||
)
|
||||
|
||||
if changes_required:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class QuotaModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
name=dict(required=True),
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
backup_gigabytes=dict(required=False, type='int', default=None),
|
||||
@@ -381,7 +275,7 @@ def main():
|
||||
injected_files=dict(required=False, type='int', default=None),
|
||||
injected_path_size=dict(required=False, type='int', default=None),
|
||||
instances=dict(required=False, type='int', default=None),
|
||||
key_pairs=dict(required=False, type='int', default=None),
|
||||
key_pairs=dict(required=False, type='int', default=None, no_log=False),
|
||||
loadbalancer=dict(required=False, type='int', default=None),
|
||||
network=dict(required=False, type='int', default=None),
|
||||
per_volume_gigabytes=dict(required=False, type='int', default=None),
|
||||
@@ -404,16 +298,89 @@ def main():
|
||||
volumes_types=dict(required=False, type='dict', default={})
|
||||
)
|
||||
|
||||
module = AnsibleModule(argument_spec,
|
||||
supports_check_mode=True
|
||||
)
|
||||
module_kwargs = dict(
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
if not HAS_KEYSTONEAUTH1:
|
||||
module.fail_json(msg=missing_required_lib("keystoneauth1"), exception=KEYSTONEAUTH1_IMP_ERR)
|
||||
def _get_volume_quotas(self, project):
|
||||
return self.conn.get_volume_quotas(project)
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
cloud_params = dict(module.params)
|
||||
def _get_network_quotas(self, project):
|
||||
return self.conn.get_network_quotas(project)
|
||||
|
||||
def _get_compute_quotas(self, project):
|
||||
return self.conn.get_compute_quotas(project)
|
||||
|
||||
def _get_quotas(self, project):
|
||||
quota = {}
|
||||
try:
|
||||
quota['volume'] = self._get_volume_quotas(project)
|
||||
except Exception:
|
||||
self.warn("No public endpoint for volumev2 service was found. Ignoring volume quotas.")
|
||||
|
||||
try:
|
||||
quota['network'] = self._get_network_quotas(project)
|
||||
except Exception:
|
||||
self.warn("No public endpoint for network service was found. Ignoring network quotas.")
|
||||
|
||||
quota['compute'] = self._get_compute_quotas(project)
|
||||
|
||||
for quota_type in quota.keys():
|
||||
quota[quota_type] = self._scrub_results(quota[quota_type])
|
||||
|
||||
return quota
|
||||
|
||||
def _scrub_results(self, quota):
|
||||
filter_attr = [
|
||||
'HUMAN_ID',
|
||||
'NAME_ATTR',
|
||||
'human_id',
|
||||
'request_ids',
|
||||
'x_openstack_request_ids',
|
||||
]
|
||||
|
||||
for attr in filter_attr:
|
||||
if attr in quota:
|
||||
del quota[attr]
|
||||
|
||||
return quota
|
||||
|
||||
def _system_state_change_details(self, project_quota_output):
|
||||
quota_change_request = {}
|
||||
changes_required = False
|
||||
|
||||
for quota_type in project_quota_output.keys():
|
||||
for quota_option in project_quota_output[quota_type].keys():
|
||||
if quota_option in self.params and self.params[quota_option] is not None:
|
||||
if project_quota_output[quota_type][quota_option] != self.params[quota_option]:
|
||||
changes_required = True
|
||||
|
||||
if quota_type not in quota_change_request:
|
||||
quota_change_request[quota_type] = {}
|
||||
|
||||
quota_change_request[quota_type][quota_option] = self.params[quota_option]
|
||||
|
||||
return (changes_required, quota_change_request)
|
||||
|
||||
def _system_state_change(self, project_quota_output):
|
||||
"""
|
||||
Determine if changes are required to the current project quota.
|
||||
|
||||
This is done by comparing the current project_quota_output against
|
||||
the desired quota settings set on the module params.
|
||||
"""
|
||||
|
||||
changes_required, quota_change_request = self._system_state_change_details(
|
||||
project_quota_output
|
||||
)
|
||||
|
||||
if changes_required:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def run(self):
|
||||
cloud_params = dict(self.params)
|
||||
|
||||
# In order to handle the different volume types we update module params after.
|
||||
dynamic_types = [
|
||||
@@ -423,20 +390,19 @@ def main():
|
||||
]
|
||||
|
||||
for dynamic_type in dynamic_types:
|
||||
for k, v in module.params[dynamic_type].items():
|
||||
module.params[k] = int(v)
|
||||
for k, v in self.params[dynamic_type].items():
|
||||
self.params[k] = int(v)
|
||||
|
||||
# Get current quota values
|
||||
project_quota_output = _get_quotas(
|
||||
sdk, module, cloud, cloud_params['name'])
|
||||
project_quota_output = self._get_quotas(cloud_params['name'])
|
||||
changes_required = False
|
||||
|
||||
if module.params['state'] == "absent":
|
||||
if self.params['state'] == "absent":
|
||||
# If a quota state is set to absent we should assume there will be changes.
|
||||
# The default quota values are not accessible so we can not determine if
|
||||
# no changes will occur or not.
|
||||
if module.check_mode:
|
||||
module.exit_json(changed=True)
|
||||
if self.ansible.check_mode:
|
||||
self.exit_json(changed=True)
|
||||
|
||||
# Calling delete_network_quotas when a quota has not been set results
|
||||
# in an error, according to the sdk docs it should return the
|
||||
@@ -447,49 +413,48 @@ def main():
|
||||
neutron_msg2 = "could not be found"
|
||||
|
||||
for quota_type in project_quota_output.keys():
|
||||
quota_call = getattr(cloud, 'delete_%s_quotas' % (quota_type))
|
||||
quota_call = getattr(self.conn, 'delete_%s_quotas' % (quota_type))
|
||||
try:
|
||||
quota_call(cloud_params['name'])
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
except Exception as e:
|
||||
error_msg = str(e)
|
||||
if error_msg.find(neutron_msg1) > -1 and error_msg.find(neutron_msg2) > -1:
|
||||
pass
|
||||
else:
|
||||
module.fail_json(msg=str(e), extra_data=e.extra_data)
|
||||
self.fail_json(msg=str(e), extra_data=e.extra_data)
|
||||
|
||||
project_quota_output = _get_quotas(
|
||||
sdk, module, cloud, cloud_params['name'])
|
||||
project_quota_output = self._get_quotas(cloud_params['name'])
|
||||
changes_required = True
|
||||
|
||||
elif module.params['state'] == "present":
|
||||
if module.check_mode:
|
||||
module.exit_json(changed=_system_state_change(module, project_quota_output))
|
||||
elif self.params['state'] == "present":
|
||||
if self.ansible.check_mode:
|
||||
self.exit_json(changed=self._system_state_change(
|
||||
project_quota_output))
|
||||
|
||||
changes_required, quota_change_request = _system_state_change_details(
|
||||
module,
|
||||
changes_required, quota_change_request = self._system_state_change_details(
|
||||
project_quota_output
|
||||
)
|
||||
|
||||
if changes_required:
|
||||
for quota_type in quota_change_request.keys():
|
||||
quota_call = getattr(cloud, 'set_%s_quotas' % (quota_type))
|
||||
quota_call = getattr(self.conn, 'set_%s_quotas' % (quota_type))
|
||||
quota_call(cloud_params['name'], **quota_change_request[quota_type])
|
||||
|
||||
# Get quota state post changes for validation
|
||||
project_quota_update = _get_quotas(
|
||||
sdk, module, cloud, cloud_params['name'])
|
||||
project_quota_update = self._get_quotas(cloud_params['name'])
|
||||
|
||||
if project_quota_output == project_quota_update:
|
||||
module.fail_json(msg='Could not apply quota update')
|
||||
self.fail_json(msg='Could not apply quota update')
|
||||
|
||||
project_quota_output = project_quota_update
|
||||
|
||||
module.exit_json(changed=changes_required,
|
||||
openstack_quotas=project_quota_output
|
||||
)
|
||||
self.exit_json(
|
||||
changed=changes_required, openstack_quotas=project_quota_output)
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e), extra_data=e.extra_data)
|
||||
|
||||
def main():
|
||||
module = QuotaModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -122,29 +122,11 @@ recordset:
|
||||
sample: ['10.0.0.1']
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def _system_state_change(state, records, description, ttl, recordset):
|
||||
if state == 'present':
|
||||
if recordset is None:
|
||||
return True
|
||||
if records is not None and recordset['records'] != records:
|
||||
return True
|
||||
if description is not None and recordset['description'] != description:
|
||||
return True
|
||||
if ttl is not None and recordset['ttl'] != ttl:
|
||||
return True
|
||||
if state == 'absent' and recordset:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class DnsRecordsetModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
zone=dict(required=True),
|
||||
name=dict(required=True),
|
||||
recordset_type=dict(required=False, choices=['a', 'aaaa', 'mx', 'cname', 'txt', 'ns', 'srv', 'ptr', 'caa']),
|
||||
@@ -154,85 +136,102 @@ def main():
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
)
|
||||
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(argument_spec,
|
||||
required_if=[
|
||||
('state', 'present',
|
||||
['recordset_type', 'records'])],
|
||||
supports_check_mode=True,
|
||||
**module_kwargs)
|
||||
module_kwargs = dict(
|
||||
required_if=[
|
||||
('state', 'present',
|
||||
['recordset_type', 'records'])],
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
module.module_min_sdk_version = '0.28.0'
|
||||
zone = module.params.get('zone')
|
||||
name = module.params.get('name')
|
||||
state = module.params.get('state')
|
||||
module_min_sdk_version = '0.28.0'
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
recordsets = cloud.search_recordsets(zone, name_or_id=name)
|
||||
def _system_state_change(self, state, records, description, ttl, recordset):
|
||||
if state == 'present':
|
||||
if recordset is None:
|
||||
return True
|
||||
if records is not None and recordset['records'] != records:
|
||||
return True
|
||||
if description is not None and recordset['description'] != description:
|
||||
return True
|
||||
if ttl is not None and recordset['ttl'] != ttl:
|
||||
return True
|
||||
if state == 'absent' and recordset:
|
||||
return True
|
||||
return False
|
||||
|
||||
if recordsets:
|
||||
recordset = recordsets[0]
|
||||
try:
|
||||
recordset_id = recordset['id']
|
||||
except KeyError as e:
|
||||
module.fail_json(msg=str(e))
|
||||
else:
|
||||
# recordsets is filtered by type and should never be more than 1 return
|
||||
recordset = None
|
||||
def run(self):
|
||||
zone = self.params.get('zone')
|
||||
name = self.params.get('name')
|
||||
state = self.params.get('state')
|
||||
|
||||
if state == 'present':
|
||||
recordset_type = module.params.get('recordset_type').upper()
|
||||
records = module.params.get('records')
|
||||
description = module.params.get('description')
|
||||
ttl = module.params.get('ttl')
|
||||
recordsets = self.conn.search_recordsets(zone, name_or_id=name)
|
||||
|
||||
kwargs = {}
|
||||
if description:
|
||||
kwargs['description'] = description
|
||||
kwargs['records'] = records
|
||||
if recordsets:
|
||||
recordset = recordsets[0]
|
||||
try:
|
||||
recordset_id = recordset['id']
|
||||
except KeyError as e:
|
||||
self.fail_json(msg=str(e))
|
||||
else:
|
||||
# recordsets is filtered by type and should never be more than 1 return
|
||||
recordset = None
|
||||
|
||||
if module.check_mode:
|
||||
module.exit_json(changed=_system_state_change(state,
|
||||
records, description,
|
||||
ttl, recordset))
|
||||
if state == 'present':
|
||||
recordset_type = self.params.get('recordset_type').upper()
|
||||
records = self.params.get('records')
|
||||
description = self.params.get('description')
|
||||
ttl = self.params.get('ttl')
|
||||
|
||||
if recordset is None:
|
||||
if ttl:
|
||||
kwargs['ttl'] = ttl
|
||||
kwargs = {}
|
||||
if description:
|
||||
kwargs['description'] = description
|
||||
kwargs['records'] = records
|
||||
|
||||
if self.ansible.check_mode:
|
||||
self.exit_json(
|
||||
changed=self._system_state_change(
|
||||
state, records, description, ttl, recordset))
|
||||
|
||||
if recordset is None:
|
||||
if ttl:
|
||||
kwargs['ttl'] = ttl
|
||||
else:
|
||||
kwargs['ttl'] = 300
|
||||
|
||||
recordset = self.conn.create_recordset(
|
||||
zone=zone, name=name, recordset_type=recordset_type,
|
||||
**kwargs)
|
||||
changed = True
|
||||
else:
|
||||
kwargs['ttl'] = 300
|
||||
|
||||
recordset = cloud.create_recordset(
|
||||
zone=zone, name=name, recordset_type=recordset_type,
|
||||
**kwargs)
|
||||
changed = True
|
||||
else:
|
||||
if ttl:
|
||||
kwargs['ttl'] = ttl
|
||||
|
||||
if ttl:
|
||||
kwargs['ttl'] = ttl
|
||||
pre_update_recordset = recordset
|
||||
changed = self._system_state_change(
|
||||
state, records, description, ttl, pre_update_recordset)
|
||||
if changed:
|
||||
recordset = self.conn.update_recordset(
|
||||
zone=zone, name_or_id=recordset_id, **kwargs)
|
||||
|
||||
pre_update_recordset = recordset
|
||||
changed = _system_state_change(state, records,
|
||||
description, ttl,
|
||||
pre_update_recordset)
|
||||
if changed:
|
||||
recordset = cloud.update_recordset(
|
||||
zone=zone, name_or_id=recordset_id, **kwargs)
|
||||
self.exit_json(changed=changed, recordset=recordset)
|
||||
|
||||
module.exit_json(changed=changed, recordset=recordset)
|
||||
elif state == 'absent':
|
||||
if self.ansible.check_mode:
|
||||
self.exit_json(changed=self._system_state_change(
|
||||
state, None, None, None, recordset))
|
||||
|
||||
elif state == 'absent':
|
||||
if module.check_mode:
|
||||
module.exit_json(changed=_system_state_change(state,
|
||||
None, None,
|
||||
None, recordset))
|
||||
if recordset is None:
|
||||
changed = False
|
||||
else:
|
||||
self.conn.delete_recordset(zone, recordset_id)
|
||||
changed = True
|
||||
self.exit_json(changed=changed)
|
||||
|
||||
if recordset is None:
|
||||
changed = False
|
||||
else:
|
||||
cloud.delete_recordset(zone, recordset_id)
|
||||
changed = True
|
||||
module.exit_json(changed=changed)
|
||||
|
||||
def main():
|
||||
module = DnsRecordsetModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -72,35 +72,11 @@ RETURN = '''
|
||||
#
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def _system_state_change(state, assignment):
|
||||
if state == 'present' and not assignment:
|
||||
return True
|
||||
elif state == 'absent' and assignment:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _build_kwargs(user, group, project, domain):
|
||||
kwargs = {}
|
||||
if user:
|
||||
kwargs['user'] = user
|
||||
if group:
|
||||
kwargs['group'] = group
|
||||
if project:
|
||||
kwargs['project'] = project
|
||||
if domain:
|
||||
kwargs['domain'] = domain
|
||||
return kwargs
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class IdentityRoleAssignmentModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
role=dict(required=True),
|
||||
user=dict(required=False),
|
||||
group=dict(required=False),
|
||||
@@ -109,92 +85,111 @@ def main():
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
)
|
||||
|
||||
module_kwargs = openstack_module_kwargs(
|
||||
module_kwargs = dict(
|
||||
required_one_of=[
|
||||
['user', 'group']
|
||||
])
|
||||
module = AnsibleModule(argument_spec,
|
||||
supports_check_mode=True,
|
||||
**module_kwargs)
|
||||
],
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
role = module.params.get('role')
|
||||
user = module.params.get('user')
|
||||
group = module.params.get('group')
|
||||
project = module.params.get('project')
|
||||
domain = module.params.get('domain')
|
||||
state = module.params.get('state')
|
||||
def _system_state_change(self, state, assignment):
|
||||
if state == 'present' and not assignment:
|
||||
return True
|
||||
elif state == 'absent' and assignment:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _build_kwargs(self, user, group, project, domain):
|
||||
kwargs = {}
|
||||
if user:
|
||||
kwargs['user'] = user
|
||||
if group:
|
||||
kwargs['group'] = group
|
||||
if project:
|
||||
kwargs['project'] = project
|
||||
if domain:
|
||||
kwargs['domain'] = domain
|
||||
return kwargs
|
||||
|
||||
def run(self):
|
||||
role = self.params.get('role')
|
||||
user = self.params.get('user')
|
||||
group = self.params.get('group')
|
||||
project = self.params.get('project')
|
||||
domain = self.params.get('domain')
|
||||
state = self.params.get('state')
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
filters = {}
|
||||
domain_id = None
|
||||
|
||||
r = cloud.get_role(role)
|
||||
r = self.conn.get_role(role)
|
||||
if r is None:
|
||||
module.fail_json(msg="Role %s is not valid" % role)
|
||||
self.fail_json(msg="Role %s is not valid" % role)
|
||||
filters['role'] = r['id']
|
||||
|
||||
if domain:
|
||||
d = cloud.get_domain(name_or_id=domain)
|
||||
d = self.conn.get_domain(name_or_id=domain)
|
||||
if d is None:
|
||||
module.fail_json(msg="Domain %s is not valid" % domain)
|
||||
self.fail_json(msg="Domain %s is not valid" % domain)
|
||||
filters['domain'] = d['id']
|
||||
domain_id = d['id']
|
||||
if user:
|
||||
if domain:
|
||||
u = cloud.get_user(user, domain_id=filters['domain'])
|
||||
u = self.conn.get_user(user, domain_id=filters['domain'])
|
||||
else:
|
||||
u = cloud.get_user(user)
|
||||
u = self.conn.get_user(user)
|
||||
|
||||
if u is None:
|
||||
module.fail_json(msg="User %s is not valid" % user)
|
||||
self.fail_json(msg="User %s is not valid" % user)
|
||||
filters['user'] = u['id']
|
||||
if group:
|
||||
if domain:
|
||||
g = cloud.get_group(group, domain_id=filters['domain'])
|
||||
g = self.conn.get_group(group, domain_id=filters['domain'])
|
||||
else:
|
||||
g = cloud.get_group(group)
|
||||
g = self.conn.get_group(group)
|
||||
if g is None:
|
||||
module.fail_json(msg="Group %s is not valid" % group)
|
||||
self.fail_json(msg="Group %s is not valid" % group)
|
||||
filters['group'] = g['id']
|
||||
if project:
|
||||
if domain:
|
||||
p = cloud.get_project(project, domain_id=filters['domain'])
|
||||
p = self.conn.get_project(project, domain_id=filters['domain'])
|
||||
# OpenStack won't allow us to use both a domain and project as
|
||||
# filter. Once we identified the project (using the domain as
|
||||
# a filter criteria), we need to remove the domain itself from
|
||||
# the filters list.
|
||||
domain_id = filters.pop('domain')
|
||||
else:
|
||||
p = cloud.get_project(project)
|
||||
p = self.conn.get_project(project)
|
||||
|
||||
if p is None:
|
||||
module.fail_json(msg="Project %s is not valid" % project)
|
||||
self.fail_json(msg="Project %s is not valid" % project)
|
||||
filters['project'] = p['id']
|
||||
|
||||
assignment = cloud.list_role_assignments(filters=filters)
|
||||
assignment = self.conn.list_role_assignments(filters=filters)
|
||||
|
||||
if module.check_mode:
|
||||
module.exit_json(changed=_system_state_change(state, assignment))
|
||||
if self.ansible.check_mode:
|
||||
self.exit_json(changed=self._system_state_change(state, assignment))
|
||||
|
||||
changed = False
|
||||
|
||||
if state == 'present':
|
||||
if not assignment:
|
||||
kwargs = _build_kwargs(user, group, project, domain_id)
|
||||
cloud.grant_role(role, **kwargs)
|
||||
kwargs = self._build_kwargs(user, group, project, domain_id)
|
||||
self.conn.grant_role(role, **kwargs)
|
||||
changed = True
|
||||
|
||||
elif state == 'absent':
|
||||
if assignment:
|
||||
kwargs = _build_kwargs(user, group, project, domain_id)
|
||||
cloud.revoke_role(role, **kwargs)
|
||||
kwargs = self._build_kwargs(user, group, project, domain_id)
|
||||
self.conn.revoke_role(role, **kwargs)
|
||||
changed = True
|
||||
|
||||
module.exit_json(changed=changed)
|
||||
self.exit_json(changed=changed)
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
def main():
|
||||
module = IdentityRoleAssignmentModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -202,7 +202,7 @@ def _ports_match(protocol, module_min, module_max, rule_min, rule_max):
|
||||
"""
|
||||
|
||||
# Check if the user is supplying -1 for ICMP.
|
||||
if protocol == 'icmp':
|
||||
if protocol in ['icmp', 'ipv6-icmp']:
|
||||
if module_min and int(module_min) == -1:
|
||||
module_min = None
|
||||
if module_max and int(module_max) == -1:
|
||||
|
||||
@@ -119,7 +119,7 @@ class ServerActionModule(OpenStackModule):
|
||||
'lock', 'unlock', 'suspend', 'resume',
|
||||
'rebuild', 'shelve', 'shelve_offload', 'unshelve']),
|
||||
image=dict(required=False, type='str'),
|
||||
admin_password=dict(required=False, type='str'),
|
||||
admin_password=dict(required=False, type='str', no_log=True),
|
||||
)
|
||||
module_kwargs = dict(
|
||||
required_if=[('action', 'rebuild', ['image'])],
|
||||
|
||||
@@ -96,70 +96,66 @@ user_id:
|
||||
type: str
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def _system_state_change(state, server_group):
|
||||
if state == 'present' and not server_group:
|
||||
return True
|
||||
if state == 'absent' and server_group:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class ServerGroupModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
name=dict(required=True),
|
||||
policies=dict(required=False, type='list', elements='str'),
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
)
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(
|
||||
argument_spec,
|
||||
|
||||
module_kwargs = dict(
|
||||
supports_check_mode=True,
|
||||
**module_kwargs
|
||||
)
|
||||
|
||||
name = module.params['name']
|
||||
policies = module.params['policies']
|
||||
state = module.params['state']
|
||||
def _system_state_change(self, state, server_group):
|
||||
if state == 'present' and not server_group:
|
||||
return True
|
||||
if state == 'absent' and server_group:
|
||||
return True
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
server_group = cloud.get_server_group(name)
|
||||
return False
|
||||
|
||||
if module.check_mode:
|
||||
module.exit_json(
|
||||
changed=_system_state_change(state, server_group)
|
||||
def run(self):
|
||||
name = self.params['name']
|
||||
policies = self.params['policies']
|
||||
state = self.params['state']
|
||||
|
||||
server_group = self.conn.get_server_group(name)
|
||||
|
||||
if self.ansible.check_mode:
|
||||
self.exit_json(
|
||||
changed=self._system_state_change(state, server_group)
|
||||
)
|
||||
|
||||
changed = False
|
||||
if state == 'present':
|
||||
if not server_group:
|
||||
if not policies:
|
||||
module.fail_json(
|
||||
self.fail_json(
|
||||
msg="Parameter 'policies' is required in Server Group "
|
||||
"Create"
|
||||
)
|
||||
server_group = cloud.create_server_group(name, policies)
|
||||
server_group = self.conn.create_server_group(name, policies)
|
||||
changed = True
|
||||
|
||||
module.exit_json(
|
||||
self.exit_json(
|
||||
changed=changed,
|
||||
id=server_group['id'],
|
||||
server_group=server_group
|
||||
)
|
||||
if state == 'absent':
|
||||
if server_group:
|
||||
cloud.delete_server_group(server_group['id'])
|
||||
self.conn.delete_server_group(server_group['id'])
|
||||
changed = True
|
||||
module.exit_json(changed=changed)
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e), extra_data=e.extra_data)
|
||||
self.exit_json(changed=changed)
|
||||
|
||||
|
||||
def main():
|
||||
module = ServerGroupModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -93,77 +93,72 @@ metadata:
|
||||
sample: {'key1': 'value1', 'key2': 'value2'}
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (
|
||||
openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module,
|
||||
)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def _needs_update(server_metadata=None, metadata=None):
|
||||
if server_metadata is None:
|
||||
server_metadata = {}
|
||||
if metadata is None:
|
||||
metadata = {}
|
||||
return len(set(metadata.items()) - set(server_metadata.items())) != 0
|
||||
|
||||
|
||||
def _get_keys_to_delete(server_metadata_keys=None, metadata_keys=None):
|
||||
if server_metadata_keys is None:
|
||||
server_metadata_keys = []
|
||||
if metadata_keys is None:
|
||||
metadata_keys = []
|
||||
return set(server_metadata_keys) & set(metadata_keys)
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class ServerMetadataModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
server=dict(required=True, aliases=['name']),
|
||||
meta=dict(required=True, type='dict'),
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
)
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(argument_spec,
|
||||
supports_check_mode=True,
|
||||
**module_kwargs)
|
||||
module_kwargs = dict(
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
state = module.params['state']
|
||||
server_param = module.params['server']
|
||||
meta_param = module.params['meta']
|
||||
changed = False
|
||||
def _needs_update(self, server_metadata=None, metadata=None):
|
||||
if server_metadata is None:
|
||||
server_metadata = {}
|
||||
if metadata is None:
|
||||
metadata = {}
|
||||
return len(set(metadata.items()) - set(server_metadata.items())) != 0
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
server = cloud.get_server(server_param)
|
||||
def _get_keys_to_delete(self, server_metadata_keys=None, metadata_keys=None):
|
||||
if server_metadata_keys is None:
|
||||
server_metadata_keys = []
|
||||
if metadata_keys is None:
|
||||
metadata_keys = []
|
||||
return set(server_metadata_keys) & set(metadata_keys)
|
||||
|
||||
def run(self):
|
||||
state = self.params['state']
|
||||
server_param = self.params['server']
|
||||
meta_param = self.params['meta']
|
||||
changed = False
|
||||
|
||||
server = self.conn.get_server(server_param)
|
||||
if not server:
|
||||
module.fail_json(
|
||||
self.fail_json(
|
||||
msg='Could not find server {0}'.format(server_param))
|
||||
|
||||
if state == 'present':
|
||||
# check if it needs update
|
||||
if _needs_update(server_metadata=server.metadata,
|
||||
metadata=meta_param):
|
||||
if not module.check_mode:
|
||||
cloud.set_server_metadata(server_param, meta_param)
|
||||
if self._needs_update(
|
||||
server_metadata=server.metadata, metadata=meta_param
|
||||
):
|
||||
if not self.ansible.check_mode:
|
||||
self.conn.set_server_metadata(server_param, meta_param)
|
||||
changed = True
|
||||
elif state == 'absent':
|
||||
# remove from params the keys that do not exist in the server
|
||||
keys_to_delete = _get_keys_to_delete(server.metadata.keys(),
|
||||
meta_param.keys())
|
||||
keys_to_delete = self._get_keys_to_delete(
|
||||
server.metadata.keys(), meta_param.keys())
|
||||
if len(keys_to_delete) > 0:
|
||||
if not module.check_mode:
|
||||
cloud.delete_server_metadata(server_param, keys_to_delete)
|
||||
if not self.ansible.check_mode:
|
||||
self.conn.delete_server_metadata(
|
||||
server_param, keys_to_delete)
|
||||
changed = True
|
||||
|
||||
if changed:
|
||||
server = cloud.get_server(server_param)
|
||||
server = self.conn.get_server(server_param)
|
||||
|
||||
module.exit_json(
|
||||
self.exit_json(
|
||||
changed=changed, server_id=server.id, metadata=server.metadata)
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=e.message, extra_data=e.extra_data)
|
||||
|
||||
def main():
|
||||
module = ServerMetadataModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -145,74 +145,14 @@ stack:
|
||||
'updated_time': null}"
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module)
|
||||
from ansible.module_utils._text import to_native
|
||||
from distutils.version import StrictVersion
|
||||
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def _create_stack(module, stack, cloud, sdk, parameters):
|
||||
try:
|
||||
stack = cloud.create_stack(module.params['name'],
|
||||
template_file=module.params['template'],
|
||||
environment_files=module.params['environment'],
|
||||
timeout=module.params['timeout'],
|
||||
wait=True,
|
||||
rollback=module.params['rollback'],
|
||||
**parameters)
|
||||
|
||||
stack = cloud.get_stack(stack.id, None)
|
||||
if stack.stack_status == 'CREATE_COMPLETE':
|
||||
return stack
|
||||
else:
|
||||
module.fail_json(msg="Failure in creating stack: {0}".format(stack))
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
if hasattr(e, 'response'):
|
||||
module.fail_json(msg=to_native(e), response=e.response.json())
|
||||
else:
|
||||
module.fail_json(msg=to_native(e))
|
||||
|
||||
|
||||
def _update_stack(module, stack, cloud, sdk, parameters):
|
||||
try:
|
||||
stack = cloud.update_stack(
|
||||
module.params['name'],
|
||||
template_file=module.params['template'],
|
||||
environment_files=module.params['environment'],
|
||||
timeout=module.params['timeout'],
|
||||
rollback=module.params['rollback'],
|
||||
wait=module.params['wait'],
|
||||
**parameters)
|
||||
|
||||
if stack['stack_status'] == 'UPDATE_COMPLETE':
|
||||
return stack
|
||||
else:
|
||||
module.fail_json(msg="Failure in updating stack: %s" %
|
||||
stack['stack_status_reason'])
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
if hasattr(e, 'response'):
|
||||
module.fail_json(msg=to_native(e), response=e.response.json())
|
||||
else:
|
||||
module.fail_json(msg=to_native(e))
|
||||
|
||||
|
||||
def _system_state_change(module, stack, cloud):
|
||||
state = module.params['state']
|
||||
if state == 'present':
|
||||
if not stack:
|
||||
return True
|
||||
if state == 'absent' and stack:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class StackModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
name=dict(required=True),
|
||||
tag=dict(required=False, default=None),
|
||||
tag=dict(required=False, default=None, min_ver='0.28.0'),
|
||||
template=dict(default=None),
|
||||
environment=dict(default=None, type='list', elements='str'),
|
||||
parameters=dict(default={}, type='dict'),
|
||||
@@ -221,53 +161,87 @@ def main():
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
)
|
||||
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(argument_spec,
|
||||
supports_check_mode=True,
|
||||
**module_kwargs)
|
||||
module_kwargs = dict(
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
state = module.params['state']
|
||||
name = module.params['name']
|
||||
# Check for required parameters when state == 'present'
|
||||
if state == 'present':
|
||||
for p in ['template']:
|
||||
if not module.params[p]:
|
||||
module.fail_json(msg='%s required with present state' % p)
|
||||
def _create_stack(self, stack, parameters):
|
||||
stack = self.conn.create_stack(
|
||||
self.params['name'],
|
||||
template_file=self.params['template'],
|
||||
environment_files=self.params['environment'],
|
||||
timeout=self.params['timeout'],
|
||||
wait=True,
|
||||
rollback=self.params['rollback'],
|
||||
**parameters)
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
stack = cloud.get_stack(name)
|
||||
stack = self.conn.get_stack(stack.id, None)
|
||||
if stack.stack_status == 'CREATE_COMPLETE':
|
||||
return stack
|
||||
else:
|
||||
self.fail_json(msg="Failure in creating stack: {0}".format(stack))
|
||||
|
||||
if module.check_mode:
|
||||
module.exit_json(changed=_system_state_change(module, stack, cloud))
|
||||
def _update_stack(self, stack, parameters):
|
||||
stack = self.conn.update_stack(
|
||||
self.params['name'],
|
||||
template_file=self.params['template'],
|
||||
environment_files=self.params['environment'],
|
||||
timeout=self.params['timeout'],
|
||||
rollback=self.params['rollback'],
|
||||
wait=self.params['wait'],
|
||||
**parameters)
|
||||
|
||||
if stack['stack_status'] == 'UPDATE_COMPLETE':
|
||||
return stack
|
||||
else:
|
||||
self.fail_json(msg="Failure in updating stack: %s" %
|
||||
stack['stack_status_reason'])
|
||||
|
||||
def _system_state_change(self, stack):
|
||||
state = self.params['state']
|
||||
if state == 'present':
|
||||
if not stack:
|
||||
return True
|
||||
if state == 'absent' and stack:
|
||||
return True
|
||||
return False
|
||||
|
||||
def run(self):
|
||||
state = self.params['state']
|
||||
name = self.params['name']
|
||||
# Check for required parameters when state == 'present'
|
||||
if state == 'present':
|
||||
for p in ['template']:
|
||||
if not self.params[p]:
|
||||
self.fail_json(msg='%s required with present state' % p)
|
||||
|
||||
stack = self.conn.get_stack(name)
|
||||
|
||||
if self.ansible.check_mode:
|
||||
self.exit_json(changed=self._system_state_change(stack))
|
||||
|
||||
if state == 'present':
|
||||
parameters = module.params['parameters']
|
||||
if module.params['tag']:
|
||||
parameters['tags'] = module.params['tag']
|
||||
min_version = '0.28.0'
|
||||
if StrictVersion(sdk.version.__version__) < StrictVersion(min_version) and stack:
|
||||
module.warn("To update tags using openstack.cloud.stack module, the"
|
||||
"installed version of the openstacksdk"
|
||||
"library MUST be >={min_version}"
|
||||
"".format(min_version=min_version))
|
||||
parameters = self.params['parameters']
|
||||
if not stack:
|
||||
stack = _create_stack(module, stack, cloud, sdk, parameters)
|
||||
stack = self._create_stack(stack, parameters)
|
||||
else:
|
||||
stack = _update_stack(module, stack, cloud, sdk, parameters)
|
||||
module.exit_json(changed=True,
|
||||
stack=stack,
|
||||
id=stack.id)
|
||||
stack = self._update_stack(stack, parameters)
|
||||
self.exit_json(changed=True,
|
||||
stack=stack,
|
||||
id=stack.id)
|
||||
elif state == 'absent':
|
||||
if not stack:
|
||||
changed = False
|
||||
else:
|
||||
changed = True
|
||||
if not cloud.delete_stack(name, wait=module.params['wait']):
|
||||
module.fail_json(msg='delete stack failed for stack: %s' % name)
|
||||
module.exit_json(changed=changed)
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=to_native(e))
|
||||
if not self.conn.delete_stack(name, wait=self.params['wait']):
|
||||
self.fail_json(msg='delete stack failed for stack: %s' % name)
|
||||
self.exit_json(changed=changed)
|
||||
|
||||
|
||||
def main():
|
||||
module = StackModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -221,35 +221,37 @@ class SubnetModule(OpenStackModule):
|
||||
no_gateway_ip = self.params['no_gateway_ip']
|
||||
dns = self.params['dns_nameservers']
|
||||
host_routes = self.params['host_routes']
|
||||
curr_pool = dict(start=pool_start, end=pool_end)
|
||||
if pool_start and pool_end:
|
||||
pool = dict(start=pool_start, end=pool_end)
|
||||
else:
|
||||
pool = None
|
||||
|
||||
changes = dict()
|
||||
if subnet['enable_dhcp'] != enable_dhcp:
|
||||
return True
|
||||
changes['enable_dhcp'] = enable_dhcp
|
||||
if subnet_name and subnet['name'] != subnet_name:
|
||||
return True
|
||||
if not subnet['allocation_pools'] and pool_start and pool_end:
|
||||
return True
|
||||
if subnet['allocation_pools'] != [curr_pool]:
|
||||
return True
|
||||
changes['subnet_name'] = subnet_name
|
||||
if pool and (not subnet['allocation_pools'] or subnet['allocation_pools'] != [pool]):
|
||||
changes['allocation_pools'] = [pool]
|
||||
if gateway_ip and subnet['gateway_ip'] != gateway_ip:
|
||||
return True
|
||||
changes['gateway_ip'] = gateway_ip
|
||||
if dns and sorted(subnet['dns_nameservers']) != sorted(dns):
|
||||
return True
|
||||
changes['dns_nameservers'] = dns
|
||||
if host_routes:
|
||||
curr_hr = sorted(subnet['host_routes'], key=lambda t: t.keys())
|
||||
new_hr = sorted(host_routes, key=lambda t: t.keys())
|
||||
if curr_hr != new_hr:
|
||||
return True
|
||||
changes['host_routes'] = host_routes
|
||||
if no_gateway_ip and subnet['gateway_ip']:
|
||||
return True
|
||||
return False
|
||||
changes['disable_gateway_ip'] = no_gateway_ip
|
||||
return changes
|
||||
|
||||
def _system_state_change(self, subnet, filters=None):
|
||||
state = self.params['state']
|
||||
if state == 'present':
|
||||
if not subnet:
|
||||
return True
|
||||
return self._needs_update(subnet, filters)
|
||||
return bool(self._needs_update(subnet, filters))
|
||||
if state == 'absent' and subnet:
|
||||
return True
|
||||
return False
|
||||
@@ -334,15 +336,9 @@ class SubnetModule(OpenStackModule):
|
||||
subnet = self.conn.create_subnet(network_name, **kwargs)
|
||||
changed = True
|
||||
else:
|
||||
if self._needs_update(subnet, filters):
|
||||
subnet = self.conn.update_subnet(subnet['id'],
|
||||
subnet_name=subnet_name,
|
||||
enable_dhcp=enable_dhcp,
|
||||
gateway_ip=gateway_ip,
|
||||
disable_gateway_ip=no_gateway_ip,
|
||||
dns_nameservers=dns,
|
||||
allocation_pools=pool,
|
||||
host_routes=host_routes)
|
||||
changes = self._needs_update(subnet, filters)
|
||||
if changes:
|
||||
subnet = self.conn.update_subnet(subnet['id'], **changes)
|
||||
changed = True
|
||||
else:
|
||||
changed = False
|
||||
|
||||
@@ -188,6 +188,8 @@ class VolumeModule(OpenStackModule):
|
||||
)
|
||||
if self.params['image']:
|
||||
image_id = self.conn.get_image_id(self.params['image'])
|
||||
if not image_id:
|
||||
self.fail_json(msg="Failed to find image '%s'" % self.params['image'])
|
||||
volume_args['imageRef'] = image_id
|
||||
|
||||
if self.params['volume']:
|
||||
|
||||
@@ -83,61 +83,11 @@ snapshot:
|
||||
display_name: test_snapshot
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (
|
||||
openstack_full_argument_spec,
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module,
|
||||
)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
def _present_volume_snapshot(module, cloud):
|
||||
volume = cloud.get_volume(module.params['volume'])
|
||||
snapshot = cloud.get_volume_snapshot(module.params['display_name'],
|
||||
filters={'volume_id': volume.id})
|
||||
if not snapshot:
|
||||
snapshot = cloud.create_volume_snapshot(volume.id,
|
||||
force=module.params['force'],
|
||||
wait=module.params['wait'],
|
||||
timeout=module.params[
|
||||
'timeout'],
|
||||
name=module.params['display_name'],
|
||||
description=module.params.get(
|
||||
'display_description')
|
||||
)
|
||||
module.exit_json(changed=True, snapshot=snapshot)
|
||||
else:
|
||||
module.exit_json(changed=False, snapshot=snapshot)
|
||||
|
||||
|
||||
def _absent_volume_snapshot(module, cloud):
|
||||
volume = cloud.get_volume(module.params['volume'])
|
||||
snapshot = cloud.get_volume_snapshot(module.params['display_name'],
|
||||
filters={'volume_id': volume.id})
|
||||
if not snapshot:
|
||||
module.exit_json(changed=False)
|
||||
else:
|
||||
cloud.delete_volume_snapshot(name_or_id=snapshot.id,
|
||||
wait=module.params['wait'],
|
||||
timeout=module.params['timeout'],
|
||||
)
|
||||
module.exit_json(changed=True, snapshot_id=snapshot.id)
|
||||
|
||||
|
||||
def _system_state_change(module, cloud):
|
||||
volume = cloud.get_volume(module.params['volume'])
|
||||
snapshot = cloud.get_volume_snapshot(module.params['display_name'],
|
||||
filters={'volume_id': volume.id})
|
||||
state = module.params['state']
|
||||
|
||||
if state == 'present':
|
||||
return snapshot is None
|
||||
if state == 'absent':
|
||||
return snapshot is not None
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = openstack_full_argument_spec(
|
||||
class VolumeSnapshotModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
display_name=dict(required=True, aliases=['name']),
|
||||
display_description=dict(default=None, aliases=['description']),
|
||||
volume=dict(required=True),
|
||||
@@ -145,29 +95,72 @@ def main():
|
||||
state=dict(default='present', choices=['absent', 'present']),
|
||||
)
|
||||
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = AnsibleModule(argument_spec,
|
||||
supports_check_mode=True,
|
||||
**module_kwargs)
|
||||
module_kwargs = dict(
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
|
||||
state = module.params['state']
|
||||
|
||||
try:
|
||||
if cloud.volume_exists(module.params['volume']):
|
||||
if module.check_mode:
|
||||
module.exit_json(changed=_system_state_change(module, cloud))
|
||||
if state == 'present':
|
||||
_present_volume_snapshot(module, cloud)
|
||||
if state == 'absent':
|
||||
_absent_volume_snapshot(module, cloud)
|
||||
def _present_volume_snapshot(self):
|
||||
volume = self.conn.get_volume(self.params['volume'])
|
||||
snapshot = self.conn.get_volume_snapshot(
|
||||
self.params['display_name'], filters={'volume_id': volume.id})
|
||||
if not snapshot:
|
||||
snapshot = self.conn.create_volume_snapshot(
|
||||
volume.id,
|
||||
force=self.params['force'],
|
||||
wait=self.params['wait'],
|
||||
timeout=self.params['timeout'],
|
||||
name=self.params['display_name'],
|
||||
description=self.params.get('display_description')
|
||||
)
|
||||
self.exit_json(changed=True, snapshot=snapshot)
|
||||
else:
|
||||
module.fail_json(
|
||||
self.exit_json(changed=False, snapshot=snapshot)
|
||||
|
||||
def _absent_volume_snapshot(self):
|
||||
volume = self.conn.get_volume(self.params['volume'])
|
||||
snapshot = self.conn.get_volume_snapshot(
|
||||
self.params['display_name'], filters={'volume_id': volume.id})
|
||||
if not snapshot:
|
||||
self.exit_json(changed=False)
|
||||
else:
|
||||
self.conn.delete_volume_snapshot(
|
||||
name_or_id=snapshot.id,
|
||||
wait=self.params['wait'],
|
||||
timeout=self.params['timeout'],
|
||||
)
|
||||
self.exit_json(changed=True, snapshot_id=snapshot.id)
|
||||
|
||||
def _system_state_change(self):
|
||||
volume = self.conn.get_volume(self.params['volume'])
|
||||
snapshot = self.conn.get_volume_snapshot(
|
||||
self.params['display_name'],
|
||||
filters={'volume_id': volume.id})
|
||||
state = self.params['state']
|
||||
|
||||
if state == 'present':
|
||||
return snapshot is None
|
||||
if state == 'absent':
|
||||
return snapshot is not None
|
||||
|
||||
def run(self):
|
||||
state = self.params['state']
|
||||
|
||||
if self.conn.volume_exists(self.params['volume']):
|
||||
if self.ansible.check_mode:
|
||||
self.exit_json(changed=self._system_state_change())
|
||||
if state == 'present':
|
||||
self._present_volume_snapshot()
|
||||
if state == 'absent':
|
||||
self._absent_volume_snapshot()
|
||||
else:
|
||||
self.fail_json(
|
||||
msg="No volume with name or id '{0}' was found.".format(
|
||||
module.params['volume']))
|
||||
except (sdk.exceptions.OpenStackCloudException, sdk.exceptions.ResourceTimeout) as e:
|
||||
module.fail_json(msg=e.message)
|
||||
self.params['volume']))
|
||||
|
||||
|
||||
def main():
|
||||
module = VolumeSnapshotModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
1
requirements.txt
Normal file
1
requirements.txt
Normal file
@@ -0,0 +1 @@
|
||||
openstacksdk>=0.13
|
||||
@@ -1,12 +1,12 @@
|
||||
[metadata]
|
||||
name = ansible-collections-openstack.cloud
|
||||
summary = Ansible collections for Openstack cloud
|
||||
description-file =
|
||||
description_file =
|
||||
README.md
|
||||
|
||||
author = OpenStack
|
||||
author-email = openstack-discuss@lists.openstack.org
|
||||
home-page = https://opendev.org/openstack/ansible-collections-openstack/
|
||||
author_email = openstack-discuss@lists.openstack.org
|
||||
home_page = https://opendev.org/openstack/ansible-collections-openstack/
|
||||
classifier =
|
||||
License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
||||
Development Status :: 5 - Production/Stable
|
||||
@@ -17,7 +17,7 @@ classifier =
|
||||
Topic :: Utilities
|
||||
|
||||
[global]
|
||||
setup-hooks =
|
||||
setup_hooks =
|
||||
pbr.hooks.setup_hook
|
||||
|
||||
[files]
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
openstacksdk
|
||||
ansible-base
|
||||
pycodestyle
|
||||
flake8
|
||||
pylint
|
||||
voluptuous
|
||||
yamllint
|
||||
rstcheck
|
||||
ruamel.yaml
|
||||
#galaxy-importer # see https://review.opendev.org/#/c/743054
|
||||
tox
|
||||
@@ -1 +1 @@
|
||||
test-requirements-2.10.txt
|
||||
test-requirements-2.11.txt
|
||||
@@ -1,7 +0,0 @@
|
||||
plugins/modules/baremetal_node.py pylint:ansible-deprecated-no-collection-name
|
||||
plugins/modules/compute_flavor_info.py pylint:ansible-deprecated-no-collection-name
|
||||
plugins/modules/identity_domain_info.py pylint:ansible-deprecated-no-collection-name
|
||||
plugins/modules/identity_user_info.py pylint:ansible-deprecated-no-collection-name
|
||||
plugins/modules/port_info.py pylint:ansible-deprecated-no-collection-name
|
||||
plugins/modules/project_info.py pylint:ansible-deprecated-no-collection-name
|
||||
plugins/module_utils/openstack.py pylint:ansible-deprecated-no-collection-name
|
||||
@@ -1,7 +0,0 @@
|
||||
plugins/modules/baremetal_node.py pylint:ansible-deprecated-no-collection-name
|
||||
plugins/modules/compute_flavor_info.py pylint:ansible-deprecated-no-collection-name
|
||||
plugins/modules/identity_domain_info.py pylint:ansible-deprecated-no-collection-name
|
||||
plugins/modules/identity_user_info.py pylint:ansible-deprecated-no-collection-name
|
||||
plugins/modules/port_info.py pylint:ansible-deprecated-no-collection-name
|
||||
plugins/modules/project_info.py pylint:ansible-deprecated-no-collection-name
|
||||
plugins/module_utils/openstack.py pylint:ansible-deprecated-no-collection-name
|
||||
|
||||
0
tests/sanity/ignore-2.12.txt
Normal file
0
tests/sanity/ignore-2.12.txt
Normal file
Reference in New Issue
Block a user