mirror of
https://opendev.org/openstack/ansible-collections-openstack.git
synced 2026-03-27 14:03:03 +00:00
Compare commits
703 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c0a9f2d94 | ||
|
|
b1ecd54a5d | ||
|
|
4a3460e727 | ||
|
|
c9887b3a23 | ||
|
|
e84ebb0773 | ||
|
|
f584c54dfd | ||
|
|
3901000119 | ||
|
|
556208fc3c | ||
|
|
3ac95541da | ||
|
|
59b5b33557 | ||
|
|
3d7948a4e4 | ||
|
|
6cb5ed4b84 | ||
|
|
283c342b10 | ||
|
|
2a5fb584e2 | ||
|
|
762fee2bad | ||
|
|
9d92897522 | ||
|
|
df0b57a3c6 | ||
|
|
5a6f5084dd | ||
|
|
c988b3bcbf | ||
|
|
437438e33c | ||
|
|
3fd79d342c | ||
|
|
98bb212ae4 | ||
|
|
08d8cd8c25 | ||
|
|
41cf92df99 | ||
|
|
5494d153b1 | ||
|
|
fef560eb5b | ||
|
|
1ce7dd8b5f | ||
|
|
438bbea34b | ||
|
|
239c45c78f | ||
|
|
e065818024 | ||
|
|
0764e671a9 | ||
|
|
5f4db3583e | ||
|
|
6262474c94 | ||
|
|
f9fcd35018 | ||
|
|
5dbf47cb49 | ||
|
|
57c63e7918 | ||
|
|
ed5829d462 | ||
|
|
b025e7c356 | ||
|
|
782340833e | ||
|
|
73aab9e80c | ||
|
|
ae7e8260a3 | ||
|
|
030df96dc0 | ||
|
|
c5d0d3ec82 | ||
|
|
0cff7eb3a2 | ||
|
|
29e3f3dac8 | ||
|
|
d18ea87091 | ||
|
|
529c1e8dcc | ||
|
|
99b7af529c | ||
|
|
2ed3ffe1d0 | ||
|
|
ae5dbf0fc0 | ||
|
|
4074db1bd0 | ||
|
|
3248ba9960 | ||
|
|
2d5ca42629 | ||
|
|
83456005fc | ||
|
|
5b61019a34 | ||
|
|
630dac3787 | ||
|
|
54c2257376 | ||
|
|
c843feb338 | ||
|
|
28541ee158 | ||
|
|
c09029ada0 | ||
|
|
903eeb7db7 | ||
|
|
03ebbaed93 | ||
|
|
8d9b8b9a35 | ||
|
|
fef5e127d4 | ||
|
|
01d3011895 | ||
|
|
d4f25d2282 | ||
|
|
3df5c38ca6 | ||
|
|
474b3804eb | ||
|
|
5a8ad4cdf0 | ||
|
|
e742016861 | ||
|
|
40a384214c | ||
|
|
1188af2486 | ||
|
|
e42e21f621 | ||
|
|
e6379e3038 | ||
|
|
e0dc4776bb | ||
|
|
22941e86d1 | ||
|
|
b089d56136 | ||
|
|
536fe731f7 | ||
|
|
4a8214b196 | ||
|
|
d1b77a3546 | ||
|
|
8aefe5dc3a | ||
|
|
217e965357 | ||
|
|
94afde008b | ||
|
|
032a5222c1 | ||
|
|
fa6eb547ab | ||
|
|
23290a568b | ||
|
|
69801f268f | ||
|
|
0c6aee5378 | ||
|
|
fb258ababa | ||
|
|
4c186a2ae6 | ||
|
|
598cc2d743 | ||
|
|
e0139fe940 | ||
|
|
bc65d42f52 | ||
|
|
ac4d105813 | ||
|
|
747c4d23bc | ||
|
|
93d51498e9 | ||
|
|
cfd2d1f773 | ||
|
|
e009f80ffc | ||
|
|
08c93cf9b1 | ||
|
|
fff978d273 | ||
|
|
9fb544d94a | ||
|
|
94ed95c8b6 | ||
|
|
4ab054790c | ||
|
|
2c68080758 | ||
|
|
6e680d594b | ||
|
|
b25e93dbdd | ||
|
|
0aedc268f1 | ||
|
|
9b47cb4b59 | ||
|
|
8612171af3 | ||
|
|
8f321eaeb2 | ||
|
|
147ad6c452 | ||
|
|
407369da6e | ||
|
|
0a371445eb | ||
|
|
2808d1c155 | ||
|
|
c30e4db77c | ||
|
|
ab6f2e45c6 | ||
|
|
568adcb890 | ||
|
|
18cf839db4 | ||
|
|
454a05452b | ||
|
|
ad9594dcd7 | ||
|
|
62c0169e64 | ||
|
|
497f020100 | ||
|
|
92c3e87467 | ||
|
|
f73a0e385e | ||
|
|
b6b5f63877 | ||
|
|
edd4e1b2e9 | ||
|
|
01e1742acf | ||
|
|
5b77519b89 | ||
|
|
19d1d41ee0 | ||
|
|
f758dfa626 | ||
|
|
34017d511b | ||
|
|
70c029fa50 | ||
|
|
d5ab2bf33f | ||
|
|
754ae5e50d | ||
|
|
546f24940f | ||
|
|
f507465c9e | ||
|
|
90b110794f | ||
|
|
c9afdbfd73 | ||
|
|
4a27306440 | ||
|
|
8534990840 | ||
|
|
16a8a9e5d4 | ||
|
|
a4a6e6d4ec | ||
|
|
778cf14f1b | ||
|
|
1b38b7c500 | ||
|
|
a46bbd0d48 | ||
|
|
39ffebea4c | ||
|
|
cc9ca5a34b | ||
|
|
1f8c9fee05 | ||
|
|
0c75f19e4c | ||
|
|
e34f259566 | ||
|
|
5aaa41c9c4 | ||
|
|
eaa26c6b9c | ||
|
|
0071fdcd97 | ||
|
|
124e174d27 | ||
|
|
4dc6c421db | ||
|
|
4cf6842222 | ||
|
|
647ffef375 | ||
|
|
97c4531d15 | ||
|
|
407b50c8b2 | ||
|
|
122afc170c | ||
|
|
52e7bfe7a4 | ||
|
|
7d9de2858a | ||
|
|
852d971d50 | ||
|
|
3b0ae6c43f | ||
|
|
7945d7f01a | ||
|
|
85fa2bb2b6 | ||
|
|
133af96666 | ||
|
|
51f1fea8b3 | ||
|
|
94c150b2e7 | ||
|
|
6b911ebd21 | ||
|
|
cec58d7560 | ||
|
|
0e07b15f92 | ||
|
|
7c536e69b3 | ||
|
|
1ca6f208f7 | ||
|
|
00ec3f1c92 | ||
|
|
0f37ed795b | ||
|
|
daf79de37e | ||
|
|
961bdb5bd5 | ||
|
|
d3c5ddd40f | ||
|
|
114bc855c0 | ||
|
|
5862d91615 | ||
|
|
4fe73c978a | ||
|
|
cd002a5555 | ||
|
|
d0ac32eefd | ||
|
|
d07778c24a | ||
|
|
a8f6dbd904 | ||
|
|
b3c2e8f1ce | ||
|
|
8c889f8eb3 | ||
|
|
764a8bff64 | ||
|
|
e9cd9bff2a | ||
|
|
8955110586 | ||
|
|
a180f339a8 | ||
|
|
53da712635 | ||
|
|
1e27b6b69c | ||
|
|
65ac75b518 | ||
|
|
2f87448567 | ||
|
|
4e1718db49 | ||
|
|
97fa59bf6f | ||
|
|
c13fac3796 | ||
|
|
99074ccd12 | ||
|
|
65a7e74b2b | ||
|
|
902b2f8147 | ||
|
|
f51898bd2f | ||
|
|
7bad5cfd42 | ||
|
|
34b0abb4ca | ||
|
|
0ade33eb6f | ||
|
|
ed36d82a0c | ||
|
|
41299b9666 | ||
|
|
a660a35d86 | ||
|
|
f0cb7f6802 | ||
|
|
6ab3d76696 | ||
|
|
40d913d2a6 | ||
|
|
41f3007a80 | ||
|
|
b416a3e242 | ||
|
|
ebaa1ac357 | ||
|
|
57cc3e6aad | ||
|
|
9f3f0837c8 | ||
|
|
8a80113d54 | ||
|
|
ffa84bd705 | ||
|
|
c0bc0b0796 | ||
|
|
fb0fb529b7 | ||
|
|
2d0656f072 | ||
|
|
515cc66287 | ||
|
|
73827a3d57 | ||
|
|
f2bf56d984 | ||
|
|
6d8c965333 | ||
|
|
81a81ad759 | ||
|
|
b99218c143 | ||
|
|
d47cf4333c | ||
|
|
8563e2327c | ||
|
|
4df7a12ebf | ||
|
|
0ec16fbecc | ||
|
|
5e7c29d97e | ||
|
|
d0eb83e934 | ||
|
|
ce6193cd2f | ||
|
|
fdc67892e3 | ||
|
|
d2eb98d048 | ||
|
|
1bf22feb2d | ||
|
|
ac401bb354 | ||
|
|
3fdbd56a58 | ||
|
|
0b2b56765c | ||
|
|
ccbbc319ce | ||
|
|
0215e2a5d4 | ||
|
|
ceae5c1030 | ||
|
|
2d60a045a6 | ||
|
|
b87ae7dcce | ||
|
|
fd15087c4d | ||
|
|
960e5df17f | ||
|
|
bae75b84bd | ||
|
|
eda2e301c3 | ||
|
|
b250b76c33 | ||
|
|
fc2dda1d86 | ||
|
|
1f5a2019a0 | ||
|
|
7ec8e4d087 | ||
|
|
070e77feca | ||
|
|
a120db2d60 | ||
|
|
96be88af21 | ||
|
|
d600284645 | ||
|
|
0e675a9129 | ||
|
|
19cd6262cf | ||
|
|
e0958c605e | ||
|
|
aa19d74cde | ||
|
|
2419b5ab19 | ||
|
|
caf1bc49da | ||
|
|
ad3a3a89f2 | ||
|
|
c6c1c6a070 | ||
|
|
bcca2efe1a | ||
|
|
802e46d554 | ||
|
|
160d0dea4d | ||
|
|
8f27184f30 | ||
|
|
9b62cd7734 | ||
|
|
595f7d1093 | ||
|
|
86b573883a | ||
|
|
c54b34db3f | ||
|
|
6767db64c2 | ||
|
|
452404ee87 | ||
|
|
8d5195fdf2 | ||
|
|
7c7e61d36b | ||
|
|
9272146cf7 | ||
|
|
a9fa496ebe | ||
|
|
d6cdad2c42 | ||
|
|
d65ea4d560 | ||
|
|
4ea2c5b50d | ||
|
|
97b05533f1 | ||
|
|
dee39a71b6 | ||
|
|
1b59c19a24 | ||
|
|
4bfa135b20 | ||
|
|
c7ae7a5f98 | ||
|
|
4db7a6238b | ||
|
|
a6805cd019 | ||
|
|
80ef209336 | ||
|
|
c1a9794207 | ||
|
|
1d22a94a90 | ||
|
|
fdf4999747 | ||
|
|
b31fdf8320 | ||
|
|
fd1b9fc0d2 | ||
|
|
a8589e9f4d | ||
|
|
2df07f3523 | ||
|
|
c83e0e39b1 | ||
|
|
92566dedae | ||
|
|
cc1b5ecae8 | ||
|
|
4a7330364e | ||
|
|
cf5007d478 | ||
|
|
c10cc9dd8c | ||
|
|
3ead86904a | ||
|
|
9f60f0f26d | ||
|
|
e85a0b809a | ||
|
|
bba1da17c9 | ||
|
|
bc6622e0e7 | ||
|
|
e869564e3c | ||
|
|
0c6e8bed69 | ||
|
|
5a43bdb873 | ||
|
|
bb25330ddc | ||
|
|
ecf4897a55 | ||
|
|
f09cccdb9e | ||
|
|
2bf82c2669 | ||
|
|
5fc8fca06b | ||
|
|
411c2ddc8c | ||
|
|
41ad425d23 | ||
|
|
c075126ebd | ||
|
|
1ec9afe2ca | ||
|
|
ffa826c0d0 | ||
|
|
4c3dfec59d | ||
|
|
453601bde2 | ||
|
|
bf2c20f590 | ||
|
|
a03dd05465 | ||
|
|
b376e3e146 | ||
|
|
938abd0d84 | ||
|
|
749f04bcfb | ||
|
|
27e113780f | ||
|
|
19b05f689c | ||
|
|
d44915caba | ||
|
|
e2ee2d0f5d | ||
|
|
771fb68f99 | ||
|
|
c6892c83c9 | ||
|
|
5b53433348 | ||
|
|
7b26b82890 | ||
|
|
e28ab9acec | ||
|
|
cc604d354c | ||
|
|
7820d9ca60 | ||
|
|
aae539ac8c | ||
|
|
5f1ffe2b99 | ||
|
|
a162a02536 | ||
|
|
2e89bbe609 | ||
|
|
187a578842 | ||
|
|
61e20bb945 | ||
|
|
879270aa47 | ||
|
|
5bc179a978 | ||
|
|
8147294a7a | ||
|
|
002e55e269 | ||
|
|
52246bb610 | ||
|
|
99e2e2cee6 | ||
|
|
b640e6207c | ||
|
|
da4a68c188 | ||
|
|
a7a190f3c0 | ||
|
|
ce73c9db34 | ||
|
|
0e102b1411 | ||
|
|
9f58d54721 | ||
|
|
ea2ee76a88 | ||
|
|
9d0e5dd1db | ||
|
|
08bbadedb0 | ||
|
|
3c7a8f39a2 | ||
|
|
aa22867536 | ||
|
|
37a51ec6ad | ||
|
|
79d7827d17 | ||
|
|
ba9aa9967f | ||
|
|
617e8fb552 | ||
|
|
5abf89d805 | ||
|
|
0599d05103 | ||
|
|
9c28af7d12 | ||
|
|
bcb5d18492 | ||
|
|
7aa626377b | ||
|
|
0a7889b9a2 | ||
|
|
a1b920742f | ||
|
|
bd55e1f905 | ||
|
|
20329c0329 | ||
|
|
bdf472a53f | ||
|
|
b7fb23b097 | ||
|
|
6ed02eff2d | ||
|
|
cb396cf03d | ||
|
|
20c2633ea3 | ||
|
|
6569e07023 | ||
|
|
031475d42e | ||
|
|
5e2ab3d8c3 | ||
|
|
f3b12fed68 | ||
|
|
39a627d4a0 | ||
|
|
4eb7c43539 | ||
|
|
8c6d1041fa | ||
|
|
26530ac97b | ||
|
|
b3e07a1864 | ||
|
|
94933250e8 | ||
|
|
1582956dcd | ||
|
|
b1952e0c4b | ||
|
|
9cd6d2f69a | ||
|
|
86a57498e8 | ||
|
|
15f73aa72e | ||
|
|
22a7f516f3 | ||
|
|
de54be5ecd | ||
|
|
3f1a693bd6 | ||
|
|
8e87ad651f | ||
|
|
b2f3cf3210 | ||
|
|
11c7cd23f8 | ||
|
|
59d0e4c3a4 | ||
|
|
014665ddac | ||
|
|
21b70f6b9b | ||
|
|
ecaff2a798 | ||
|
|
02e9e87964 | ||
|
|
980536c32e | ||
|
|
a9a0d23441 | ||
|
|
011515de2d | ||
|
|
4292a00f75 | ||
|
|
bbefa8c156 | ||
|
|
b023aa337a | ||
|
|
c13f02fd54 | ||
|
|
ae4e7f3c06 | ||
|
|
2d554d1e22 | ||
|
|
770b283593 | ||
|
|
42921c6d9f | ||
|
|
292aabb477 | ||
|
|
3a08a9c07c | ||
|
|
0e370b2c51 | ||
|
|
0441403c42 | ||
|
|
4160888887 | ||
|
|
07374a1f0d | ||
|
|
8a395a04cf | ||
|
|
441a61fd8c | ||
|
|
c05b1fdbaf | ||
|
|
9cd92208d6 | ||
|
|
5ef192f1f2 | ||
|
|
aed60716ee | ||
|
|
938b90ea19 | ||
|
|
ce853a8f9f | ||
|
|
9911c7f93a | ||
|
|
8c890e656b | ||
|
|
b839f9e25d | ||
|
|
b7765776a7 | ||
|
|
4490e008c4 | ||
|
|
f376d4679e | ||
|
|
12ec8c63c2 | ||
|
|
72f371c157 | ||
|
|
ce421fe370 | ||
|
|
f20ec3a151 | ||
|
|
a89ec027b0 | ||
|
|
322f96c4db | ||
|
|
50b55560fc | ||
|
|
0c0013504e | ||
|
|
e651838f3e | ||
|
|
4553282545 | ||
|
|
235628dace | ||
|
|
4ee8621b37 | ||
|
|
d07039a7ec | ||
|
|
54728a83fa | ||
|
|
8431232eeb | ||
|
|
b21b8b1084 | ||
|
|
e2ffed388e | ||
|
|
ff44a1d1e5 | ||
|
|
9f893824c5 | ||
|
|
b9df964149 | ||
|
|
0c8fe9002e | ||
|
|
e010db6273 | ||
|
|
88277a59af | ||
|
|
1a4d0128c7 | ||
|
|
03a86669de | ||
|
|
fa7526a0ec | ||
|
|
7446ab23b8 | ||
|
|
4171ee52b7 | ||
|
|
60f1b8e2a5 | ||
|
|
0bff3f286f | ||
|
|
5188e281b9 | ||
|
|
966b6597f3 | ||
|
|
5636d502ce | ||
|
|
4db925b452 | ||
|
|
3ce4455bc8 | ||
|
|
309c3025ba | ||
|
|
637d321a9a | ||
|
|
74c18f34f3 | ||
|
|
00be40a462 | ||
|
|
1eb5d85b68 | ||
|
|
d0a4d6e8cc | ||
|
|
29c03592cc | ||
|
|
7888b51053 | ||
|
|
0e4dc21bab | ||
|
|
623b4afbd1 | ||
|
|
80e6597f96 | ||
|
|
8f1512166e | ||
|
|
eabe945194 | ||
|
|
06115c77b7 | ||
|
|
4a1b092efb | ||
|
|
da1fab6629 | ||
|
|
0efb855c68 | ||
|
|
329a5ef50d | ||
|
|
47708e0172 | ||
|
|
17d5c7de8e | ||
|
|
82792ab5d5 | ||
|
|
d4033b4cea | ||
|
|
426b6e782a | ||
|
|
75b2c60960 | ||
|
|
c9527889a0 | ||
|
|
42a5cb5601 | ||
|
|
aa387aab3a | ||
|
|
af79857bfb | ||
|
|
a51d922bee | ||
|
|
0cbaeb6fbb | ||
|
|
532857c0b2 | ||
|
|
acd9bc993b | ||
|
|
0904ddd2fe | ||
|
|
2120814356 | ||
|
|
ad70a20af5 | ||
|
|
a32cff23c7 | ||
|
|
f29a8407af | ||
|
|
555178ecc6 | ||
|
|
f93172677c | ||
|
|
2a461cadd9 | ||
|
|
e3c61aeefd | ||
|
|
3e4413ec31 | ||
|
|
37afe5f2e6 | ||
|
|
7e190d12b4 | ||
|
|
3d9f9a0f87 | ||
|
|
57e1087177 | ||
|
|
6cb6e70645 | ||
|
|
662ac61640 | ||
|
|
891fb6df53 | ||
|
|
0c6752215b | ||
|
|
a6f1177584 | ||
|
|
2dc2806c57 | ||
|
|
59df183660 | ||
|
|
2c287d754c | ||
|
|
28d32b53e8 | ||
|
|
2cb67620aa | ||
|
|
5217b6bdc4 | ||
|
|
96ea60a883 | ||
|
|
0eef3cb978 | ||
|
|
e695000daa | ||
|
|
0258878400 | ||
|
|
ea7ba854d5 | ||
|
|
6b3bf3bba0 | ||
|
|
daaa6bf561 | ||
|
|
2027eb1f46 | ||
|
|
944f9ca498 | ||
|
|
ca6824bffe | ||
|
|
a10be98638 | ||
|
|
6787924f13 | ||
|
|
d1d6b4d2dd | ||
|
|
06e76a1687 | ||
|
|
464d7767bb | ||
|
|
718f3a6b3a | ||
|
|
3320c662c8 | ||
|
|
77acba047b | ||
|
|
890401b605 | ||
|
|
8da4e852f0 | ||
|
|
f3e9c78c18 | ||
|
|
47382d52ed | ||
|
|
0e2058988e | ||
|
|
ab1a2a19d7 | ||
|
|
17a1d72b1c | ||
|
|
58ec1030a4 | ||
|
|
da01746e53 | ||
|
|
c329f65b41 | ||
|
|
18b03e1971 | ||
|
|
16a81fc221 | ||
|
|
50deae71f4 | ||
|
|
b1e5ca91cf | ||
|
|
185d0a5eca | ||
|
|
2b8aa2cb08 | ||
|
|
3c8fbc6b27 | ||
|
|
d212be018b | ||
|
|
573e219e30 | ||
|
|
5c3750df2c | ||
|
|
94e0e10e49 | ||
|
|
db9a8d5a18 | ||
|
|
7e20a8fc97 | ||
|
|
c7969aa052 | ||
|
|
179a500903 | ||
|
|
ab3e136867 | ||
|
|
8d2391d873 | ||
|
|
e1d62ff73a | ||
|
|
c3261d9813 | ||
|
|
1d8605fbf7 | ||
|
|
0843990dee | ||
|
|
6f8b39bb16 | ||
|
|
c39c8f9d74 | ||
|
|
e4c7bd3df8 | ||
|
|
8a4974025f | ||
|
|
51a9731cef | ||
|
|
051b270d36 | ||
|
|
ca234d7e42 | ||
|
|
5967e1ad0a | ||
|
|
bca980c115 | ||
|
|
a55b817968 | ||
|
|
b7c22515b7 | ||
|
|
70c773fe6d | ||
|
|
a3f809eb99 | ||
|
|
049a2de725 | ||
|
|
69947cd9fd | ||
|
|
c68b33f79f | ||
|
|
62f0da75bb | ||
|
|
6e2bde4060 | ||
|
|
e4a223d160 | ||
|
|
6d4d8d4b0c | ||
|
|
a4e6d1b67c | ||
|
|
3aaf7ff03a | ||
|
|
f6a5433503 | ||
|
|
92c10638a9 | ||
|
|
e3317db56d | ||
|
|
870f82d97b | ||
|
|
87c305907e | ||
|
|
c532560d1b | ||
|
|
ea1f1df805 | ||
|
|
40a32c1e8b | ||
|
|
5881f5423a | ||
|
|
51eba6de02 | ||
|
|
93faf4f1c3 | ||
|
|
c03284abec | ||
|
|
49c95804ba | ||
|
|
c8a5be6b30 | ||
|
|
8255ec4c80 | ||
|
|
36ce09a781 | ||
|
|
0ac75add62 | ||
|
|
d004e0af05 | ||
|
|
b040392238 | ||
|
|
19f24568a2 | ||
|
|
9783fbb972 | ||
|
|
b87e474192 | ||
|
|
c1b8786160 | ||
|
|
981d268039 | ||
|
|
af27a79312 | ||
|
|
e504d807de | ||
|
|
faada98ed9 | ||
|
|
c914c42799 | ||
|
|
d5c403cded | ||
|
|
d36ac1f125 | ||
|
|
15675ce23f | ||
|
|
8180fe8af8 | ||
|
|
88f03fa1df | ||
|
|
565f7fd369 | ||
|
|
47a0d625dc | ||
|
|
b09d8248f7 | ||
|
|
bce3eea5c0 | ||
|
|
134a8e9d23 | ||
|
|
9ed9b1d399 | ||
|
|
80abd782da | ||
|
|
ee9a5c564e | ||
|
|
393b484e5a | ||
|
|
6117f7062e | ||
|
|
f89eea10b4 | ||
|
|
e1178fde34 | ||
|
|
8b35c64fda | ||
|
|
8b98452cbb | ||
|
|
d081bb5378 | ||
|
|
2ce1adad4a | ||
|
|
8ca8df1a84 | ||
|
|
058cb4ff3f | ||
|
|
1c6663999d | ||
|
|
ab96eb6a11 | ||
|
|
38e61994c7 | ||
|
|
d416a27112 | ||
|
|
631e1412a0 | ||
|
|
4c31ea152e | ||
|
|
a39470ac2b | ||
|
|
39a8362d7a | ||
|
|
05da83520e | ||
|
|
a6b52612de | ||
|
|
a67272d1f5 | ||
|
|
f448c78dd4 | ||
|
|
33ce7ab9c7 | ||
|
|
03fadf3b43 | ||
|
|
86a5cc3b42 | ||
|
|
8731fcc64b | ||
|
|
f6a7cf5343 | ||
|
|
284d7871ce | ||
|
|
fcf6fae499 | ||
|
|
88b86be33e | ||
|
|
1f3417cdef | ||
|
|
8792b2b527 | ||
|
|
4a930cf0ec | ||
|
|
e1fe3f6067 | ||
|
|
40ce8103f4 | ||
|
|
bbe1d84448 | ||
|
|
9600baec6e | ||
|
|
abebbe722c | ||
|
|
94e518e42c | ||
|
|
a96d28dfbc | ||
|
|
32ef77d9fd | ||
|
|
4b64ebe623 | ||
|
|
01c2499fb6 | ||
|
|
5e3a91a7c6 | ||
|
|
fc852da4bc | ||
|
|
5717f05102 | ||
|
|
4d0df9f022 | ||
|
|
f8c768ae61 | ||
|
|
4d1017d5d9 | ||
|
|
c75ab0924a | ||
|
|
dfa7983a78 | ||
|
|
8e2e5966b7 | ||
|
|
c9da50e7e7 | ||
|
|
f3610ad0e1 | ||
|
|
7e4fbcf568 | ||
|
|
f89644973d | ||
|
|
b4f015ebd7 | ||
|
|
f0da22da7e | ||
|
|
d206ea000a | ||
|
|
5667600420 | ||
|
|
98ce765383 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,7 +1,6 @@
|
||||
.tox
|
||||
build_artifact
|
||||
ansible_collections
|
||||
galaxy.yml
|
||||
FILES.json
|
||||
MANIFEST.json
|
||||
importer_result.json
|
||||
|
||||
491
.zuul.yaml
491
.zuul.yaml
@@ -1,31 +1,228 @@
|
||||
# yamllint disable
|
||||
---
|
||||
# Keep parent jobs in sync between branches to avoid issues e.g. with job scheduling. Zuul CI will search in master
|
||||
# branch first when collecting job variants during job freeze which can have unwanted side effects. For example, when
|
||||
# parent job *-base has been changed in stable/1.0.0 branch, Zuul could still use *-base variants from master branch
|
||||
# during job freeze on child jobs such as *-ussuri-ansible-2.11 etc.
|
||||
#
|
||||
# Do not share job definitions with the job.branches attribute across multiple branches. Do not define jobs which are
|
||||
# specific to other branches, except for parent jobs which are shared across branches. For example, to not add a job
|
||||
# which is specific for the stable/1.0.0 branch to the .zuul.yaml in master branch. In particular do not use the
|
||||
# job.branches directive on a job which will be copied to multiple branches. When you have multiple copies of a job with
|
||||
# the job.branches attribute, Zuul CI could pick any of the job definitions which might not be the one you expected.
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-base
|
||||
parent: openstacksdk-functional-devstack
|
||||
# Do not restrict branches in base jobs because else Zuul would not find a matching
|
||||
# parent job variant during job freeze when child jobs are on other branches.
|
||||
post-run: ci/playbooks/postlog.yaml
|
||||
description: |
|
||||
Run openstack collections functional tests against a devstack
|
||||
# Do not set job.override-checkout or job.required-projects.override-checkout in base job because
|
||||
# else Zuul will use this branch when matching variants for parent jobs during job freeze
|
||||
required-projects:
|
||||
- openstack/ansible-collections-openstack
|
||||
- openstack/designate
|
||||
# openstack/devstack is required through parent job openstacksdk-functional-devstack
|
||||
# openstack/os-client-config is required through parent job openstacksdk-functional-devstack
|
||||
# openstack/openstacksdk is required through parent job openstacksdk-functional-devstack
|
||||
irrelevant-files: &ignore_files
|
||||
- changelogs/.*
|
||||
- galaxy.*
|
||||
- COPYING
|
||||
- docs/.*
|
||||
- .*\.md
|
||||
- .*\.rst
|
||||
- tools/run-ansible-sanity.sh
|
||||
- tests/sanity/.*
|
||||
- .zuul.yaml
|
||||
vars:
|
||||
zuul_work_dir: src/opendev.org/openstack/ansible-collections-openstack
|
||||
tox_envlist: ansible_latest
|
||||
tox_install_siblings: true
|
||||
fetch_subunit: false
|
||||
devstack_plugins:
|
||||
designate: https://opendev.org/openstack/designate
|
||||
devstack_services:
|
||||
designate: true
|
||||
neutron-dns: true
|
||||
neutron-trunk: true
|
||||
zuul_copy_output:
|
||||
'{{ devstack_log_dir }}/test_output.log': 'logs'
|
||||
extensions_to_txt:
|
||||
log: true
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack
|
||||
parent: openstacksdk-functional-devstack
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
branches: master
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using master of openstacksdk with latest ansible release
|
||||
required-projects:
|
||||
- openstack/ansible-collections-openstack
|
||||
vars:
|
||||
zuul_work_dir: src/opendev.org/openstack/ansible-collections-openstack
|
||||
tox_envlist: ansible
|
||||
tox_install_siblings: true
|
||||
fetch_subunit: false
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-releases
|
||||
parent: ansible-collections-openstack-functional-devstack
|
||||
name: ansible-collections-openstack-functional-devstack-magnum-base
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
# Do not restrict branches in base jobs because else Zuul would not find a matching
|
||||
# parent job variant during job freeze when child jobs are on other branches.
|
||||
description: |
|
||||
Run openstack collections functional tests against a devstack with Magnum plugin enabled
|
||||
# Do not set job.override-checkout or job.required-projects.override-checkout in base job because
|
||||
# else Zuul will use this branch when matching variants for parent jobs during job freeze
|
||||
required-projects:
|
||||
- openstack/magnum
|
||||
- openstack/python-magnumclient
|
||||
files:
|
||||
- ^ci/roles/coe_cluster/.*$
|
||||
- ^plugins/modules/coe_cluster.py
|
||||
- ^plugins/modules/coe_cluster_template.py
|
||||
timeout: 10800
|
||||
vars:
|
||||
devstack_localrc:
|
||||
# NOTE: extend default glance limit from 1GB
|
||||
GLANCE_LIMIT_IMAGE_SIZE_TOTAL: 5000
|
||||
devstack_plugins:
|
||||
magnum: https://opendev.org/openstack/magnum
|
||||
devstack_services:
|
||||
magnum-api: true
|
||||
magnum-cond: true
|
||||
# Disable swift and dependent c-bak service to support upload of .qcow2.xz image in the gate
|
||||
s-account: false
|
||||
s-container: false
|
||||
s-object: false
|
||||
s-proxy: false
|
||||
c-bak: false
|
||||
tox_extra_args: -vv --skip-missing-interpreters=false -- coe_cluster coe_cluster_template
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-manila-base
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
# Do not restrict branches in base jobs because else Zuul would not find a matching
|
||||
# parent job variant during job freeze when child jobs are on other branches.
|
||||
description: |
|
||||
Run openstack collections functional tests against a devstack with Manila plugin enabled
|
||||
# Do not set job.override-checkout or job.required-projects.override-checkout in base job because
|
||||
# else Zuul will use this branch when matching variants for parent jobs during job freeze
|
||||
required-projects:
|
||||
- openstack/manila
|
||||
- openstack/python-manilaclient
|
||||
files:
|
||||
- ^ci/roles/share_type/.*$
|
||||
- ^plugins/modules/share_type.py
|
||||
- ^plugins/modules/share_type_info.py
|
||||
timeout: 10800
|
||||
vars:
|
||||
devstack_localrc:
|
||||
MANILA_ENABLED_BACKENDS: generic
|
||||
MANILA_OPTGROUP_generic_driver_handles_share_servers: true
|
||||
MANILA_OPTGROUP_generic_connect_share_server_to_tenant_network: true
|
||||
MANILA_USE_SERVICE_INSTANCE_PASSWORD: true
|
||||
devstack_plugins:
|
||||
manila: https://opendev.org/openstack/manila
|
||||
devstack_services:
|
||||
manila: true
|
||||
m-api: true
|
||||
m-sch: true
|
||||
m-shr: true
|
||||
m-dat: true
|
||||
tox_extra_args: -vv --skip-missing-interpreters=false -- share_type share_type_info
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-magnum
|
||||
parent: ansible-collections-openstack-functional-devstack-magnum-base
|
||||
branches: master
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using releases of openstacksdk and latest ansible release
|
||||
with Magnum plugin enabled, using master of openstacksdk and latest
|
||||
ansible release. Run it only on coe_cluster{,_template} changes.
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-manila
|
||||
parent: ansible-collections-openstack-functional-devstack-manila-base
|
||||
branches: master
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
with Manila plugin enabled, using master of openstacksdk and latest
|
||||
ansible release. Run it only on share_type{,_info} changes.
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-octavia-base
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
# Do not restrict branches in base jobs because else Zuul would not find a matching
|
||||
# parent job variant during job freeze when child jobs are on other branches.
|
||||
description: |
|
||||
Run openstack collections functional tests against a devstack with Octavia plugin enabled
|
||||
# Do not set job.override-checkout or job.required-projects.override-checkout in base job because
|
||||
# else Zuul will use this branch when matching variants for parent jobs during job freeze
|
||||
required-projects:
|
||||
- openstack/octavia
|
||||
files:
|
||||
- ^ci/roles/loadbalancer/.*$
|
||||
- ^plugins/modules/lb_health_monitor.py
|
||||
- ^plugins/modules/lb_listener.py
|
||||
- ^plugins/modules/lb_member.py
|
||||
- ^plugins/modules/lb_pool.py
|
||||
- ^plugins/modules/loadbalancer.py
|
||||
vars:
|
||||
configure_swap_size: 4096
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$OCTAVIA_CONF:
|
||||
controller_worker:
|
||||
amphora_driver: amphora_noop_driver
|
||||
devstack_plugins:
|
||||
designate: https://opendev.org/openstack/designate
|
||||
octavia: https://opendev.org/openstack/octavia
|
||||
devstack_services:
|
||||
designate: true
|
||||
octavia: true
|
||||
o-api: true
|
||||
o-cw: true
|
||||
o-hm: true
|
||||
o-hk: true
|
||||
neutron-dns: true
|
||||
tox_extra_args: -vv --skip-missing-interpreters=false -- loadbalancer
|
||||
tox_install_siblings: false
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-octavia
|
||||
parent: ansible-collections-openstack-functional-devstack-octavia-base
|
||||
branches: master
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
with Octavia plugin enabled, using latest releases of openstacksdk
|
||||
and latest ansible release. Run it only on Load Balancer changes.
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-releases
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
branches: master
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using latest releases of openstacksdk and latest ansible release
|
||||
vars:
|
||||
tox_constraints_file: '{{ ansible_user_dir }}/{{ zuul.project.src_dir }}/tests/constraints-openstacksdk-1.x.x.txt'
|
||||
tox_install_siblings: false
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-2.18
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
branches: master
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using master of openstacksdk and stable 2.16 branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.18
|
||||
vars:
|
||||
tox_envlist: ansible_2_18
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
parent: ansible-collections-openstack-functional-devstack
|
||||
parent: ansible-collections-openstack-functional-devstack-base
|
||||
nodeset: openstack-single-node-jammy
|
||||
branches: master
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using master of openstacksdk and devel branch of ansible
|
||||
@@ -35,205 +232,137 @@
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: devel
|
||||
|
||||
# Linters
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-2.9
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
name: openstack-tox-linters-ansible
|
||||
parent: openstack-tox-linters
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using master of openstacksdk and stable 2.9 branch of ansible
|
||||
voting: true
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.9
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-train-ansible-devel
|
||||
parent: ansible-collections-openstack-functional-devstack
|
||||
description: |
|
||||
Run openstack collections functional tests against a train devstack
|
||||
using train brach of openstacksdk and devel branch of ansible
|
||||
# non-voting because we can't prevent ansible devel from breaking us
|
||||
voting: false
|
||||
Run openstack collections linter tests using the devel branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: devel
|
||||
- name: openstack/openstacksdk
|
||||
override-branch: train
|
||||
- name: openstack/devstack
|
||||
override-checkout: train
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-train-ansible-2.9
|
||||
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.9 branch of ansible
|
||||
voting: true
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.9
|
||||
- name: openstack/openstacksdk
|
||||
override-branch: train
|
||||
- name: openstack/devstack
|
||||
override-checkout: train
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-stein-ansible-devel
|
||||
parent: ansible-collections-openstack-functional-devstack
|
||||
description: |
|
||||
Run openstack collections functional tests against a stein devstack
|
||||
using stein brach of openstacksdk and devel branch of ansible
|
||||
# non-voting because we can't prevent ansible devel from breaking us
|
||||
voting: false
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: devel
|
||||
- name: openstack/openstacksdk
|
||||
override-branch: stein
|
||||
- name: openstack/devstack
|
||||
override-checkout: stein
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-stein-ansible-2.9
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
description: |
|
||||
Run openstack collections functional tests against a stein devstack
|
||||
using stein brach of openstacksdk and stable 2.9 branch of ansible
|
||||
voting: true
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.9
|
||||
- name: openstack/openstacksdk
|
||||
override-branch: stein
|
||||
- name: openstack/devstack
|
||||
override-checkout: stein
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-rocky-ansible-devel
|
||||
parent: ansible-collections-openstack-functional-devstack
|
||||
description: |
|
||||
Run openstack collections functional tests against a rocky devstack
|
||||
using rocky brach of openstacksdk and devel branch of ansible
|
||||
# non-voting because we can't prevent ansible devel from breaking us
|
||||
voting: false
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: devel
|
||||
- name: openstack/openstacksdk
|
||||
override-branch: rocky
|
||||
- name: openstack/devstack
|
||||
override-checkout: rocky
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-rocky-ansible-2.9
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
description: |
|
||||
Run openstack collections functional tests against a rocky devstack
|
||||
using rocky brach of openstacksdk and stable 2.9 branch of ansible
|
||||
voting: true
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.9
|
||||
- name: openstack/openstacksdk
|
||||
override-branch: rocky
|
||||
- name: openstack/devstack
|
||||
override-checkout: rocky
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-queens-ansible-2.9
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
description: |
|
||||
Run openstack collections functional tests against a queens devstack
|
||||
using master brach of openstacksdk and stable 2.9 branch of ansible
|
||||
voting: true
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.9
|
||||
- name: openstack/openstacksdk
|
||||
override-branch: master
|
||||
- name: openstack/devstack
|
||||
override-checkout: queens
|
||||
vars:
|
||||
# override tox_constraints_file from parent job
|
||||
tox_constraints_file: '{{ ansible_user_dir }}/{{ zuul.project.src_dir }}/tests/constraints-none.txt'
|
||||
tox_envlist: linters_latest
|
||||
tox_install_siblings: true
|
||||
|
||||
- job:
|
||||
name: openstack-tox-linters-ansible-devel
|
||||
parent: openstack-tox-linters
|
||||
parent: openstack-tox-linters-ansible
|
||||
nodeset: ubuntu-jammy
|
||||
description: |
|
||||
Run openstack collections linter tests using the devel branch of ansible
|
||||
# non-voting because we can't prevent ansible devel from breaking us
|
||||
voting: false
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: devel
|
||||
vars:
|
||||
python_version: '3.10'
|
||||
bindep_profile: test py310
|
||||
|
||||
- job:
|
||||
name: openstack-tox-linters-ansible-2.9
|
||||
parent: openstack-tox-linters
|
||||
name: openstack-tox-linters-ansible-2.18
|
||||
parent: openstack-tox-linters-ansible
|
||||
description: |
|
||||
Run openstack collections linter tests using the 2.9 branch of ansible
|
||||
voting: true
|
||||
Run openstack collections linter tests using the 2.18 branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.9
|
||||
override-checkout: stable-2.18
|
||||
vars:
|
||||
tox_envlist: linters_2_18
|
||||
python_version: "3.12"
|
||||
bindep_profile: test py312
|
||||
|
||||
# Cross-checks with other projects
|
||||
- job:
|
||||
name: bifrost-collections-src
|
||||
parent: bifrost-integration-tinyipa-ubuntu-jammy
|
||||
required-projects:
|
||||
- openstack/ansible-collections-openstack
|
||||
- # always use master branch when collecting parent job variants, refer to git blame for rationale.
|
||||
name: openstack/bifrost
|
||||
override-checkout: master
|
||||
- # always use master branch when collecting parent job variants
|
||||
name: openstack/openstacksdk
|
||||
override-checkout: master
|
||||
- job:
|
||||
name: bifrost-keystone-collections-src
|
||||
parent: bifrost-integration-tinyipa-keystone-ubuntu-jammy
|
||||
required-projects:
|
||||
- openstack/ansible-collections-openstack
|
||||
- # always use master branch when collecting parent job variants, refer to git blame for rationale.
|
||||
name: openstack/bifrost
|
||||
override-checkout: master
|
||||
- # always use master branch when collecting parent job variants
|
||||
name: openstack/openstacksdk
|
||||
override-checkout: master
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-release
|
||||
parent: openstack-tox-linters-ansible
|
||||
run: ci/publish/publish_collection.yml
|
||||
secrets:
|
||||
- ansible_galaxy_info
|
||||
|
||||
- secret:
|
||||
name: ansible_galaxy_info
|
||||
data:
|
||||
url: https://galaxy.ansible.com
|
||||
token: !encrypted/pkcs1-oaep
|
||||
- QJ3c5LfmM4YmqwwLKv4wK5lroWDLGeMyPkmHXhvf0ry3vGjKZvZxVpbIhFXJHXevHov/r
|
||||
nvlqwmG8D5msynQKZDFg2ZwSMIQWRKfSbsSLe7A6NWI2wC+QtZSPiRiBcBcHY1QbNNW21
|
||||
84cssYa1oHOA0WXpomBz1qXuPV48aKLjMnWysgFhNSx3Oog+ZOSCczyyVVuXP1lIWIO26
|
||||
AtRTrEcr37K3JY9usE2PCbZKFOq/+IDPz9fbS7PtBOv7iXOHOf3AfBiJiaJe3q/ecoaaq
|
||||
ejk2WTKWfvq/3rY4pU1976kUcxgcd+jj9ReFyw8edCsc1ecL0qmZFbdHmC03jEcVo4p8I
|
||||
WJQ0D5wk4/u2Fu9texNuBvb62Yu3Y028Zhm5rz8Zl/ISsdaA3losn5S7C7iAH/yKlGQEI
|
||||
N/1X4M0tVPaMtsIhZyyz+JMbeNyVR9ZarqbtpzRtVhjxL7KOiAQbEzAmZcBbCJ2Z5iI+P
|
||||
bTp03f9Y/tZNtkohARvx1TKhv8CvsmyGkMm+r5Y8aWz3SNy8LL6bSwtGun/ifbnadHmw/
|
||||
TD5/UUXHHjBGkeAu9HTtwUZ5Qdkfg92PnPgruAAuOkF1Y4RyRS9qvwhtqyHO8TwU0INRY
|
||||
5MHEzeOQWemoQb/qdENp+J/Q9oMEbpFYv9TkrWkxVoKop6Str8e3FF5sxmN/SE=
|
||||
|
||||
- project:
|
||||
check:
|
||||
jobs:
|
||||
- tox-pep8
|
||||
- openstack-tox-linters-ansible-devel
|
||||
- openstack-tox-linters-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack:
|
||||
dependencies: &deps_unit_lint
|
||||
- tox-pep8
|
||||
- openstack-tox-linters-ansible-2.9
|
||||
irrelevant-files: &ignore_files
|
||||
- changelogs/.*
|
||||
- COPYING
|
||||
- docs/.*
|
||||
- README.md
|
||||
- tools/run-ansible-sanity.sh
|
||||
- tests/sanity/.*
|
||||
- openstack-tox-linters-ansible-2.18
|
||||
- ansible-collections-openstack-functional-devstack
|
||||
- ansible-collections-openstack-functional-devstack-releases
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.18
|
||||
- ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
- ansible-collections-openstack-functional-devstack-magnum
|
||||
- ansible-collections-openstack-functional-devstack-manila
|
||||
- ansible-collections-openstack-functional-devstack-octavia
|
||||
|
||||
- ansible-collections-openstack-functional-devstack-releases:
|
||||
dependencies: *deps_unit_lint
|
||||
- bifrost-collections-src:
|
||||
voting: false
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-ansible-devel:
|
||||
dependencies: *deps_unit_lint
|
||||
- bifrost-keystone-collections-src:
|
||||
voting: false
|
||||
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-train-ansible-devel:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-train-ansible-2.9:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-stein-ansible-devel:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-stein-ansible-2.9:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-rocky-ansible-devel:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-rocky-ansible-2.9:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
- ansible-collections-openstack-functional-devstack-queens-ansible-2.9:
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
|
||||
|
||||
gate:
|
||||
jobs:
|
||||
- tox-pep8
|
||||
- openstack-tox-linters
|
||||
- openstack-tox-linters-ansible-2.18
|
||||
- ansible-collections-openstack-functional-devstack-releases
|
||||
- ansible-collections-openstack-functional-devstack-magnum
|
||||
- ansible-collections-openstack-functional-devstack-manila
|
||||
- ansible-collections-openstack-functional-devstack-octavia
|
||||
|
||||
periodic:
|
||||
jobs:
|
||||
- openstack-tox-linters-ansible-devel
|
||||
- openstack-tox-linters-ansible-2.18
|
||||
- ansible-collections-openstack-functional-devstack
|
||||
- ansible-collections-openstack-functional-devstack-releases
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack-train-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack-stein-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack-rocky-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack-queens-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.18
|
||||
- ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
- bifrost-collections-src
|
||||
- bifrost-keystone-collections-src
|
||||
- ansible-collections-openstack-functional-devstack-magnum
|
||||
- ansible-collections-openstack-functional-devstack-manila
|
||||
- ansible-collections-openstack-functional-devstack-octavia
|
||||
|
||||
tag:
|
||||
jobs:
|
||||
- ansible-collections-openstack-release
|
||||
|
||||
740
CHANGELOG.rst
Normal file
740
CHANGELOG.rst
Normal file
@@ -0,0 +1,740 @@
|
||||
==========================================
|
||||
Ansible OpenStack Collection Release Notes
|
||||
==========================================
|
||||
|
||||
.. contents:: Topics
|
||||
|
||||
v2.5.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfixes and minor changes
|
||||
|
||||
Major Changes
|
||||
-------------
|
||||
|
||||
- Add import_method to module
|
||||
- Add object_containers_info module
|
||||
- Add support for filters in inventory
|
||||
- Add volume_manage module
|
||||
- Introduce share_type modules
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Allow role_assignment module to work cross domain
|
||||
- Don't compare current state for `reboot_*` actions
|
||||
- Fix disable_gateway_ip for subnet
|
||||
- Fix disable_gateway_ip for subnet
|
||||
- Fix example in the dns_zone_info module doc
|
||||
- Fix router module external IPs when only subnet specified
|
||||
- Fix the bug reporting url
|
||||
- Let clouds_yaml_path behave as documented (Override path to clouds.yaml file)
|
||||
- Shows missing data in `stack_info` module output
|
||||
|
||||
v2.4.1
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfixes and minor changes
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Update tags when changing server
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Fix missed client_cert in OpenStackModule
|
||||
|
||||
v2.4.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
New trait module and minor changes
|
||||
|
||||
Major Changes
|
||||
-------------
|
||||
|
||||
- Add trait module
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add loadbalancer quota options
|
||||
- Allow create instance with tags
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.trait - Add or Delete a trait from OpenStack
|
||||
|
||||
v2.3.3
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfixes and minor changes
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add test to only_ipv4 in inventory
|
||||
- add an option to use only IPv4 only for ansible_host and ansible_ssh_host
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- CI - Fix deprecated ANSIBLE_COLLECTIONS_PATHS variable
|
||||
|
||||
v2.3.2
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfixes and minor changes
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Drop compat implementations for tests
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Fix openstack.cloud.port module failure in check mode
|
||||
|
||||
v2.3.1
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Client TLS certificate support
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add ability to pass client tls certificate
|
||||
|
||||
v2.3.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfixes and new modules
|
||||
|
||||
Major Changes
|
||||
-------------
|
||||
|
||||
- Add Neutron trunk module
|
||||
- Add application_credential module
|
||||
- Add module to filter available volume services
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add inactive state for the images
|
||||
- Add insecure_registry property to coe_cluster_templates
|
||||
- Add support for creation of the default external networks
|
||||
- Add target_all_project option
|
||||
- Add vlan_tranparency for creation networks
|
||||
- Allow munch results in server_info module
|
||||
- Allow to specify multiple allocation pools when creating a subnet
|
||||
- CI - Disable auto-discovery for setuptools
|
||||
- CI - Don't create port with binding profile
|
||||
- CI - Fix CI in collection
|
||||
- CI - Fix linters-devel and devstack tests
|
||||
- CI - Fix regression in quota module
|
||||
- CI - Fix test for server shelve
|
||||
- CI - Migrate Bifrost jobs to Ubuntu Jammy
|
||||
- CI - Remove 2.9 jobs from Zuul config
|
||||
- CI - Run functional testing regardless of pep8/linter results
|
||||
- Enable glance-direct interop image import
|
||||
- Ensure coe_cluster_template compare labels properly
|
||||
- Wait for deleted server to disappear from results
|
||||
- router - Allow specifying external network name in a different project
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Allow wait false when auto_ip is false
|
||||
- Fix exception when creating object from file
|
||||
- Fix exception when updating container with metadata
|
||||
- Fix typo in openstack.cloud.lb_pool
|
||||
- Fix typo in parameter description
|
||||
- fix subnet module - allow cidr option with subnet_pool
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.application_credential - Manage OpenStack Identity (Keystone) application credentials
|
||||
- openstack.cloud.trunk - Add or delete trunks from an OpenStack cloud
|
||||
- openstack.cloud.volume_service_info - Fetch OpenStack Volume (Cinder) services
|
||||
|
||||
v2.2.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
New module for volume_type and bugfixes
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add volume_encryption_type modules
|
||||
- Add volume_type modules
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Fix image module filter
|
||||
- Fix port module idempotency
|
||||
- Fix router module idempotency
|
||||
|
||||
v2.1.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
New module for Ironic and bugfixes
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add baremetal_deploy_template module
|
||||
- Highlight our mode of operation more prominently
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Change security group rules only when instructed to do so
|
||||
- Fix for AttributeError: 'dict' object has no attribute 'status'
|
||||
- Fix issue with multiple records in recordset
|
||||
- Fix mistake in compute_flavor_access notes
|
||||
- Fixed private option in inventory plugin
|
||||
- Respect description option and delete security group rules first
|
||||
- Use true and false instead of yes and no for boolean values
|
||||
|
||||
v2.0.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Our new major release 2.0.0 of the Ansible collection for OpenStack clouds aka ``openstack.cloud`` is a complete overhaul of the code base and brings full compatibility with openstacksdk 1.0.0.
|
||||
|
||||
Highlights of this release are
|
||||
* three new modules which for example provide a generic and uniform API for interacting with OpenStack cloud resources,
|
||||
* a complete refactoring of all existing modules bringing dozens of bugfixes, new features as well as consistent
|
||||
and properly documented module results and options,
|
||||
* 100% compatibility with openstacksdk's first major release 1.0.0,
|
||||
* new guides for contributors from devstack setup over coding guidelines to our release process and
|
||||
* massively increased CI coverage with many new integration tests, now covering all modules and plugins.
|
||||
|
||||
Note, this ``2.0.0`` release *breaks backward compatibility* with previous ``1.x.x`` releases!
|
||||
* ``2.x.x`` releases of this collection are compatible with openstacksdk ``1.x.x`` and later *only*,
|
||||
* ``1.x.x`` releases of this collection are compatible with openstacksdk ``0.x.x`` prior to ``0.99.0`` *only*,
|
||||
* ``2.x.x`` releases of are not backward compatible with ``1.x.x`` releases,
|
||||
* ``1.x.x`` release series will be in maintenance mode now and receive bugfixes only.
|
||||
|
||||
However, this collection as well as openstacksdk continue to be backward compatible with clouds running on older OpenStack releases. For example, it is fine and a fully supported use case to use this 2.0.0 release with clouds based on OpenStack Train, Wallaby or Zed. Feel encouraged to always use the latest releases of this collection and openstacksdk regardless of which version of OpenStack is installed in your cloud.
|
||||
|
||||
This collection is compatible with and tested with Ansible 2.9 and later. However, support for old ``os_*`` short module names such as ``os_server`` have been dropped with this release. You have to call modules using their FQCN (Fully-Qualified Collection Name) such as ``openstack.cloud.server`` instead.
|
||||
|
||||
Many thanks to all contributors who made this release possible. Tens of thousands LOCs have been reviewed and changed and fixed and tested throughout last year. You rock!
|
||||
|
||||
Major Changes
|
||||
-------------
|
||||
|
||||
- Many modules gained support for Ansible's check mode or have been fixed to properly implement a no change policy during check mode runs.
|
||||
- Many modules gained support for updates. In the past, those modules allowed to create and delete OpenStack cloud resources but would ignore when module options had been changed.
|
||||
- Many modules such as ``openstack.cloud.server``, ``openstack.cloud.baremetal_node`` and all load-balancer related modules now properly implement the ``wait`` option. For example, when ``wait`` is set to ``true`` then modules will not return until resources have reached its ``active`` or ``deleted`` state.
|
||||
- Module ``openstack.cloud.resource`` has been added. It provides an generic and uniform interface to create, update and delete any OpenStack cloud resource which openstacksdk supports. This module unlocks a huge amount of functionality from OpenStack clouds to Ansible users which has been inaccessible with existing modules so far.
|
||||
- Module ``openstack.cloud.resources`` has been added. It provides an generic and uniform interface to list any type of OpenStack cloud resources which openstacksdk supports. This module fetch any OpenStack cloud resource without having to implement a new Ansible ``*_info`` module for this type of resource first.
|
||||
- Module ``openstack.cloud.subnet_pool`` has been added. It allows to create and delete subnet pools in OpenStack clouds.
|
||||
- Module examples have been improved and updated for most modules.
|
||||
- Module results have been properly documented for all modules.
|
||||
- Options in all modules have been renamed to match openstacksdk's attribute names (if applicable). The previous option names have been added as aliases to keep module options backward compatible.
|
||||
- Our CI integration tests have been massively expanded. Our test coverage spans across all modules and plugins now, including tests for our inventory plugin and our new ``openstack.cloud.resource`` and ``openstack.cloud.resources`` modules.
|
||||
- Our contributors documentation has been heavily extended. In directory ``docs`` you will find the rationale for our branching strategy, a developer's guide on how to contribute to the collection, a tutorial to set up a DevStack environment for hacking on and testing the collection, a step-by-step guide for publishing new releases and a list of questions to ask when doing reviews or submitting patches for review.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Added generic module options ``sdk_log_path`` and ``sdk_log_level`` which allow to track openstacksdk activity.
|
||||
- Many more options were added to modules but we stopped counting at one point...
|
||||
- Module ``openstack.cloud.coe_cluster`` gained support for option ``is_floating_ip_enabled``.
|
||||
- Module ``openstack.cloud.lb_listener`` gained options ``default_tls_container_ref`` and ``sni_container_refs`` which allow to specify TLS certificates when using the ``TERMINATED_HTTPS`` protocol.
|
||||
- Module ``openstack.cloud.network`` gained support for updates, i.e. existing networks will be properly updated now when module options such as ``mtu`` or ``admin_state_up`` have been changed.
|
||||
- Module ``openstack.cloud.port`` gained an ``description`` option.
|
||||
- Module ``openstack.cloud.role_assignment`` gained an ``system`` option.
|
||||
- Module ``openstack.cloud.security_group_rule`` gained an ``description`` option.
|
||||
- Module ``openstack.cloud.server_action`` gained an option ``all_projects`` which allows to execute actions on servers outside of the current auth-scoped project (if the user has permission to do so).
|
||||
- Module ``openstack.cloud.server_info`` gained an ``description`` option.
|
||||
- Module ``openstack.cloud.server`` gained an ``description`` option.
|
||||
- Module ``openstack.cloud.server`` gained support for updates. For example, options such as ``description`` and floating ip addresses can be updated now.
|
||||
- Module ``openstack.cloud.subnet`` gained an ``subnet_pool`` option.
|
||||
|
||||
Breaking Changes / Porting Guide
|
||||
--------------------------------
|
||||
|
||||
- 2.x.x releases of this collection are not backward compatible with 1.x.x releases. Backward compatibility is guaranteed within each release series only. Module options have been kept backward compatible across both release series, apart from a few exceptions noted below. However, module results have changed for most modules due to deep changes in openstacksdk. For easier porting and usage, we streamlined return values across modules and documented return values of all modules.
|
||||
- Default value for option ``security_groups`` in ``openstack.cloud.server`` has been changed from ``['default']`` to ``[]`` because the latter is the default in python-openstackclient and the former behavior causes issues with existing servers.
|
||||
- Dropped symbolic links with prefix ``os_`` and plugin routing for deprecated ``os_*`` module names. This means users have to call modules of the Ansible OpenStack collection using their FQCN (Fully Qualified Collection Name) such as ``openstack.cloud.server``. Short module names such as ``os_server`` will now raise an Ansible error.
|
||||
- Module ``openstack.cloud.project_access`` has been split into two separate modules ``openstack.cloud.compute_flavor_access`` and ``openstack.cloud.volume_type_access``.
|
||||
- Option ``availability_zone`` has been removed from the list of generic options available in all modules. Instead it has been inserted into the ``openstack.cloud.server`` and ``openstack.cloud.volume`` modules because it is relevant to those two modules only.
|
||||
- Option ``name`` of module ``openstack.cloud.port`` is required now because it is used to find, update and delete ports and idempotency would break otherwise.
|
||||
- Option ``policies`` has been replaced with option ``policy`` in module ``openstack.cloud.server_group``. The former is ancient and was superceded by ``policy`` a long time ago.
|
||||
- Release series 2.x.x of this collection is compatible with openstacksdk 1.0.0 and later only. For compatibility with openstacksdk < 0.99.0 use release series 1.x.x of this collection. Ansible will raise an error when modules and plugins in this collection are used with an incompatible release of openstacksdk.
|
||||
- Special value ``auto`` for option ``id`` in module ``openstack.cloud.compute_flavor`` has been deprecated to be consistent with our other modules and openstacksdk's behaviour.
|
||||
|
||||
Deprecated Features
|
||||
-------------------
|
||||
|
||||
- Option ``is_public`` in module ``openstack.cloud.image`` has been deprecated and replaced with option ``visibility``.
|
||||
- Option ``volume`` in module ``openstack.cloud.image`` has been deprecated and it should be replaced with module ``openstack.cloud.volume`` in user code.
|
||||
|
||||
Removed Features (previously deprecated)
|
||||
----------------------------------------
|
||||
|
||||
- Dropped deprecated ``skip_update_of_driver_password`` option from module ``openstack.cloud.baremetal_node``.
|
||||
- Dropped unmaintained, obsolete and broken inventory script ``scripts/inventory/openstack_inventory.py``. It had been replaced with a proper Ansible inventory plugin ``openstack.cloud.openstack`` during the 1.x.x life cycle.
|
||||
- Module ``openstack.cloud.object`` no longer allows to create and delete containers, its sole purpose is managing an object in a container now. Use module ``openstack.cloud.object_container`` to managing Swift containers instead.
|
||||
- Option ``listeners`` has been removed from module ``openstack.cloud.loadbalancer`` because it duplicates a subset of the functionality (and code) provided by our ``openstack.cloud.lb_{listener,member,pool}`` modules.
|
||||
- Our outdated, undocumented, untested and bloated code templates in ``contrib`` directory which could be used to generate and develop new Ansible modules for this collection have been removed.
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Ansible check mode has been fixed in module ``openstack.cloud.compute_flavor``, it will no longer apply changes when check mode is enabled.
|
||||
- Creating load-balancers with module ``openstack.cloud.loadbalancer`` properly handles situations where several provider networks exist. A floating ip address specified in option ``floating_ip_address`` will be allocated from Neutron external network specified in option ``floating_ip_network``.
|
||||
- Default values for options ``shared``, ``admin_state_up`` and ``external`` in module ``openstack.cloud.network`` have been dropped because they cause failures for clouds which do not have those optional extensions installed.
|
||||
- Dropped default values for options ``min_disk`` and ``min_ram`` in module ``openstack.cloud.image`` because it interferes with its update mechanism and Glance uses those values anyway. Fixed handling of options ``name``, ``id``, ``visibility`` and ``is_public``.
|
||||
- Module ``openstack.cloud.baremetal_node_info`` will now properly return machine details when iterating over all available baremetal nodes.
|
||||
- Module ``openstack.cloud.host_aggregate`` now correctly handles ``hosts`` not being set or being set to ``None``.
|
||||
- Module ``openstack.cloud.identity_user`` will no longer fail when no password is supplied since Keystone allows to create a user without an password.
|
||||
- Module ``openstack.cloud.keypair`` no longer removes trailing spaces when reading a public key because this broke idempotency when using openstackclient and this module at the same time.
|
||||
- Module ``openstack.cloud.quota`` no longer sends invalid attributes such as ``project_id`` to OpenStack API when updating Nova, Neutron and Cinder quotas.
|
||||
- Module ``openstack.cloud.server`` will no longer change security groups to ``['default']`` on existing servers when option ``security_groups`` has not been specified.
|
||||
- Module ``openstack.cloud.subnet`` now properly handles updates, thus idempotency has been fixed and restored.
|
||||
- Modules ``openstack.cloud.security_group`` and ``openstack.cloud.security_group_rule`` gained support for specifying string ``any`` as a valid protocol in security group rules.
|
||||
- Option ``interfaces`` in module ``openstack.cloud.router`` no longer requires option ``network`` to be set, it is ``external_fixed_ips`` what requires ``network``.
|
||||
- Option ``is_public`` in module ``openstack.cloud.image`` will now be handled as a boolean instead of a string to be compatible to Glance API and fix issues when interacting with Glance service.
|
||||
- Option ``network`` in module ``openstack.cloud.router`` is now propery marked as required by options ``enable_snat`` and ``external_fixed_ips``.
|
||||
- Option ``owner`` in module ``openstack.cloud.image`` is now respected when searching for and creating images.
|
||||
- Our OpenStack inventory plugin now properly supports Ansible's cache feature.
|
||||
|
||||
v1.7.1
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfixes
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- lb_member - Add monitor_[address,port] parameter
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- openstack_inventory - Fix documentation
|
||||
- quota - Fix description of volumes_types parameter
|
||||
|
||||
v1.7.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
New modules for Ironic and bugfixes
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- openstack_inventory - Adds use_name variable
|
||||
- port - Add dns_[name,domain] to the port module
|
||||
- project - Remove project properties tests and support
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- identity_user_info - Fix identity user lookup with a domain
|
||||
- keystone_domain - Move identity domain to use proxy layer
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.baremetal_node_info - Retrieve information about Bare Metal nodes from OpenStack an object.
|
||||
- openstack.cloud.baremetal_port - Create, Update, Remove ironic ports from OpenStack
|
||||
- openstack.cloud.baremetal_port_info - Retrieve information about Bare Metal ports from OpenStack an object.
|
||||
|
||||
v1.6.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
New modules for RBAC and Nova services
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- quota - Adds metadata_items parameter
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.compute_service_info - Retrieve information about one or more OpenStack compute services
|
||||
- openstack.cloud.neutron_rbac_policies_info - Fetch Neutron policies.
|
||||
- openstack.cloud.neutron_rbac_policy - Create or delete a Neutron policy to apply a RBAC rule against an object.
|
||||
|
||||
v1.5.3
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfixes
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Don't require allowed_address_pairs for port
|
||||
- server_volume - check specified server is found
|
||||
|
||||
v1.5.2
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfixes
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add documentation links to README.md
|
||||
- Don't run functional jobs on galaxy.yml change
|
||||
- Move CI to use Ansible 2.12 version as main
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Add client and member listener timeouts for persistence (Ex. SSH)
|
||||
- Added missing warn() used in cloud.openstack.quota
|
||||
- Fix issue with same host and group names
|
||||
- Flavor properties are not deleted on changes and id will stay
|
||||
|
||||
v1.5.1
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfixes for networking modules
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Changed minversion in tox to 3.18.0
|
||||
- Update IRC server in README
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Add mandatory requires_ansible version to metadata
|
||||
- Add protocol listener octavia
|
||||
- Add support check mode for all info modules
|
||||
- Allow to attach multiple floating ips to a server
|
||||
- Only add or remove router interfaces when needed
|
||||
- Wait for pool to be active and online
|
||||
|
||||
v1.5.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
New modules for DNS and FIPs and bugfixes.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add bindep.txt for ansible-builder
|
||||
- Add check_mode attribute to OpenstackModule
|
||||
- Migrating image module from AnsibleModule to OpenStackModule
|
||||
- Switch KeystoneFederationProtocolInfo module to OpenStackModule
|
||||
- Switch ProjectAccess module to OpenStackModule
|
||||
- Switch Quota module to OpenStackModule
|
||||
- Switch Recordset module to OpenStackModule
|
||||
- Switch ServerGroup module to OpenStackModule
|
||||
- Switch ServerMetadata module to OpenStackModule
|
||||
- Switch Snapshot module to OpenStackModule
|
||||
- Switch Stack module to OpenStackModule
|
||||
- Switch auth module to OpenStackModule
|
||||
- Switch catalog_service module to OpenStackModule
|
||||
- Switch coe_cluster module to OpenStackModule
|
||||
- Switch coe_cluster_template module to OpenStackModule
|
||||
- Switch endpoint module to OpenStackModule
|
||||
- Switch federation_idp module to OpenStackModule
|
||||
- Switch federation_idp_info module to OpenStackModule
|
||||
- Switch federation_mapping module to OpenStackModule
|
||||
- Switch federation_mapping_info module to OpenStackModule
|
||||
- Switch federation_protocol module to OpenStackModule
|
||||
- Switch flavor module to OpenStackModule
|
||||
- Switch flavor_info module to OpenStackModule
|
||||
- Switch floating_ip module to OpenStackModule
|
||||
- Switch group_assignment module to OpenStackModule
|
||||
- Switch hostaggregate module to OpenStackModule
|
||||
- Switch identity_domain module to OpenStackModule
|
||||
- Switch identity_domain_info module to OpenStackModule
|
||||
- Switch identity_group module to OpenStackModule
|
||||
- Switch identity_group_info module to OpenStackModule
|
||||
- Switch identity_role module to OpenStackModule
|
||||
- Switch identity_user module to OpenStackModule
|
||||
- Switch lb_listener module to OpenStackModule
|
||||
- Switch lb_member module to OpenStackModule
|
||||
- Switch lb_pool module to OpenStackModule
|
||||
- Switch object module to OpenStackModule
|
||||
- Switch port module to OpenStackModule
|
||||
- Switch port_info module to OpenStackModule
|
||||
- Switch project and project_info module to OpenStackModule
|
||||
- Switch role_assignment module to OpenStackModule
|
||||
- Switch user_info module to OpenStackModule
|
||||
- image - Add support to setting image tags
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Update checks for validate_certs in openstack_cloud_from_module
|
||||
- compute_flavor - Fix the idempotent of compute_flavor module
|
||||
- host_aggregate - Fix host_aggregate to tolerate aggregate.hosts being None
|
||||
- inventory/openstack - Fix inventory plugin on Ansible 2.11
|
||||
- port - fix update on empty list of allowed address pairs
|
||||
- setup.cfg Replace dashes with underscores
|
||||
- subnet - Only apply necessary changes to subnets
|
||||
- volume - Fail if referenced source image for a new volume does not exist
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.address_scope - Create or delete address scopes from OpenStack
|
||||
- openstack.cloud.dns_zone_info - Getting information about dns zones
|
||||
- openstack.cloud.floating_ip_info - Get information about floating ips
|
||||
|
||||
v1.4.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
New object_container module and bugfixes.
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Add Octavia job for testing Load Balancer
|
||||
- Add binding profile to port module
|
||||
- Add execution environment metadata
|
||||
- Fix CI for latest ansible-test with no_log
|
||||
- Fix issues with newest ansible-test 2.11
|
||||
- Prepare for Ansible 2.11 tests
|
||||
- add option to exclude legacy groups
|
||||
- security_group_rule add support ipv6-icmp
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.object_container - Manage Swift container
|
||||
|
||||
v1.3.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
New modules and bugfixes.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Fix some typos in readme
|
||||
- Guidelines Fix links and formatting
|
||||
- baremetal_node - Add support for new features
|
||||
- baremetal_node - ironic deprecate sub-options of driver_info
|
||||
- baremetal_node - ironic stop putting meaningless values to properties
|
||||
- image_info - Migrating image_info module from AnsibleModule to OpenStackModule
|
||||
- recordset - Update recordset docu
|
||||
- server - Allow description field to be set with os_server
|
||||
- server_action - Added shelve and unshelve as new server actions
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- port - Fixed check for None in os_port
|
||||
- project - Fix setting custom property on os_project
|
||||
- security_group_rule - Remove protocols choice in security rules
|
||||
- volume_info - Fix volume_info result for SDK < 0.19
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.identity_role_info - Retrieve information about Openstack Identity roles.
|
||||
- openstack.cloud.keypair_info - Retrieve information about Openstack key pairs.
|
||||
- openstack.cloud.security_group_info - Retrieve information about Openstack Security Groups.
|
||||
- openstack.cloud.security_group_rule_info - Retrieve information about Openstack Security Group rules.
|
||||
- openstack.cloud.stack_info - Retrieve information about Openstack Heat stacks.
|
||||
|
||||
v1.2.1
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Porting modules to new OpenstackModule class and fixes.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- dns_zone - Migrating dns_zone from AnsibleModule to OpenStackModule
|
||||
- dns_zone, recordset - Enable update for recordset and add tests for dns and recordset module
|
||||
- endpoint - Do not fail when endpoint state is absent
|
||||
- ironic - Refactor ironic authentication into a new module_utils module
|
||||
- loadbalancer - Refactor loadbalancer module
|
||||
- network - Migrating network from AnsibleModule to OpenStackModule
|
||||
- networks_info - Migrating networks_info from AnsibleModule to OpenStackModule
|
||||
- openstack - Add galaxy.yml to support install from git
|
||||
- openstack - Fix docs-args mismatch in modules
|
||||
- openstack - OpenStackModule Support defining a minimum version of the SDK
|
||||
- router - Migrating routers from AnsibleModule to OpenStackModule
|
||||
- routers_info - Added deprecated_names for router_info module
|
||||
- routers_info - Migrating routers_info from AnsibleModule to OpenStackModule
|
||||
- security_group.py - Migrating security_group from AnsibleModule to OpenStackModule
|
||||
- security_group_rule - Refactor TCP/UDP port check
|
||||
- server.py - Improve "server" module with OpenstackModule class
|
||||
- server_volume - Migrating server_volume from AnsibleModule to OpenStackModule
|
||||
- subnet - Fix subnets update and idempotency
|
||||
- subnet - Migrating subnet module from AnsibleModule to OpenStackModule
|
||||
- subnets_info - Migrating subnets_info from AnsibleModule to OpenStackModule
|
||||
- volume.py - Migrating volume from AnsibleModule to OpenStackModule
|
||||
- volume_info - Fix volume_info arguments for SDK 0.19
|
||||
|
||||
v1.2.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
New volume backup modules.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- lb_health_monitor - Make it possible to create a health monitor to a pool
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.volume_backup module - Add/Delete Openstack volumes backup.
|
||||
- openstack.cloud.volume_backup_info module - Retrieve information about Openstack volume backups.
|
||||
- openstack.cloud.volume_snapshot_info module - Retrieve information about Openstack volume snapshots.
|
||||
|
||||
v1.1.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Starting redesign modules and bugfixes.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- A basic module subclass was introduced and a few modules moved to inherit from it.
|
||||
- Add more useful information from exception
|
||||
- Added pip installation option for collection.
|
||||
- Added template for generation of artibtrary module.
|
||||
- baremetal modules - Do not require ironic_url if cloud or auth.endpoint is provided
|
||||
- inventory_openstack - Add openstack logger and Ansible display utility
|
||||
- loadbalancer - Add support for setting the Flavor when creating a load balancer
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Fix non existing attribuites in SDK exception
|
||||
- security_group_rule - Don't pass tenant_id for remote group
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.volume_info - Retrieve information about Openstack volumes.
|
||||
|
||||
v1.0.1
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfix for server_info
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- server_info - Fix broken server_info module and add tests
|
||||
|
||||
v1.0.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Initial release of collection.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Renaming all modules and removing "os" prefix from names.
|
||||
- baremetal_node_action - Support json type for the ironic_node config_drive parameter
|
||||
- config - Update os_client_config to use openstacksdk
|
||||
- host_aggregate - Add support for not 'purging' missing hosts
|
||||
- project - Add properties for os_project
|
||||
- server_action - pass imageRef to rebuild
|
||||
- subnet - Updated allocation pool checks
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- baremetal_node - Correct parameter name
|
||||
- coe_cluster - Retrive id/uuid correctly
|
||||
- federation_mapping - Fixup some minor nits found in followup reviews
|
||||
- inventory_openstack - Fix constructed compose
|
||||
- network - Bump minimum openstacksdk version when using os_network/dns_domain
|
||||
- role_assignment - Fix os_user_role for groups in multidomain context
|
||||
- role_assignment - Fix os_user_role issue to grant a role in a domain
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.federation_idp - Add support for Keystone Identity Providers
|
||||
- openstack.cloud.federation_idp_info - Add support for fetching the information about federation IDPs
|
||||
- openstack.cloud.federation_mapping - Add support for Keystone mappings
|
||||
- openstack.cloud.federation_mapping_info - Add support for fetching the information about Keystone mappings
|
||||
- openstack.cloud.keystone_federation_protocol - Add support for Keystone federation Protocols
|
||||
- openstack.cloud.keystone_federation_protocol_info - Add support for getting information about Keystone federation Protocols
|
||||
- openstack.cloud.routers_info - Retrieve information about one or more OpenStack routers.
|
||||
@@ -1,40 +0,0 @@
|
||||
.. _contributing:
|
||||
|
||||
=============================================
|
||||
Contributing to ansible-collections-openstack
|
||||
=============================================
|
||||
|
||||
If you're interested in contributing to the ansible-collections-openstack project,
|
||||
the following will help get you started.
|
||||
|
||||
Developer Workflow
|
||||
------------------
|
||||
|
||||
OpenStack uses OpenDev for it's development, and patches are submitted to
|
||||
`OpenDev Gerrit`_. Please read `DeveloperWorkflow`_ before sending your
|
||||
first patch for review.
|
||||
|
||||
Pull requests submitted through GitHub will be ignored.
|
||||
|
||||
.. seealso::
|
||||
|
||||
* https://wiki.openstack.org/wiki/How_To_Contribute
|
||||
* https://wiki.openstack.org/wiki/CLA
|
||||
|
||||
.. _OpenDev Gerrit: https://review.opendev.org/
|
||||
.. _DeveloperWorkflow: https://docs.openstack.org/infra/manual/developers.html#development-workflow
|
||||
|
||||
Project Hosting Details
|
||||
-----------------------
|
||||
|
||||
Bug tracker
|
||||
https://storyboard.openstack.org/#!/project/openstack/ansible-collections-openstack
|
||||
|
||||
Mailing list (prefix subjects with ``[ansible]`` for faster responses)
|
||||
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-discuss
|
||||
|
||||
Code Hosting
|
||||
https://opendev.org/openstack/ansible-collections-openstack
|
||||
|
||||
Code Review
|
||||
https://review.opendev.org/#/q/status:open+project:openstack/ansible-collections-openstack,n,z
|
||||
216
README.md
216
README.md
@@ -1,37 +1,84 @@
|
||||
[](http://zuul.opendev.org/t/openstack/builds?project=openstack%2Fansible-collections-openstack#)
|
||||
[](
|
||||
http://zuul.opendev.org/t/openstack/builds?project=openstack%2Fansible-collections-openstack)
|
||||
|
||||
# Ansible Collection: openstack.cloud
|
||||
# Ansible OpenStack Collection
|
||||
|
||||
Ansible OpenStack collection aka `openstack.cloud` provides Ansible modules and Ansible plugins for managing OpenStack
|
||||
clouds. It is supported and maintained by the OpenStack community.
|
||||
|
||||
This repo hosts the `openstack.cloud` Ansible Collection.
|
||||
**NOTE:** We need and value your contributions! Maintaining this collection is a community effort. We are all both users
|
||||
and developers of this collection at the same time. If you find a bug, please report it. If you have fixed a bug, please
|
||||
submit a patch. If you need new functionality which is not covered by this collection yet, please extend an existing
|
||||
module or submit a new one. Our [Contributing](#contributing) section below has tons of docs to check out. Please get in
|
||||
touch!
|
||||
|
||||
The collection includes the Openstack modules and plugins supported by Openstack community to help the management of Openstack infrastructure.
|
||||
## Branches and Non Backward Compatibility ⚠️
|
||||
|
||||
## Installation and Usage
|
||||
Our codebase has been split into two separate release series, `2.x.x` and `1.x.x`:
|
||||
|
||||
### Installing the Collection from Ansible Galaxy
|
||||
* `2.x.x` releases of Ansible OpenStack collection are compatible with [OpenStack SDK][openstacksdk] `1.x.x` and its
|
||||
release candidates `0.99.0` and later *only* (OpenStack Zed and later). Our `master` branch tracks our `2.x.x`
|
||||
releases.
|
||||
* `1.x.x` releases of Ansible OpenStack collection are compatible with [OpenStack SDK][openstacksdk] `0.x.x` prior to
|
||||
`0.99.0` *only* (OpenStack Yoga and earlier). Our `stable/1.0.0` branch tracks our `1.x.x` releases.
|
||||
* `2.x.x` releases of Ansible OpenStack collection are not backward compatible to `1.x.x` releases ⚠️
|
||||
|
||||
Before using the Openstack Cloud collection, you need to install the collection with the `ansible-galaxy` CLI:
|
||||
For rationale and details please read our [branching docs](docs/branching.md). Both branches will be developed in
|
||||
parallel for the time being. Patches from `master` will be backported to `stable/1.0.0` on a best effort basis but
|
||||
expect new features to be introduced in our `master` branch only. Contributions are welcome for both branches!
|
||||
|
||||
`ansible-galaxy collection install openstack.cloud`
|
||||
[openstacksdk]: https://opendev.org/openstack/openstacksdk
|
||||
|
||||
You can also include it in a `requirements.yml` file and install it via `ansible-galaxy collection install -r requirements.yml` using the format:
|
||||
## Installation
|
||||
|
||||
For using this collection, first you have to install both Python packages `ansible` and `openstacksdk` on your Ansible
|
||||
controller:
|
||||
|
||||
```sh
|
||||
pip install "ansible>=2.9" "openstacksdk>=1.0.0"
|
||||
```
|
||||
|
||||
[OpenStack SDK][openstacksdk] has to be available on the Ansible host running the OpenStack modules. Depending on the
|
||||
Ansible playbook and roles you use, this host is not necessarily the Ansible controller. Sometimes Ansible might invoke
|
||||
a non-standard Python interpreter on the target Ansible host. Using Python 3.6 is required for modules in this
|
||||
collection.
|
||||
|
||||
Always use the last stable version of [OpenStack SDK][openstacksdk] if possible, also when running against older
|
||||
OpenStack deployments. OpenStack SDK is backward compatible to older OpenStack deployments, so its safe to run last
|
||||
version of the SDK against older OpenStack clouds. The installed version of the OpenStack SDK does not have to match
|
||||
your OpenStack cloud, but it has to match the release series of this collection which you are using. For notes about
|
||||
our release series and branches please read the introduction above.
|
||||
|
||||
Before using this collection, you have to install it with `ansible-galaxy`:
|
||||
|
||||
```sh
|
||||
ansible-galaxy collection install openstack.cloud
|
||||
```
|
||||
|
||||
You can also include it in a `requirements.yml` file:
|
||||
|
||||
```yaml
|
||||
collections:
|
||||
- name: openstack.cloud
|
||||
```
|
||||
|
||||
### Playbooks
|
||||
And then install it with:
|
||||
|
||||
To use a module from Openstack Cloud collection, please reference the full namespace, collection name, and modules name that you want to use:
|
||||
```sh
|
||||
ansible-galaxy collection install -r requirements.yml
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
To use a module from the Ansible OpenStack collection, call them by their Fully Qualified Collection Name (FQCN),
|
||||
composed of their namespace, collection name and module name:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Using Openstack Cloud collection
|
||||
hosts: localhost
|
||||
- hosts: localhost
|
||||
tasks:
|
||||
- openstack.cloud.server:
|
||||
- name: Create server in an OpenStack cloud
|
||||
openstack.cloud.server:
|
||||
name: vm
|
||||
state: present
|
||||
cloud: openstack
|
||||
@@ -42,16 +89,16 @@ To use a module from Openstack Cloud collection, please reference the full names
|
||||
volume_size: 75
|
||||
```
|
||||
|
||||
Or you can add full namepsace and collecton name in the `collections` element:
|
||||
Or you can add the full namespace and collection name in the `collections` element:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Using Openstack Cloud collection
|
||||
hosts: localhost
|
||||
- hosts: localhost
|
||||
collections:
|
||||
- openstack.cloud
|
||||
tasks:
|
||||
- server_volume:
|
||||
- name: Create server in an OpenStack cloud
|
||||
server_volume:
|
||||
state: present
|
||||
cloud: openstack
|
||||
server: Mysql-server
|
||||
@@ -59,41 +106,126 @@ Or you can add full namepsace and collecton name in the `collections` element:
|
||||
device: /dev/vdb
|
||||
```
|
||||
|
||||
For powerful generic [CRUD][crud]-style resource management use Ansible module
|
||||
[`openstack.cloud.resource`](plugins/modules/resource.py):
|
||||
|
||||
```yaml
|
||||
---
|
||||
- hosts: localhost
|
||||
tasks:
|
||||
- name: Create security group
|
||||
openstack.cloud.resource:
|
||||
cloud: openstack
|
||||
service: network
|
||||
type: security_group
|
||||
attributes:
|
||||
name: ansible_security_group
|
||||
description: 'ansible security group'
|
||||
|
||||
- name: Update security group description
|
||||
openstack.cloud.resource:
|
||||
cloud: openstack
|
||||
service: network
|
||||
type: security_group
|
||||
attributes:
|
||||
name: ansible_security_group
|
||||
description: 'ansible neutron security group'
|
||||
|
||||
- name: Delete security group
|
||||
openstack.cloud.resource:
|
||||
cloud: openstack
|
||||
service: network
|
||||
type: security_group
|
||||
attributes:
|
||||
name: ansible_security_group
|
||||
state: absent
|
||||
```
|
||||
|
||||
For generic resource listing use Ansible module [`openstack.cloud.resources`](plugins/modules/resources.py):
|
||||
|
||||
```yaml
|
||||
---
|
||||
- hosts: localhost
|
||||
tasks:
|
||||
- name: List images
|
||||
openstack.cloud.resources:
|
||||
cloud: openstack
|
||||
service: image
|
||||
type: image
|
||||
|
||||
- name: List compute flavors
|
||||
openstack.cloud.resources:
|
||||
cloud: openstack
|
||||
service: compute
|
||||
type: flavor
|
||||
|
||||
- name: List networks with name 'public'
|
||||
openstack.cloud.resources:
|
||||
cloud: openstack
|
||||
service: network
|
||||
type: network
|
||||
parameters:
|
||||
name: public
|
||||
```
|
||||
|
||||
[Ansible module defaults][ansible-module-defaults] are supported as well:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- module_defaults:
|
||||
group/openstack.cloud.openstack:
|
||||
cloud: devstack-admin
|
||||
#
|
||||
#
|
||||
# Listing modules individually is required for
|
||||
# backward compatibility with Ansible 2.9 only
|
||||
openstack.cloud.compute_flavor_info:
|
||||
cloud: devstack-admin
|
||||
openstack.cloud.server_info:
|
||||
cloud: devstack-admin
|
||||
block:
|
||||
- name: List compute flavors
|
||||
openstack.cloud.compute_flavor_info:
|
||||
|
||||
- name: List servers
|
||||
openstack.cloud.server_info:
|
||||
```
|
||||
|
||||
[ansible-module-defaults]: https://docs.ansible.com/ansible/latest/user_guide/playbooks_module_defaults.html
|
||||
[crud]: https://en.wikipedia.org/wiki/CRUD
|
||||
|
||||
## Documentation
|
||||
|
||||
See collection docs at Ansible's main page:
|
||||
|
||||
* [openstack.cloud collection docs (version released in Ansible package)](
|
||||
https://docs.ansible.com/ansible/latest/collections/openstack/cloud/index.html)
|
||||
|
||||
* [openstack.cloud collection docs (devel version)](
|
||||
https://docs.ansible.com/ansible/devel/collections/openstack/cloud/index.html)
|
||||
|
||||
## Contributing
|
||||
|
||||
For information on contributing, please see [CONTRIBUTING](https://opendev.org/openstack/ansible-collections-openstack/src/branch/master/CONTRIBUTING.rst)
|
||||
Thank you for your interest in our Ansible OpenStack collection ☺️
|
||||
|
||||
There are many ways in which you can participate in the project, for example:
|
||||
|
||||
- Submit bugs and feature requests, and help us verify them
|
||||
- Submit and review source code changes in [Openstack Gerrit](https://review.opendev.org/#/q/project:openstack/ansible-collections-openstack)
|
||||
- Add new modules for Openstack Cloud
|
||||
- [Report and verify bugs and help with solving issues](
|
||||
https://bugs.launchpad.net/ansible-collections-openstack).
|
||||
- [Submit and review patches](
|
||||
https://review.opendev.org/#/q/project:openstack/ansible-collections-openstack).
|
||||
- Follow OpenStack's [How To Contribute](https://wiki.openstack.org/wiki/How_To_Contribute) guide.
|
||||
|
||||
We work with [OpenDev Gerrit](https://review.opendev.org/), pull requests submitted through GitHub will be ignored.
|
||||
|
||||
## Testing and Development
|
||||
|
||||
If you want to develop new content for this collection or improve what is already here, the easiest way to work on the collection is to clone it into one of the configured [`COLLECTIONS_PATHS`](https://docs.ansible.com/ansible/latest/reference_appendices/config.html#collections-paths), and work on it there.
|
||||
|
||||
### Testing with `ansible-test`
|
||||
|
||||
We use `ansible-test` for sanity:
|
||||
|
||||
```bash
|
||||
tox -e linters
|
||||
```
|
||||
|
||||
## More Information
|
||||
|
||||
TBD
|
||||
Please read our [Contributions and Development Guide](docs/contributing.md) (⚠️) and our [Review Guide](
|
||||
docs/reviewing.md) (⚠️) before sending your first patch. Pull requests submitted through GitHub will be ignored.
|
||||
|
||||
## Communication
|
||||
|
||||
We have a dedicated Interest Group for Openstack Ansible modules.
|
||||
You can find other people interested in this in `#openstack-ansible-sig` on Freenode IRC.
|
||||
We have a Special Interest Group for the Ansible OpenStack collection. Join us in `#openstack-ansible-sig` on
|
||||
[OFTC IRC](https://www.oftc.net/) 🍪
|
||||
|
||||
## License
|
||||
|
||||
GNU General Public License v3.0 or later
|
||||
|
||||
See [LICENCE](https://opendev.org/openstack/ansible-collections-openstack/src/branch/master/COPYING) to see the full text.
|
||||
See [LICENCE](COPYING) to see the full text.
|
||||
|
||||
7
bindep.txt
Normal file
7
bindep.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
# This is a cross-platform list tracking distribution packages needed by tests;
|
||||
# see https://docs.openstack.org/infra/bindep/ for additional information.
|
||||
|
||||
gcc [compile platform:centos-8 platform:rhel-8]
|
||||
python38-cryptography [platform:centos-8 platform:rhel-8]
|
||||
python38-devel [compile platform:centos-8 platform:rhel-8]
|
||||
python38-requests [platform:centos-8 platform:rhel-8]
|
||||
638
changelogs/changelog.yaml
Normal file
638
changelogs/changelog.yaml
Normal file
@@ -0,0 +1,638 @@
|
||||
ancestor: null
|
||||
releases:
|
||||
1.0.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- baremetal_node - Correct parameter name
|
||||
- coe_cluster - Retrive id/uuid correctly
|
||||
- federation_mapping - Fixup some minor nits found in followup reviews
|
||||
- inventory_openstack - Fix constructed compose
|
||||
- network - Bump minimum openstacksdk version when using os_network/dns_domain
|
||||
- role_assignment - Fix os_user_role for groups in multidomain context
|
||||
- role_assignment - Fix os_user_role issue to grant a role in a domain
|
||||
minor_changes:
|
||||
- Renaming all modules and removing "os" prefix from names.
|
||||
- baremetal_node_action - Support json type for the ironic_node config_drive
|
||||
parameter
|
||||
- config - Update os_client_config to use openstacksdk
|
||||
- host_aggregate - Add support for not 'purging' missing hosts
|
||||
- project - Add properties for os_project
|
||||
- server_action - pass imageRef to rebuild
|
||||
- subnet - Updated allocation pool checks
|
||||
release_summary: Initial release of collection.
|
||||
modules:
|
||||
- description: Add support for Keystone Identity Providers
|
||||
name: federation_idp
|
||||
namespace: ''
|
||||
- description: Add support for fetching the information about federation IDPs
|
||||
name: federation_idp_info
|
||||
namespace: ''
|
||||
- description: Add support for Keystone mappings
|
||||
name: federation_mapping
|
||||
namespace: ''
|
||||
- description: Add support for fetching the information about Keystone mappings
|
||||
name: federation_mapping_info
|
||||
namespace: ''
|
||||
- description: Add support for Keystone federation Protocols
|
||||
name: keystone_federation_protocol
|
||||
namespace: ''
|
||||
- description: Add support for getting information about Keystone federation Protocols
|
||||
name: keystone_federation_protocol_info
|
||||
namespace: ''
|
||||
- description: Retrieve information about one or more OpenStack routers.
|
||||
name: routers_info
|
||||
namespace: ''
|
||||
release_date: '2020-05-19'
|
||||
1.0.1:
|
||||
changes:
|
||||
bugfixes:
|
||||
- server_info - Fix broken server_info module and add tests
|
||||
release_summary: Bugfix for server_info
|
||||
release_date: '2020-05-22'
|
||||
1.1.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Fix non existing attribuites in SDK exception
|
||||
- security_group_rule - Don't pass tenant_id for remote group
|
||||
minor_changes:
|
||||
- A basic module subclass was introduced and a few modules moved to inherit
|
||||
from it.
|
||||
- Add more useful information from exception
|
||||
- Added pip installation option for collection.
|
||||
- Added template for generation of artibtrary module.
|
||||
- baremetal modules - Do not require ironic_url if cloud or auth.endpoint is
|
||||
provided
|
||||
- inventory_openstack - Add openstack logger and Ansible display utility
|
||||
- loadbalancer - Add support for setting the Flavor when creating a load balancer
|
||||
release_summary: Starting redesign modules and bugfixes.
|
||||
modules:
|
||||
- description: Retrieve information about Openstack volumes.
|
||||
name: volume_info
|
||||
namespace: ''
|
||||
release_date: '2020-08-17'
|
||||
1.2.0:
|
||||
changes:
|
||||
minor_changes:
|
||||
- lb_health_monitor - Make it possible to create a health monitor to a pool
|
||||
release_summary: New volume backup modules.
|
||||
modules:
|
||||
- description: Add/Delete Openstack volumes backup.
|
||||
name: volume_backup module
|
||||
namespace: ''
|
||||
- description: Retrieve information about Openstack volume backups.
|
||||
name: volume_backup_info module
|
||||
namespace: ''
|
||||
- description: Retrieve information about Openstack volume snapshots.
|
||||
name: volume_snapshot_info module
|
||||
namespace: ''
|
||||
release_date: '2020-10-13'
|
||||
1.2.1:
|
||||
changes:
|
||||
minor_changes:
|
||||
- dns_zone - Migrating dns_zone from AnsibleModule to OpenStackModule
|
||||
- dns_zone, recordset - Enable update for recordset and add tests for dns and
|
||||
recordset module
|
||||
- endpoint - Do not fail when endpoint state is absent
|
||||
- ironic - Refactor ironic authentication into a new module_utils module
|
||||
- loadbalancer - Refactor loadbalancer module
|
||||
- network - Migrating network from AnsibleModule to OpenStackModule
|
||||
- networks_info - Migrating networks_info from AnsibleModule to OpenStackModule
|
||||
- openstack - Add galaxy.yml to support install from git
|
||||
- openstack - Fix docs-args mismatch in modules
|
||||
- openstack - OpenStackModule Support defining a minimum version of the SDK
|
||||
- router - Migrating routers from AnsibleModule to OpenStackModule
|
||||
- routers_info - Added deprecated_names for router_info module
|
||||
- routers_info - Migrating routers_info from AnsibleModule to OpenStackModule
|
||||
- security_group.py - Migrating security_group from AnsibleModule to OpenStackModule
|
||||
- security_group_rule - Refactor TCP/UDP port check
|
||||
- server.py - Improve "server" module with OpenstackModule class
|
||||
- server_volume - Migrating server_volume from AnsibleModule to OpenStackModule
|
||||
- subnet - Fix subnets update and idempotency
|
||||
- subnet - Migrating subnet module from AnsibleModule to OpenStackModule
|
||||
- subnets_info - Migrating subnets_info from AnsibleModule to OpenStackModule
|
||||
- volume.py - Migrating volume from AnsibleModule to OpenStackModule
|
||||
- volume_info - Fix volume_info arguments for SDK 0.19
|
||||
release_summary: Porting modules to new OpenstackModule class and fixes.
|
||||
release_date: '2021-01-03'
|
||||
1.3.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- port - Fixed check for None in os_port
|
||||
- project - Fix setting custom property on os_project
|
||||
- security_group_rule - Remove protocols choice in security rules
|
||||
- volume_info - Fix volume_info result for SDK < 0.19
|
||||
minor_changes:
|
||||
- Fix some typos in readme
|
||||
- Guidelines Fix links and formatting
|
||||
- baremetal_node - Add support for new features
|
||||
- baremetal_node - ironic deprecate sub-options of driver_info
|
||||
- baremetal_node - ironic stop putting meaningless values to properties
|
||||
- image_info - Migrating image_info module from AnsibleModule to OpenStackModule
|
||||
- recordset - Update recordset docu
|
||||
- server - Allow description field to be set with os_server
|
||||
- server_action - Added shelve and unshelve as new server actions
|
||||
release_summary: New modules and bugfixes.
|
||||
modules:
|
||||
- description: Retrieve information about Openstack Identity roles.
|
||||
name: identity_role_info
|
||||
namespace: ''
|
||||
- description: Retrieve information about Openstack key pairs.
|
||||
name: keypair_info
|
||||
namespace: ''
|
||||
- description: Retrieve information about Openstack Security Groups.
|
||||
name: security_group_info
|
||||
namespace: ''
|
||||
- description: Retrieve information about Openstack Security Group rules.
|
||||
name: security_group_rule_info
|
||||
namespace: ''
|
||||
- description: Retrieve information about Openstack Heat stacks.
|
||||
name: stack_info
|
||||
namespace: ''
|
||||
release_date: '2021-02-16'
|
||||
1.4.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Add Octavia job for testing Load Balancer
|
||||
- Add binding profile to port module
|
||||
- Add execution environment metadata
|
||||
- Fix CI for latest ansible-test with no_log
|
||||
- Fix issues with newest ansible-test 2.11
|
||||
- Prepare for Ansible 2.11 tests
|
||||
- add option to exclude legacy groups
|
||||
- security_group_rule add support ipv6-icmp
|
||||
release_summary: New object_container module and bugfixes.
|
||||
modules:
|
||||
- description: Manage Swift container
|
||||
name: object_container
|
||||
namespace: ''
|
||||
release_date: '2021-04-08'
|
||||
1.5.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Update checks for validate_certs in openstack_cloud_from_module
|
||||
- compute_flavor - Fix the idempotent of compute_flavor module
|
||||
- host_aggregate - Fix host_aggregate to tolerate aggregate.hosts being None
|
||||
- inventory/openstack - Fix inventory plugin on Ansible 2.11
|
||||
- port - fix update on empty list of allowed address pairs
|
||||
- setup.cfg Replace dashes with underscores
|
||||
- subnet - Only apply necessary changes to subnets
|
||||
- volume - Fail if referenced source image for a new volume does not exist
|
||||
minor_changes:
|
||||
- Add bindep.txt for ansible-builder
|
||||
- Add check_mode attribute to OpenstackModule
|
||||
- Migrating image module from AnsibleModule to OpenStackModule
|
||||
- Switch KeystoneFederationProtocolInfo module to OpenStackModule
|
||||
- Switch ProjectAccess module to OpenStackModule
|
||||
- Switch Quota module to OpenStackModule
|
||||
- Switch Recordset module to OpenStackModule
|
||||
- Switch ServerGroup module to OpenStackModule
|
||||
- Switch ServerMetadata module to OpenStackModule
|
||||
- Switch Snapshot module to OpenStackModule
|
||||
- Switch Stack module to OpenStackModule
|
||||
- Switch auth module to OpenStackModule
|
||||
- Switch catalog_service module to OpenStackModule
|
||||
- Switch coe_cluster module to OpenStackModule
|
||||
- Switch coe_cluster_template module to OpenStackModule
|
||||
- Switch endpoint module to OpenStackModule
|
||||
- Switch federation_idp module to OpenStackModule
|
||||
- Switch federation_idp_info module to OpenStackModule
|
||||
- Switch federation_mapping module to OpenStackModule
|
||||
- Switch federation_mapping_info module to OpenStackModule
|
||||
- Switch federation_protocol module to OpenStackModule
|
||||
- Switch flavor module to OpenStackModule
|
||||
- Switch flavor_info module to OpenStackModule
|
||||
- Switch floating_ip module to OpenStackModule
|
||||
- Switch group_assignment module to OpenStackModule
|
||||
- Switch hostaggregate module to OpenStackModule
|
||||
- Switch identity_domain module to OpenStackModule
|
||||
- Switch identity_domain_info module to OpenStackModule
|
||||
- Switch identity_group module to OpenStackModule
|
||||
- Switch identity_group_info module to OpenStackModule
|
||||
- Switch identity_role module to OpenStackModule
|
||||
- Switch identity_user module to OpenStackModule
|
||||
- Switch lb_listener module to OpenStackModule
|
||||
- Switch lb_member module to OpenStackModule
|
||||
- Switch lb_pool module to OpenStackModule
|
||||
- Switch object module to OpenStackModule
|
||||
- Switch port module to OpenStackModule
|
||||
- Switch port_info module to OpenStackModule
|
||||
- Switch project and project_info module to OpenStackModule
|
||||
- Switch role_assignment module to OpenStackModule
|
||||
- Switch user_info module to OpenStackModule
|
||||
- image - Add support to setting image tags
|
||||
release_summary: New modules for DNS and FIPs and bugfixes.
|
||||
modules:
|
||||
- description: Create or delete address scopes from OpenStack
|
||||
name: address_scope
|
||||
namespace: ''
|
||||
- description: Getting information about dns zones
|
||||
name: dns_zone_info
|
||||
namespace: ''
|
||||
- description: Get information about floating ips
|
||||
name: floating_ip_info
|
||||
namespace: ''
|
||||
release_date: '2021-06-23'
|
||||
1.5.1:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Add mandatory requires_ansible version to metadata
|
||||
- Add protocol listener octavia
|
||||
- Add support check mode for all info modules
|
||||
- Allow to attach multiple floating ips to a server
|
||||
- Only add or remove router interfaces when needed
|
||||
- Wait for pool to be active and online
|
||||
minor_changes:
|
||||
- Changed minversion in tox to 3.18.0
|
||||
- Update IRC server in README
|
||||
release_summary: Bugfixes for networking modules
|
||||
release_date: '2021-09-02'
|
||||
1.5.2:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Add client and member listener timeouts for persistence (Ex. SSH)
|
||||
- Added missing warn() used in cloud.openstack.quota
|
||||
- Fix issue with same host and group names
|
||||
- Flavor properties are not deleted on changes and id will stay
|
||||
minor_changes:
|
||||
- Add documentation links to README.md
|
||||
- Don't run functional jobs on galaxy.yml change
|
||||
- Move CI to use Ansible 2.12 version as main
|
||||
release_summary: Bugfixes
|
||||
release_date: '2021-11-09'
|
||||
1.5.3:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Don't require allowed_address_pairs for port
|
||||
- server_volume - check specified server is found
|
||||
release_summary: Bugfixes
|
||||
release_date: '2021-11-11'
|
||||
1.6.0:
|
||||
changes:
|
||||
minor_changes:
|
||||
- quota - Adds metadata_items parameter
|
||||
release_summary: New modules for RBAC and Nova services
|
||||
modules:
|
||||
- description: Retrieve information about one or more OpenStack compute services
|
||||
name: compute_service_info
|
||||
namespace: ''
|
||||
- description: Fetch Neutron policies.
|
||||
name: neutron_rbac_policies_info
|
||||
namespace: ''
|
||||
- description: Create or delete a Neutron policy to apply a RBAC rule against
|
||||
an object.
|
||||
name: neutron_rbac_policy
|
||||
namespace: ''
|
||||
release_date: '2022-01-13'
|
||||
1.7.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- identity_user_info - Fix identity user lookup with a domain
|
||||
- keystone_domain - Move identity domain to use proxy layer
|
||||
minor_changes:
|
||||
- openstack_inventory - Adds use_name variable
|
||||
- port - Add dns_[name,domain] to the port module
|
||||
- project - Remove project properties tests and support
|
||||
release_summary: New modules for Ironic and bugfixes
|
||||
modules:
|
||||
- description: Retrieve information about Bare Metal nodes from OpenStack an object.
|
||||
name: baremetal_node_info
|
||||
namespace: ''
|
||||
- description: Create, Update, Remove ironic ports from OpenStack
|
||||
name: baremetal_port
|
||||
namespace: ''
|
||||
- description: Retrieve information about Bare Metal ports from OpenStack an object.
|
||||
name: baremetal_port_info
|
||||
namespace: ''
|
||||
release_date: '2022-02-15'
|
||||
1.7.1:
|
||||
changes:
|
||||
bugfixes:
|
||||
- openstack_inventory - Fix documentation
|
||||
- quota - Fix description of volumes_types parameter
|
||||
minor_changes:
|
||||
- lb_member - Add monitor_[address,port] parameter
|
||||
release_summary: Bugfixes
|
||||
release_date: '2022-03-08'
|
||||
2.0.0:
|
||||
changes:
|
||||
breaking_changes:
|
||||
- 2.x.x releases of this collection are not backward compatible with 1.x.x releases.
|
||||
Backward compatibility is guaranteed within each release series only. Module
|
||||
options have been kept backward compatible across both release series, apart
|
||||
from a few exceptions noted below. However, module results have changed for
|
||||
most modules due to deep changes in openstacksdk. For easier porting and usage,
|
||||
we streamlined return values across modules and documented return values of
|
||||
all modules.
|
||||
- Default value for option ``security_groups`` in ``openstack.cloud.server``
|
||||
has been changed from ``['default']`` to ``[]`` because the latter is the
|
||||
default in python-openstackclient and the former behavior causes issues with
|
||||
existing servers.
|
||||
- Dropped symbolic links with prefix ``os_`` and plugin routing for deprecated
|
||||
``os_*`` module names. This means users have to call modules of the Ansible
|
||||
OpenStack collection using their FQCN (Fully Qualified Collection Name) such
|
||||
as ``openstack.cloud.server``. Short module names such as ``os_server`` will
|
||||
now raise an Ansible error.
|
||||
- Module ``openstack.cloud.project_access`` has been split into two separate
|
||||
modules ``openstack.cloud.compute_flavor_access`` and ``openstack.cloud.volume_type_access``.
|
||||
- Option ``availability_zone`` has been removed from the list of generic options
|
||||
available in all modules. Instead it has been inserted into the ``openstack.cloud.server``
|
||||
and ``openstack.cloud.volume`` modules because it is relevant to those two
|
||||
modules only.
|
||||
- Option ``name`` of module ``openstack.cloud.port`` is required now because
|
||||
it is used to find, update and delete ports and idempotency would break otherwise.
|
||||
- Option ``policies`` has been replaced with option ``policy`` in module ``openstack.cloud.server_group``.
|
||||
The former is ancient and was superceded by ``policy`` a long time ago.
|
||||
- Release series 2.x.x of this collection is compatible with openstacksdk 1.0.0
|
||||
and later only. For compatibility with openstacksdk < 0.99.0 use release series
|
||||
1.x.x of this collection. Ansible will raise an error when modules and plugins
|
||||
in this collection are used with an incompatible release of openstacksdk.
|
||||
- Special value ``auto`` for option ``id`` in module ``openstack.cloud.compute_flavor``
|
||||
has been deprecated to be consistent with our other modules and openstacksdk's
|
||||
behaviour.
|
||||
bugfixes:
|
||||
- Ansible check mode has been fixed in module ``openstack.cloud.compute_flavor``,
|
||||
it will no longer apply changes when check mode is enabled.
|
||||
- Creating load-balancers with module ``openstack.cloud.loadbalancer`` properly
|
||||
handles situations where several provider networks exist. A floating ip address
|
||||
specified in option ``floating_ip_address`` will be allocated from Neutron
|
||||
external network specified in option ``floating_ip_network``.
|
||||
- Default values for options ``shared``, ``admin_state_up`` and ``external``
|
||||
in module ``openstack.cloud.network`` have been dropped because they cause
|
||||
failures for clouds which do not have those optional extensions installed.
|
||||
- Dropped default values for options ``min_disk`` and ``min_ram`` in module
|
||||
``openstack.cloud.image`` because it interferes with its update mechanism
|
||||
and Glance uses those values anyway. Fixed handling of options ``name``, ``id``,
|
||||
``visibility`` and ``is_public``.
|
||||
- Module ``openstack.cloud.baremetal_node_info`` will now properly return machine
|
||||
details when iterating over all available baremetal nodes.
|
||||
- Module ``openstack.cloud.host_aggregate`` now correctly handles ``hosts``
|
||||
not being set or being set to ``None``.
|
||||
- Module ``openstack.cloud.identity_user`` will no longer fail when no password
|
||||
is supplied since Keystone allows to create a user without an password.
|
||||
- Module ``openstack.cloud.keypair`` no longer removes trailing spaces when
|
||||
reading a public key because this broke idempotency when using openstackclient
|
||||
and this module at the same time.
|
||||
- Module ``openstack.cloud.quota`` no longer sends invalid attributes such as
|
||||
``project_id`` to OpenStack API when updating Nova, Neutron and Cinder quotas.
|
||||
- Module ``openstack.cloud.server`` will no longer change security groups to
|
||||
``['default']`` on existing servers when option ``security_groups`` has not
|
||||
been specified.
|
||||
- Module ``openstack.cloud.subnet`` now properly handles updates, thus idempotency
|
||||
has been fixed and restored.
|
||||
- Modules ``openstack.cloud.security_group`` and ``openstack.cloud.security_group_rule``
|
||||
gained support for specifying string ``any`` as a valid protocol in security
|
||||
group rules.
|
||||
- Option ``interfaces`` in module ``openstack.cloud.router`` no longer requires
|
||||
option ``network`` to be set, it is ``external_fixed_ips`` what requires ``network``.
|
||||
- Option ``is_public`` in module ``openstack.cloud.image`` will now be handled
|
||||
as a boolean instead of a string to be compatible to Glance API and fix issues
|
||||
when interacting with Glance service.
|
||||
- Option ``network`` in module ``openstack.cloud.router`` is now propery marked
|
||||
as required by options ``enable_snat`` and ``external_fixed_ips``.
|
||||
- Option ``owner`` in module ``openstack.cloud.image`` is now respected when
|
||||
searching for and creating images.
|
||||
- Our OpenStack inventory plugin now properly supports Ansible's cache feature.
|
||||
deprecated_features:
|
||||
- Option ``is_public`` in module ``openstack.cloud.image`` has been deprecated
|
||||
and replaced with option ``visibility``.
|
||||
- Option ``volume`` in module ``openstack.cloud.image`` has been deprecated
|
||||
and it should be replaced with module ``openstack.cloud.volume`` in user code.
|
||||
major_changes:
|
||||
- Many modules gained support for Ansible's check mode or have been fixed to
|
||||
properly implement a no change policy during check mode runs.
|
||||
- Many modules gained support for updates. In the past, those modules allowed
|
||||
to create and delete OpenStack cloud resources but would ignore when module
|
||||
options had been changed.
|
||||
- Many modules such as ``openstack.cloud.server``, ``openstack.cloud.baremetal_node``
|
||||
and all load-balancer related modules now properly implement the ``wait``
|
||||
option. For example, when ``wait`` is set to ``true`` then modules will not
|
||||
return until resources have reached its ``active`` or ``deleted`` state.
|
||||
- Module ``openstack.cloud.resource`` has been added. It provides an generic
|
||||
and uniform interface to create, update and delete any OpenStack cloud resource
|
||||
which openstacksdk supports. This module unlocks a huge amount of functionality
|
||||
from OpenStack clouds to Ansible users which has been inaccessible with existing
|
||||
modules so far.
|
||||
- Module ``openstack.cloud.resources`` has been added. It provides an generic
|
||||
and uniform interface to list any type of OpenStack cloud resources which
|
||||
openstacksdk supports. This module fetch any OpenStack cloud resource without
|
||||
having to implement a new Ansible ``*_info`` module for this type of resource
|
||||
first.
|
||||
- Module ``openstack.cloud.subnet_pool`` has been added. It allows to create
|
||||
and delete subnet pools in OpenStack clouds.
|
||||
- Module examples have been improved and updated for most modules.
|
||||
- Module results have been properly documented for all modules.
|
||||
- Options in all modules have been renamed to match openstacksdk's attribute
|
||||
names (if applicable). The previous option names have been added as aliases
|
||||
to keep module options backward compatible.
|
||||
- Our CI integration tests have been massively expanded. Our test coverage spans
|
||||
across all modules and plugins now, including tests for our inventory plugin
|
||||
and our new ``openstack.cloud.resource`` and ``openstack.cloud.resources``
|
||||
modules.
|
||||
- Our contributors documentation has been heavily extended. In directory ``docs``
|
||||
you will find the rationale for our branching strategy, a developer's guide
|
||||
on how to contribute to the collection, a tutorial to set up a DevStack environment
|
||||
for hacking on and testing the collection, a step-by-step guide for publishing
|
||||
new releases and a list of questions to ask when doing reviews or submitting
|
||||
patches for review.
|
||||
minor_changes:
|
||||
- Added generic module options ``sdk_log_path`` and ``sdk_log_level`` which
|
||||
allow to track openstacksdk activity.
|
||||
- Many more options were added to modules but we stopped counting at one point...
|
||||
- Module ``openstack.cloud.coe_cluster`` gained support for option ``is_floating_ip_enabled``.
|
||||
- Module ``openstack.cloud.lb_listener`` gained options ``default_tls_container_ref``
|
||||
and ``sni_container_refs`` which allow to specify TLS certificates when using
|
||||
the ``TERMINATED_HTTPS`` protocol.
|
||||
- Module ``openstack.cloud.network`` gained support for updates, i.e. existing
|
||||
networks will be properly updated now when module options such as ``mtu``
|
||||
or ``admin_state_up`` have been changed.
|
||||
- Module ``openstack.cloud.port`` gained an ``description`` option.
|
||||
- Module ``openstack.cloud.role_assignment`` gained an ``system`` option.
|
||||
- Module ``openstack.cloud.security_group_rule`` gained an ``description`` option.
|
||||
- Module ``openstack.cloud.server_action`` gained an option ``all_projects``
|
||||
which allows to execute actions on servers outside of the current auth-scoped
|
||||
project (if the user has permission to do so).
|
||||
- Module ``openstack.cloud.server_info`` gained an ``description`` option.
|
||||
- Module ``openstack.cloud.server`` gained an ``description`` option.
|
||||
- Module ``openstack.cloud.server`` gained support for updates. For example,
|
||||
options such as ``description`` and floating ip addresses can be updated now.
|
||||
- Module ``openstack.cloud.subnet`` gained an ``subnet_pool`` option.
|
||||
release_summary: "Our new major release 2.0.0 of the Ansible collection for
|
||||
OpenStack clouds aka ``openstack.cloud`` is a complete overhaul of the code
|
||||
base and brings full compatibility with openstacksdk 1.0.0.\n\nHighlights
|
||||
of this release are\n* three new modules which for example provide a generic
|
||||
and uniform API for interacting with OpenStack cloud resources,\n* a complete
|
||||
refactoring of all existing modules bringing dozens of bugfixes, new features
|
||||
as well as consistent\n and properly documented module results and options,\n*
|
||||
100% compatibility with openstacksdk's first major release 1.0.0,\n* new guides
|
||||
for contributors from devstack setup over coding guidelines to our release
|
||||
process and\n* massively increased CI coverage with many new integration tests,
|
||||
now covering all modules and plugins.\n\nNote, this ``2.0.0`` release *breaks
|
||||
backward compatibility* with previous ``1.x.x`` releases!\n* ``2.x.x`` releases
|
||||
of this collection are compatible with openstacksdk ``1.x.x`` and later *only*,\n*
|
||||
``1.x.x`` releases of this collection are compatible with openstacksdk ``0.x.x``
|
||||
prior to ``0.99.0`` *only*,\n* ``2.x.x`` releases of are not backward compatible
|
||||
with ``1.x.x`` releases,\n* ``1.x.x`` release series will be in maintenance
|
||||
mode now and receive bugfixes only.\n\nHowever, this collection as well as
|
||||
openstacksdk continue to be backward compatible with clouds running on older
|
||||
OpenStack releases. For example, it is fine and a fully supported use case
|
||||
to use this 2.0.0 release with clouds based on OpenStack Train, Wallaby or
|
||||
Zed. Feel encouraged to always use the latest releases of this collection
|
||||
and openstacksdk regardless of which version of OpenStack is installed in
|
||||
your cloud.\n\nThis collection is compatible with and tested with Ansible
|
||||
2.9 and later. However, support for old ``os_*`` short module names such as
|
||||
``os_server`` have been dropped with this release. You have to call modules
|
||||
using their FQCN (Fully-Qualified Collection Name) such as ``openstack.cloud.server``
|
||||
instead.\n\nMany thanks to all contributors who made this release possible.
|
||||
Tens of thousands LOCs have been reviewed and changed and fixed and tested
|
||||
throughout last year. You rock!"
|
||||
removed_features:
|
||||
- Dropped deprecated ``skip_update_of_driver_password`` option from module ``openstack.cloud.baremetal_node``.
|
||||
- Dropped unmaintained, obsolete and broken inventory script ``scripts/inventory/openstack_inventory.py``.
|
||||
It had been replaced with a proper Ansible inventory plugin ``openstack.cloud.openstack``
|
||||
during the 1.x.x life cycle.
|
||||
- Module ``openstack.cloud.object`` no longer allows to create and delete containers,
|
||||
its sole purpose is managing an object in a container now. Use module ``openstack.cloud.object_container``
|
||||
to managing Swift containers instead.
|
||||
- Option ``listeners`` has been removed from module ``openstack.cloud.loadbalancer``
|
||||
because it duplicates a subset of the functionality (and code) provided by
|
||||
our ``openstack.cloud.lb_{listener,member,pool}`` modules.
|
||||
- Our outdated, undocumented, untested and bloated code templates in ``contrib``
|
||||
directory which could be used to generate and develop new Ansible modules
|
||||
for this collection have been removed.
|
||||
release_date: '2023-01-31'
|
||||
2.1.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Change security group rules only when instructed to do so
|
||||
- 'Fix for AttributeError: ''dict'' object has no attribute ''status'''
|
||||
- Fix issue with multiple records in recordset
|
||||
- Fix mistake in compute_flavor_access notes
|
||||
- Fixed private option in inventory plugin
|
||||
- Respect description option and delete security group rules first
|
||||
- Use true and false instead of yes and no for boolean values
|
||||
minor_changes:
|
||||
- Add baremetal_deploy_template module
|
||||
- Highlight our mode of operation more prominently
|
||||
release_summary: New module for Ironic and bugfixes
|
||||
release_date: '2023-04-19'
|
||||
2.2.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Fix image module filter
|
||||
- Fix port module idempotency
|
||||
- Fix router module idempotency
|
||||
minor_changes:
|
||||
- Add volume_encryption_type modules
|
||||
- Add volume_type modules
|
||||
release_summary: New module for volume_type and bugfixes
|
||||
release_date: '2023-12-01'
|
||||
2.3.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Allow wait false when auto_ip is false
|
||||
- Fix exception when creating object from file
|
||||
- Fix exception when updating container with metadata
|
||||
- Fix typo in openstack.cloud.lb_pool
|
||||
- Fix typo in parameter description
|
||||
- fix subnet module - allow cidr option with subnet_pool
|
||||
major_changes:
|
||||
- Add Neutron trunk module
|
||||
- Add application_credential module
|
||||
- Add module to filter available volume services
|
||||
minor_changes:
|
||||
- Add inactive state for the images
|
||||
- Add insecure_registry property to coe_cluster_templates
|
||||
- Add support for creation of the default external networks
|
||||
- Add target_all_project option
|
||||
- Add vlan_tranparency for creation networks
|
||||
- Allow munch results in server_info module
|
||||
- Allow to specify multiple allocation pools when creating a subnet
|
||||
- CI - Disable auto-discovery for setuptools
|
||||
- CI - Don't create port with binding profile
|
||||
- CI - Fix CI in collection
|
||||
- CI - Fix linters-devel and devstack tests
|
||||
- CI - Fix regression in quota module
|
||||
- CI - Fix test for server shelve
|
||||
- CI - Migrate Bifrost jobs to Ubuntu Jammy
|
||||
- CI - Remove 2.9 jobs from Zuul config
|
||||
- CI - Run functional testing regardless of pep8/linter results
|
||||
- Enable glance-direct interop image import
|
||||
- Ensure coe_cluster_template compare labels properly
|
||||
- Wait for deleted server to disappear from results
|
||||
- router - Allow specifying external network name in a different project
|
||||
release_summary: Bugfixes and new modules
|
||||
modules:
|
||||
- description: Manage OpenStack Identity (Keystone) application credentials
|
||||
name: application_credential
|
||||
namespace: ''
|
||||
- description: Add or delete trunks from an OpenStack cloud
|
||||
name: trunk
|
||||
namespace: ''
|
||||
- description: Fetch OpenStack Volume (Cinder) services
|
||||
name: volume_service_info
|
||||
namespace: ''
|
||||
release_date: '2024-11-28'
|
||||
2.3.1:
|
||||
changes:
|
||||
minor_changes:
|
||||
- Add ability to pass client tls certificate
|
||||
release_summary: Client TLS certificate support
|
||||
release_date: '2024-12-18'
|
||||
2.3.2:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Fix openstack.cloud.port module failure in check mode
|
||||
minor_changes:
|
||||
- Drop compat implementations for tests
|
||||
release_summary: Bugfixes and minor changes
|
||||
release_date: '2024-12-20'
|
||||
2.3.3:
|
||||
changes:
|
||||
bugfixes:
|
||||
- CI - Fix deprecated ANSIBLE_COLLECTIONS_PATHS variable
|
||||
minor_changes:
|
||||
- Add test to only_ipv4 in inventory
|
||||
- add an option to use only IPv4 only for ansible_host and ansible_ssh_host
|
||||
release_summary: Bugfixes and minor changes
|
||||
release_date: '2024-12-22'
|
||||
2.4.0:
|
||||
changes:
|
||||
major_changes:
|
||||
- Add trait module
|
||||
minor_changes:
|
||||
- Add loadbalancer quota options
|
||||
- Allow create instance with tags
|
||||
release_summary: New trait module and minor changes
|
||||
modules:
|
||||
- description: Add or Delete a trait from OpenStack
|
||||
name: trait
|
||||
namespace: ''
|
||||
release_date: '2025-01-15'
|
||||
2.4.1:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Fix missed client_cert in OpenStackModule
|
||||
minor_changes:
|
||||
- Update tags when changing server
|
||||
release_summary: Bugfixes and minor changes
|
||||
release_date: '2024-01-20'
|
||||
2.5.0:
|
||||
changes:
|
||||
major_changes:
|
||||
- Add import_method to module
|
||||
- Add object_containers_info module
|
||||
- Add support for filters in inventory
|
||||
- Add volume_manage module
|
||||
- Introduce share_type modules
|
||||
minor_changes:
|
||||
- Allow role_assignment module to work cross domain
|
||||
- Don't compare current state for `reboot_*` actions
|
||||
- Fix disable_gateway_ip for subnet
|
||||
- Fix disable_gateway_ip for subnet
|
||||
- Fix example in the dns_zone_info module doc
|
||||
- Fix router module external IPs when only subnet specified
|
||||
- Fix the bug reporting url
|
||||
- Let clouds_yaml_path behave as documented (Override path to clouds.yaml file)
|
||||
- Shows missing data in `stack_info` module output
|
||||
release_summary: Bugfixes and minor changes
|
||||
release_date: '2025-10-24'
|
||||
31
changelogs/config.yaml
Normal file
31
changelogs/config.yaml
Normal file
@@ -0,0 +1,31 @@
|
||||
changelog_filename_template: ../CHANGELOG.rst
|
||||
changelog_filename_version_depth: 0
|
||||
changes_file: changelog.yaml
|
||||
changes_format: combined
|
||||
ignore_other_fragment_extensions: true
|
||||
keep_fragments: false
|
||||
mention_ancestor: true
|
||||
new_plugins_after_name: removed_features
|
||||
notes_dir: fragments
|
||||
prelude_name: release_summary
|
||||
prelude_title: Release Summary
|
||||
sections:
|
||||
- - major_changes
|
||||
- Major Changes
|
||||
- - minor_changes
|
||||
- Minor Changes
|
||||
- - breaking_changes
|
||||
- Breaking Changes / Porting Guide
|
||||
- - deprecated_features
|
||||
- Deprecated Features
|
||||
- - removed_features
|
||||
- Removed Features (previously deprecated)
|
||||
- - security_fixes
|
||||
- Security Fixes
|
||||
- - bugfixes
|
||||
- Bugfixes
|
||||
- - known_issues
|
||||
- Known Issues
|
||||
title: Ansible OpenStack Collection
|
||||
trivial_section_name: trivial
|
||||
use_fqcn: true
|
||||
@@ -1,3 +0,0 @@
|
||||
bugfixes:
|
||||
- Bump the minimum openstacksdk version to 0.18.0 when os_network
|
||||
uses the port_security_enabled or mtu arguments.
|
||||
@@ -1,3 +0,0 @@
|
||||
bugfixes:
|
||||
- Bump the minimum openstacksdk version to 0.29.0 when os_network
|
||||
uses the dns_domain argument.
|
||||
@@ -1,2 +0,0 @@
|
||||
bugfixes:
|
||||
- os_coe_cluster: Retrieve the correct id/uuid depending on whether it is a create/get request.
|
||||
@@ -1,2 +0,0 @@
|
||||
minor_changes:
|
||||
- Moved Openstack inventory script from Ansible community.general to openstack collection.
|
||||
8
ci/playbooks/postlog.yaml
Normal file
8
ci/playbooks/postlog.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
- hosts: all
|
||||
tasks:
|
||||
- zuul_return:
|
||||
data:
|
||||
zuul:
|
||||
artifacts:
|
||||
- name: Test log
|
||||
url: controller/logs/test_output_log.txt
|
||||
91
ci/publish/publish_collection.yml
Normal file
91
ci/publish/publish_collection.yml
Normal file
@@ -0,0 +1,91 @@
|
||||
---
|
||||
- hosts: all
|
||||
vars:
|
||||
collection_path: "{{ ansible_user_dir }}/{{ zuul.project.src_dir }}"
|
||||
build_collection_path: /tmp/collection_built/
|
||||
ansible_virtualenv_path: /tmp/ansible_venv
|
||||
ansible_galaxy_path: "{{ ansible_virtualenv_path }}/bin/ansible-galaxy"
|
||||
|
||||
tasks:
|
||||
|
||||
- name: Include role for pip
|
||||
include_role:
|
||||
name: ensure-pip
|
||||
|
||||
- name: Install Ansible in virtualenv
|
||||
pip:
|
||||
name: ansible-core<2.19
|
||||
virtualenv: "{{ ansible_virtualenv_path }}"
|
||||
virtualenv_command: "{{ ensure_pip_virtualenv_command }}"
|
||||
|
||||
- name: Detect ansible version
|
||||
command: "{{ ansible_virtualenv_path }}/bin/ansible --version"
|
||||
register: ansible_version
|
||||
|
||||
- name: Discover tag version
|
||||
set_fact:
|
||||
version_tag: "{{ zuul.tag|default('no_version', true) }}"
|
||||
|
||||
- name: Fail if no tag version found
|
||||
fail:
|
||||
msg: "No tag was found in Zuul vars!"
|
||||
when: version_tag == 'no_version'
|
||||
|
||||
- name: Create a directory for collection
|
||||
file:
|
||||
state: "{{ item }}"
|
||||
path: "{{ build_collection_path }}"
|
||||
loop:
|
||||
- absent
|
||||
- directory
|
||||
|
||||
- name: Set galaxy.yml for right version from tag
|
||||
lineinfile:
|
||||
path: '{{ collection_path }}/galaxy.yml'
|
||||
regexp: '^version:.*'
|
||||
line: 'version: {{ version_tag }}'
|
||||
|
||||
- name: Build collection
|
||||
command: "{{ ansible_galaxy_path }} collection build --output-path {{ build_collection_path }} --force"
|
||||
args:
|
||||
chdir: "{{ collection_path }}"
|
||||
|
||||
- name: Publish content to Ansible Galaxy
|
||||
block:
|
||||
- name: Create ansible.cfg configuration file tempfile
|
||||
tempfile:
|
||||
state: file
|
||||
suffix: .cfg
|
||||
register: _ansiblecfg_tmp
|
||||
|
||||
- name: Create ansible.cfg configuration file
|
||||
copy:
|
||||
dest: "{{ _ansiblecfg_tmp.path }}"
|
||||
mode: 0600
|
||||
content: |
|
||||
[galaxy]
|
||||
server_list = release_galaxy
|
||||
|
||||
[galaxy_server.release_galaxy]
|
||||
url = {{ ansible_galaxy_info.url }}
|
||||
token = {{ ansible_galaxy_info.token }}
|
||||
|
||||
- name: Get content of galaxy.yml
|
||||
slurp:
|
||||
src: "{{ collection_path }}/galaxy.yml"
|
||||
register: galaxy_vars
|
||||
|
||||
- name: Parse yaml into variable
|
||||
set_fact:
|
||||
galaxy_yaml: "{{ galaxy_vars['content'] | b64decode | from_yaml }}"
|
||||
|
||||
- name: Publish collection to Ansible Galaxy / Automation Hub
|
||||
environment:
|
||||
ANSIBLE_CONFIG: "{{ _ansiblecfg_tmp.path }}"
|
||||
shell: >-
|
||||
{{ ansible_galaxy_path }} collection publish -vvv
|
||||
{{ build_collection_path }}/{{ galaxy_yaml.namespace }}-{{ galaxy_yaml.name }}-{{ version_tag }}.tar.gz
|
||||
|
||||
always:
|
||||
- name: Shred ansible-galaxy credentials
|
||||
command: "shred {{ _ansiblecfg_tmp.path }}"
|
||||
8
ci/requirements.yml
Normal file
8
ci/requirements.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
collections:
|
||||
- ansible.posix
|
||||
- ansible.utils
|
||||
- name: community.general
|
||||
version: 4.8.8
|
||||
# 5.0.0 dropped compatibility with ansible 2.9 and ansible-base 2.10
|
||||
# Ref.: https://github.com/ansible-collections/community.general/commit/1a9b3214fdf1eaccba5cc9ee210cbc5b5070fe4b
|
||||
8
ci/roles/address_scope/defaults/main.yml
Normal file
8
ci/roles/address_scope/defaults/main.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
address_scope_name: "address_scope"
|
||||
expected_fields:
|
||||
- id
|
||||
- ip_version
|
||||
- is_shared
|
||||
- name
|
||||
- project_id
|
||||
- tenant_id
|
||||
46
ci/roles/address_scope/tasks/main.yml
Normal file
46
ci/roles/address_scope/tasks/main.yml
Normal file
@@ -0,0 +1,46 @@
|
||||
---
|
||||
- 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 returned values
|
||||
assert:
|
||||
that:
|
||||
- item in create_address_scope.address_scope
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- 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
|
||||
9
ci/roles/application_credential/defaults/main.yml
Normal file
9
ci/roles/application_credential/defaults/main.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
expected_fields:
|
||||
- description
|
||||
- expires_at
|
||||
- id
|
||||
- name
|
||||
- project_id
|
||||
- roles
|
||||
- secret
|
||||
- unrestricted
|
||||
61
ci/roles/application_credential/tasks/main.yml
Normal file
61
ci/roles/application_credential/tasks/main.yml
Normal file
@@ -0,0 +1,61 @@
|
||||
---
|
||||
|
||||
- name: Create application credentials
|
||||
openstack.cloud.application_credential:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_creds
|
||||
description: dummy description
|
||||
register: appcred
|
||||
|
||||
- name: Assert return values of application_credential module
|
||||
assert:
|
||||
that:
|
||||
- appcred is changed
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(appcred.application_credential.keys())|length == 0
|
||||
|
||||
- name: Create the application credential again
|
||||
openstack.cloud.application_credential:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_creds
|
||||
description: dummy description
|
||||
register: appcred
|
||||
|
||||
- name: Assert return values of ansible_credential module
|
||||
assert:
|
||||
that:
|
||||
# credentials are immutable so creating twice will cause delete and create
|
||||
- appcred is changed
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(appcred.application_credential.keys())|length == 0
|
||||
|
||||
- name: Update the application credential again
|
||||
openstack.cloud.application_credential:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_creds
|
||||
description: new description
|
||||
register: appcred
|
||||
|
||||
- name: Assert application credential changed
|
||||
assert:
|
||||
that:
|
||||
- appcred is changed
|
||||
- appcred.application_credential.description == 'new description'
|
||||
|
||||
- name: Get list of all keypairs using application credential
|
||||
openstack.cloud.keypair_info:
|
||||
cloud: "{{ appcred.cloud }}"
|
||||
|
||||
- name: Delete application credential
|
||||
openstack.cloud.application_credential:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_creds
|
||||
register: appcred
|
||||
|
||||
- name: Assert application credential changed
|
||||
assert:
|
||||
that: appcred is changed
|
||||
2
ci/roles/auth/defaults/main.yml
Normal file
2
ci/roles/auth/defaults/main.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
expected_fields:
|
||||
- auth_token
|
||||
@@ -2,5 +2,10 @@
|
||||
- name: Authenticate to the cloud
|
||||
openstack.cloud.auth:
|
||||
cloud={{ cloud }}
|
||||
register: auth
|
||||
|
||||
- debug: var=service_catalog
|
||||
- name: Assert return values of auth module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(auth.keys())|length == 0
|
||||
|
||||
7
ci/roles/baremetal_deploy_template/defaults/main.yml
Normal file
7
ci/roles/baremetal_deploy_template/defaults/main.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
expected_fields:
|
||||
- created_at
|
||||
- extra
|
||||
- id
|
||||
- name
|
||||
- steps
|
||||
- updated_at
|
||||
58
ci/roles/baremetal_deploy_template/tasks/main.yml
Normal file
58
ci/roles/baremetal_deploy_template/tasks/main.yml
Normal file
@@ -0,0 +1,58 @@
|
||||
---
|
||||
# TODO: Actually run this role in CI. Atm we do not have DevStack's ironic plugin enabled.
|
||||
- name: Create baremetal deploy template
|
||||
openstack.cloud.baremetal_deploy_template:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: CUSTOM_ANSIBLE_DEPLOY_TEMPLATE
|
||||
steps:
|
||||
- interface: bios
|
||||
step: apply_configuration
|
||||
args:
|
||||
settings:
|
||||
- name: some-setting
|
||||
value: some-value
|
||||
priority: 110
|
||||
register: template
|
||||
|
||||
- debug: var=template
|
||||
|
||||
- name: Assert return values of baremetal_deploy_template module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(template.template.keys())|length == 0
|
||||
|
||||
- name: Update baremetal deploy template
|
||||
openstack.cloud.baremetal_deploy_template:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
id: "{{ template.template.id }}"
|
||||
extra:
|
||||
foo: bar
|
||||
register: updated_template
|
||||
|
||||
- name: Assert return values of updated baremetal deploy template
|
||||
assert:
|
||||
that:
|
||||
- updated_template is changed
|
||||
- updated_template.template.id == template.template.id
|
||||
|
||||
- name: Update baremetal deploy template again
|
||||
openstack.cloud.baremetal_deploy_template:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
id: "{{ template.template.id }}"
|
||||
register: updated_template
|
||||
|
||||
- name: Assert return values of updated baremetal deploy template
|
||||
assert:
|
||||
that:
|
||||
- updated_template is not changed
|
||||
- updated_template.template.id == template.template.id
|
||||
|
||||
- name: Delete Bare Metal deploy template
|
||||
openstack.cloud.baremetal_deploy_template:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
id: "{{ template.template.id }}"
|
||||
56
ci/roles/baremetal_inspect/defaults/main.yml
Normal file
56
ci/roles/baremetal_inspect/defaults/main.yml
Normal file
@@ -0,0 +1,56 @@
|
||||
expected_fields:
|
||||
- allocation_id
|
||||
- bios_interface
|
||||
- boot_interface
|
||||
- boot_mode
|
||||
- chassis_id
|
||||
- clean_step
|
||||
- conductor
|
||||
- conductor_group
|
||||
- console_interface
|
||||
- created_at
|
||||
- deploy_interface
|
||||
- deploy_step
|
||||
- driver
|
||||
- driver_info
|
||||
- driver_internal_info
|
||||
- extra
|
||||
- fault
|
||||
- id
|
||||
- inspect_interface
|
||||
- instance_id
|
||||
- instance_info
|
||||
- is_automated_clean_enabled
|
||||
- is_console_enabled
|
||||
- is_maintenance
|
||||
- is_protected
|
||||
- is_retired
|
||||
- is_secure_boot
|
||||
- last_error
|
||||
- links
|
||||
- maintenance_reason
|
||||
- management_interface
|
||||
- name
|
||||
- network_interface
|
||||
- owner
|
||||
- port_groups
|
||||
- ports
|
||||
- power_interface
|
||||
- power_state
|
||||
- properties
|
||||
- protected_reason
|
||||
- provision_state
|
||||
- raid_config
|
||||
- raid_interface
|
||||
- rescue_interface
|
||||
- reservation
|
||||
- resource_class
|
||||
- retired_reason
|
||||
- states
|
||||
- storage_interface
|
||||
- target_power_state
|
||||
- target_provision_state
|
||||
- target_raid_config
|
||||
- traits
|
||||
- updated_at
|
||||
- vendor_interface
|
||||
15
ci/roles/baremetal_inspect/tasks/main.yml
Normal file
15
ci/roles/baremetal_inspect/tasks/main.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
# TODO: Actually run this role in CI. Atm we do not have DevStack's ironic plugin enabled.
|
||||
- name: Introspect node
|
||||
openstack.cloud.baremetal_inspect:
|
||||
cloud: "{{ cloud }}"
|
||||
name: node-1
|
||||
register: inspect
|
||||
|
||||
- debug: var=inspect
|
||||
|
||||
- name: assert return values of baremetal_inspect module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(inspect.node.keys())|length == 0
|
||||
56
ci/roles/baremetal_node/defaults/main.yml
Normal file
56
ci/roles/baremetal_node/defaults/main.yml
Normal file
@@ -0,0 +1,56 @@
|
||||
expected_fields:
|
||||
- allocation_id
|
||||
- bios_interface
|
||||
- boot_interface
|
||||
- boot_mode
|
||||
- chassis_id
|
||||
- clean_step
|
||||
- conductor
|
||||
- conductor_group
|
||||
- console_interface
|
||||
- created_at
|
||||
- deploy_interface
|
||||
- deploy_step
|
||||
- driver
|
||||
- driver_info
|
||||
- driver_internal_info
|
||||
- extra
|
||||
- fault
|
||||
- id
|
||||
- inspect_interface
|
||||
- instance_id
|
||||
- instance_info
|
||||
- is_automated_clean_enabled
|
||||
- is_console_enabled
|
||||
- is_maintenance
|
||||
- is_protected
|
||||
- is_retired
|
||||
- is_secure_boot
|
||||
- last_error
|
||||
- links
|
||||
- maintenance_reason
|
||||
- management_interface
|
||||
- name
|
||||
- network_interface
|
||||
- owner
|
||||
- port_groups
|
||||
- ports
|
||||
- power_interface
|
||||
- power_state
|
||||
- properties
|
||||
- protected_reason
|
||||
- provision_state
|
||||
- raid_config
|
||||
- raid_interface
|
||||
- rescue_interface
|
||||
- reservation
|
||||
- resource_class
|
||||
- retired_reason
|
||||
- states
|
||||
- storage_interface
|
||||
- target_power_state
|
||||
- target_provision_state
|
||||
- target_raid_config
|
||||
- traits
|
||||
- updated_at
|
||||
- vendor_interface
|
||||
74
ci/roles/baremetal_node/tasks/main.yml
Normal file
74
ci/roles/baremetal_node/tasks/main.yml
Normal file
@@ -0,0 +1,74 @@
|
||||
---
|
||||
# TODO: Actually run this role in CI. Atm we do not have DevStack's ironic plugin enabled.
|
||||
- name: Create baremetal node
|
||||
openstack.cloud.baremetal_node:
|
||||
cloud: "{{ cloud }}"
|
||||
driver_info:
|
||||
ipmi_address: "1.2.3.4"
|
||||
ipmi_username: "admin"
|
||||
ipmi_password: "secret"
|
||||
name: ansible_baremetal_node
|
||||
nics:
|
||||
- mac: "aa:bb:cc:aa:bb:cc"
|
||||
state: present
|
||||
register: node
|
||||
|
||||
- debug: var=node
|
||||
|
||||
- name: assert return values of baremetal_node module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(node.node.keys())|length == 0
|
||||
|
||||
- name: Fetch baremetal nodes
|
||||
openstack.cloud.baremetal_node_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: nodes
|
||||
|
||||
- name: assert module results of baremetal_node_info module
|
||||
assert:
|
||||
that:
|
||||
- nodes.nodes|list|length > 0
|
||||
|
||||
- name: assert return values of baremetal_node_info module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(nodes.nodes.0.keys())|length == 0
|
||||
|
||||
- name: Fetch baremetal node by name
|
||||
openstack.cloud.baremetal_node_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_baremetal_node
|
||||
register: nodes
|
||||
|
||||
- name: assert module results of baremetal_node_info module
|
||||
assert:
|
||||
that:
|
||||
- nodes.nodes|list|length == 1
|
||||
- nodes.nodes.0.id == node.node.id
|
||||
- nodes.nodes.0.name == "ansible_baremetal_node"
|
||||
|
||||
- name: Delete baremetal node
|
||||
openstack.cloud.baremetal_node:
|
||||
cloud: "{{ cloud }}"
|
||||
driver_info:
|
||||
ipmi_address: "1.2.3.4"
|
||||
ipmi_username: "admin"
|
||||
ipmi_password: "secret"
|
||||
name: ansible_baremetal_node
|
||||
nics:
|
||||
- mac: "aa:bb:cc:aa:bb:cc"
|
||||
state: absent
|
||||
|
||||
- name: Fetch baremetal node by name
|
||||
openstack.cloud.baremetal_node_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_baremetal_node
|
||||
register: nodes
|
||||
|
||||
- name: Assert that baremetal node has been deleted
|
||||
assert:
|
||||
that:
|
||||
- nodes.nodes|list|length == 0
|
||||
14
ci/roles/baremetal_port/defaults/main.yml
Normal file
14
ci/roles/baremetal_port/defaults/main.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
expected_fields:
|
||||
- address
|
||||
- created_at
|
||||
- extra
|
||||
- id
|
||||
- internal_info
|
||||
- is_pxe_enabled
|
||||
- links
|
||||
- local_link_connection
|
||||
- name
|
||||
- node_id
|
||||
- physical_network
|
||||
- port_group_id
|
||||
- updated_at
|
||||
112
ci/roles/baremetal_port/tasks/main.yml
Normal file
112
ci/roles/baremetal_port/tasks/main.yml
Normal file
@@ -0,0 +1,112 @@
|
||||
---
|
||||
# TODO: Actually run this role in CI. Atm we do not have DevStack's ironic plugin enabled.
|
||||
- name: Create baremetal node
|
||||
openstack.cloud.baremetal_node:
|
||||
cloud: "{{ cloud }}"
|
||||
driver_info:
|
||||
ipmi_address: "1.2.3.4"
|
||||
ipmi_username: "admin"
|
||||
ipmi_password: "secret"
|
||||
name: ansible_baremetal_node
|
||||
nics:
|
||||
- mac: "aa:bb:cc:aa:bb:cc"
|
||||
state: present
|
||||
register: node
|
||||
|
||||
- name: Create baremetal port
|
||||
openstack.cloud.baremetal_port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
node: ansible_baremetal_node
|
||||
address: fa:16:3e:aa:aa:aa
|
||||
is_pxe_enabled: False
|
||||
register: port
|
||||
|
||||
- debug: var=port
|
||||
|
||||
- name: Assert return values of baremetal_port module
|
||||
assert:
|
||||
that:
|
||||
- not port.port.is_pxe_enabled
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(port.port.keys())|length == 0
|
||||
|
||||
- name: Fetch baremetal ports
|
||||
openstack.cloud.baremetal_port_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: ports
|
||||
|
||||
- name: Assert module results of baremetal_port_info module
|
||||
assert:
|
||||
that:
|
||||
- ports.ports|list|length > 0
|
||||
|
||||
- name: assert return values of baremetal_port_info module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(ports.ports.0.keys())|length == 0
|
||||
|
||||
- name: Fetch baremetal port by id
|
||||
openstack.cloud.baremetal_port_info:
|
||||
cloud: "{{ cloud }}"
|
||||
id: "{{ port.port.id }}"
|
||||
register: ports
|
||||
|
||||
- name: assert module results of baremetal_port_info module
|
||||
assert:
|
||||
that:
|
||||
- ports.ports|list|length == 1
|
||||
- ports.ports.0.id == port.port.id
|
||||
|
||||
- name: Update baremetal port
|
||||
openstack.cloud.baremetal_port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
id: "{{ port.port.id }}"
|
||||
is_pxe_enabled: True
|
||||
register: updated_port
|
||||
|
||||
- name: Assert return values of updated baremetal port
|
||||
assert:
|
||||
that:
|
||||
- update_port is changed
|
||||
- update_port.port.id == port.port.id
|
||||
- update_port.port.address == port.port.address
|
||||
- update_port.port.is_pxe_enabled
|
||||
|
||||
- name: Update baremetal port again
|
||||
openstack.cloud.baremetal_port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
id: "{{ port.port.id }}"
|
||||
is_pxe_enabled: True
|
||||
register: updated_port
|
||||
|
||||
- name: Assert return values of updated baremetal port
|
||||
assert:
|
||||
that:
|
||||
- update_port is not changed
|
||||
- update_port.port.id == port.port.id
|
||||
|
||||
- name: Delete Bare Metal port
|
||||
openstack.cloud.baremetal_port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
id: "{{ port.port.id }}"
|
||||
|
||||
- name: Fetch baremetal ports
|
||||
openstack.cloud.baremetal_port_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: ports
|
||||
|
||||
- name: Assert no baremetal port is left
|
||||
assert:
|
||||
that:
|
||||
- ports.ports|list|length == 0
|
||||
|
||||
- name: Delete baremetal node
|
||||
openstack.cloud.baremetal_node:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_baremetal_node
|
||||
state: absent
|
||||
7
ci/roles/catalog_service/defaults/main.yml
Normal file
7
ci/roles/catalog_service/defaults/main.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
expected_fields:
|
||||
- description
|
||||
- id
|
||||
- is_enabled
|
||||
- links
|
||||
- name
|
||||
- type
|
||||
103
ci/roles/catalog_service/tasks/main.yml
Normal file
103
ci/roles/catalog_service/tasks/main.yml
Normal file
@@ -0,0 +1,103 @@
|
||||
---
|
||||
- name: Delete service test
|
||||
openstack.cloud.catalog_service:
|
||||
cloud: "{{ cloud }}"
|
||||
service_type: test
|
||||
name: test
|
||||
state: absent
|
||||
register: service_delete
|
||||
|
||||
- name: Assert changed is set to false
|
||||
assert:
|
||||
that:
|
||||
- not service_delete.changed
|
||||
|
||||
- name: Create a service for test
|
||||
openstack.cloud.catalog_service:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "test_service"
|
||||
state: present
|
||||
service_type: test_type
|
||||
description: "Test service"
|
||||
register: service_test
|
||||
|
||||
- name: Verify returned values
|
||||
assert:
|
||||
that: item in service_test.service
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- name: Check if the service test was created successfully
|
||||
openstack.cloud.catalog_service:
|
||||
cloud: "{{ cloud }}"
|
||||
service_type: test
|
||||
name: test
|
||||
register: service_created
|
||||
|
||||
- name: Verify returned values
|
||||
assert:
|
||||
that: item in service_created.service
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- name: Update service test
|
||||
openstack.cloud.catalog_service:
|
||||
cloud: "{{ cloud }}"
|
||||
service_type: test
|
||||
description: "A new description"
|
||||
is_enabled: False
|
||||
name: test
|
||||
register: service_test
|
||||
|
||||
- name: Check if description and is_enabled were updated
|
||||
assert:
|
||||
that:
|
||||
- service_test.service.description == "A new description"
|
||||
- not (service_test.service.is_enabled|bool)
|
||||
|
||||
- name: Get all services
|
||||
openstack.cloud.catalog_service_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: services
|
||||
|
||||
- name: Assert return values of catalog_service_info module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(services.services[0].keys())|length == 0
|
||||
|
||||
- name: Get service by name
|
||||
openstack.cloud.catalog_service_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: test
|
||||
register: services
|
||||
|
||||
- name: Assert services returned by catalog_service_info module
|
||||
assert:
|
||||
that:
|
||||
- services.services|length == 1
|
||||
- services.services[0].id == service_test.service.id
|
||||
|
||||
- name: Delete service test
|
||||
openstack.cloud.catalog_service:
|
||||
cloud: "{{ cloud }}"
|
||||
service_type: test
|
||||
name: test
|
||||
state: absent
|
||||
register: service_deleted
|
||||
|
||||
- name: Verify if service was deleted
|
||||
assert:
|
||||
that:
|
||||
- service_deleted.changed
|
||||
|
||||
- name: Delete service test again
|
||||
openstack.cloud.catalog_service:
|
||||
cloud: "{{ cloud }}"
|
||||
service_type: test
|
||||
name: test
|
||||
state: absent
|
||||
register: service_deleted
|
||||
|
||||
- name: Assert changed is set to false
|
||||
assert:
|
||||
that:
|
||||
- not service_deleted.changed
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
- name: List all profiles
|
||||
openstack.cloud.config:
|
||||
register: list
|
||||
|
||||
# WARNING: This will output sensitive authentication information!!!!
|
||||
- debug: var=list
|
||||
26
ci/roles/coe_cluster/defaults/main.yml
Normal file
26
ci/roles/coe_cluster/defaults/main.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
expected_fields:
|
||||
- api_address
|
||||
- cluster_template_id
|
||||
- coe_version
|
||||
- create_timeout
|
||||
- created_at
|
||||
- discovery_url
|
||||
- fixed_network
|
||||
- fixed_subnet
|
||||
- flavor_id
|
||||
- id
|
||||
- is_floating_ip_enabled
|
||||
- is_master_lb_enabled
|
||||
- keypair
|
||||
- labels
|
||||
- master_addresses
|
||||
- master_count
|
||||
- master_flavor_id
|
||||
- name
|
||||
- node_addresses
|
||||
- node_count
|
||||
- stack_id
|
||||
- status
|
||||
- status_reason
|
||||
- updated_at
|
||||
- uuid
|
||||
183
ci/roles/coe_cluster/tasks/main.yml
Normal file
183
ci/roles/coe_cluster/tasks/main.yml
Normal file
@@ -0,0 +1,183 @@
|
||||
---
|
||||
- name: Create keypair
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_keypair
|
||||
state: present
|
||||
register: keypair
|
||||
|
||||
- name: List all images
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: images
|
||||
|
||||
- name: Identify Fedora CoreOS image id
|
||||
set_fact:
|
||||
image_id: "{{ images.images|community.general.json_query(query)|first }}"
|
||||
vars:
|
||||
query: "[?starts_with(name, 'fedora-coreos')].id"
|
||||
|
||||
- name: Create external network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
external: true
|
||||
name: ansible_external_network
|
||||
state: present
|
||||
register: external_network
|
||||
|
||||
- name: Create external subnet
|
||||
openstack.cloud.subnet:
|
||||
cidr: 10.6.6.0/24
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_external_subnet
|
||||
network_name: ansible_external_network
|
||||
state: present
|
||||
|
||||
- name: Create internal network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_internal_network
|
||||
external: false
|
||||
|
||||
- name: Create internal subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
network_name: ansible_internal_network
|
||||
name: ansible_internal_subnet
|
||||
cidr: 10.7.7.0/24
|
||||
|
||||
- name: Create router
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
external_fixed_ips:
|
||||
- subnet: ansible_external_subnet
|
||||
ip: 10.6.6.10
|
||||
interfaces:
|
||||
- net: ansible_internal_network
|
||||
subnet: ansible_internal_subnet
|
||||
portip: 10.7.7.1
|
||||
name: ansible_router
|
||||
network: ansible_external_network
|
||||
state: present
|
||||
|
||||
- name: Create Kubernetes cluster template
|
||||
openstack.cloud.coe_cluster_template:
|
||||
cloud: "{{ cloud }}"
|
||||
coe: kubernetes
|
||||
external_network_id: '{{ external_network.network.id }}'
|
||||
fixed_network: ansible_internal_network
|
||||
fixed_subnet: ansible_internal_subnet
|
||||
image_id: '{{ image_id }}'
|
||||
is_floating_ip_enabled: true
|
||||
keypair_id: '{{ keypair.keypair.id }}'
|
||||
flavor_id: 'm1.small'
|
||||
master_flavor_id: 'm1.small'
|
||||
name: k8s
|
||||
state: present
|
||||
register: coe_cluster_template
|
||||
|
||||
- name: Create Kubernetes cluster
|
||||
openstack.cloud.coe_cluster:
|
||||
cloud: "{{ cloud }}"
|
||||
cluster_template_id: "{{ coe_cluster_template.cluster_template.uuid }}"
|
||||
keypair: ansible_keypair
|
||||
name: k8s
|
||||
state: present
|
||||
# cluster creation takes longer than max tenant timeout of 10800
|
||||
wait: false
|
||||
register: coe_cluster
|
||||
|
||||
- name: Assert return values of coe_cluster module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(coe_cluster.cluster.keys())|length == 0
|
||||
|
||||
- name: Pause for 1 minutes to allow Magnum to create the Kubernetes cluster
|
||||
ansible.builtin.pause:
|
||||
minutes: 1
|
||||
|
||||
- name: Create Kubernetes cluster again
|
||||
openstack.cloud.coe_cluster:
|
||||
cloud: "{{ cloud }}"
|
||||
cluster_template_id: "{{ coe_cluster_template.cluster_template.uuid }}"
|
||||
keypair: ansible_keypair
|
||||
name: k8s
|
||||
state: present
|
||||
# cluster creation takes longer than max tenant timeout of 10800
|
||||
wait: false
|
||||
register: coe_cluster
|
||||
|
||||
- name: Assert return values of coe_cluster module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(coe_cluster.cluster.keys())|length == 0
|
||||
|
||||
- name: Delete Kubernetes cluster
|
||||
openstack.cloud.coe_cluster:
|
||||
cloud: "{{ cloud }}"
|
||||
name: k8s
|
||||
state: absent
|
||||
register: coe_cluster
|
||||
|
||||
- name: Assert return values of coe_cluster module
|
||||
assert:
|
||||
that:
|
||||
- coe_cluster is changed
|
||||
|
||||
- name: Delete Kubernetes cluster again
|
||||
openstack.cloud.coe_cluster:
|
||||
cloud: "{{ cloud }}"
|
||||
name: k8s
|
||||
state: absent
|
||||
register: coe_cluster
|
||||
|
||||
- name: Assert return values of coe_cluster module
|
||||
assert:
|
||||
that:
|
||||
- coe_cluster is not changed
|
||||
|
||||
- name: Delete Kubernetes cluster template
|
||||
openstack.cloud.coe_cluster_template:
|
||||
cloud: "{{ cloud }}"
|
||||
name: k8s
|
||||
state: absent
|
||||
|
||||
- name: Delete router
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_router
|
||||
state: absent
|
||||
|
||||
- name: Delete internal subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_internal_subnet
|
||||
|
||||
- name: Delete internal network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_internal_network
|
||||
|
||||
- name: Delete external subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_external_subnet
|
||||
state: absent
|
||||
|
||||
- name: Delete external network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_external_network
|
||||
state: absent
|
||||
|
||||
- name: Delete keypair
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_keypair
|
||||
state: absent
|
||||
33
ci/roles/coe_cluster_template/defaults/main.yml
Normal file
33
ci/roles/coe_cluster_template/defaults/main.yml
Normal file
@@ -0,0 +1,33 @@
|
||||
expected_fields:
|
||||
- apiserver_port
|
||||
- cluster_distro
|
||||
- coe
|
||||
- created_at
|
||||
- dns_nameserver
|
||||
- docker_storage_driver
|
||||
- docker_volume_size
|
||||
- external_network_id
|
||||
- fixed_network
|
||||
- fixed_subnet
|
||||
- flavor_id
|
||||
- http_proxy
|
||||
- https_proxy
|
||||
- id
|
||||
- image_id
|
||||
- insecure_registry
|
||||
- is_floating_ip_enabled
|
||||
- is_hidden
|
||||
- is_master_lb_enabled
|
||||
- is_public
|
||||
- is_registry_enabled
|
||||
- is_tls_disabled
|
||||
- keypair_id
|
||||
- labels
|
||||
- master_flavor_id
|
||||
- name
|
||||
- network_driver
|
||||
- no_proxy
|
||||
- server_type
|
||||
- updated_at
|
||||
- uuid
|
||||
- volume_driver
|
||||
87
ci/roles/coe_cluster_template/tasks/main.yml
Normal file
87
ci/roles/coe_cluster_template/tasks/main.yml
Normal file
@@ -0,0 +1,87 @@
|
||||
---
|
||||
- name: Create keypair
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_keypair
|
||||
state: present
|
||||
register: keypair
|
||||
|
||||
- name: List all images
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: images
|
||||
|
||||
- name: Identify Fedora CoreOS image id
|
||||
set_fact:
|
||||
image_id: "{{ images.images|community.general.json_query(query)|first }}"
|
||||
vars:
|
||||
query: "[?starts_with(name, 'fedora-coreos')].id"
|
||||
|
||||
- name: Create Kubernetes cluster template
|
||||
openstack.cloud.coe_cluster_template:
|
||||
cloud: "{{ cloud }}"
|
||||
coe: kubernetes
|
||||
is_floating_ip_enabled: false
|
||||
image_id: '{{ image_id }}'
|
||||
keypair_id: '{{ keypair.keypair.id }}'
|
||||
name: k8s
|
||||
state: present
|
||||
labels:
|
||||
docker_volume_size: 10
|
||||
cloud_provider_tag: v1.23.1
|
||||
register: coe_cluster_template
|
||||
|
||||
- name: Assert return values of coe_cluster_template module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(coe_cluster_template.cluster_template.keys())|length == 0
|
||||
|
||||
- name: Create Kubernetes cluster template again
|
||||
openstack.cloud.coe_cluster_template:
|
||||
cloud: "{{ cloud }}"
|
||||
coe: kubernetes
|
||||
is_floating_ip_enabled: false
|
||||
image_id: '{{ image_id }}'
|
||||
keypair_id: '{{ keypair.keypair.id }}'
|
||||
name: k8s
|
||||
state: present
|
||||
labels:
|
||||
docker_volume_size: 10
|
||||
cloud_provider_tag: v1.23.1
|
||||
register: coe_cluster_template
|
||||
|
||||
- name: Assert return values of coe_cluster_template module
|
||||
assert:
|
||||
that:
|
||||
- coe_cluster_template is not changed
|
||||
|
||||
- name: Delete Kubernetes cluster template
|
||||
openstack.cloud.coe_cluster_template:
|
||||
cloud: "{{ cloud }}"
|
||||
name: k8s
|
||||
state: absent
|
||||
register: coe_cluster_template
|
||||
|
||||
- name: Assert return values of coe_cluster_template module
|
||||
assert:
|
||||
that:
|
||||
- coe_cluster_template is changed
|
||||
|
||||
- name: Delete Kubernetes cluster template again
|
||||
openstack.cloud.coe_cluster_template:
|
||||
cloud: "{{ cloud }}"
|
||||
name: k8s
|
||||
state: absent
|
||||
register: coe_cluster_template
|
||||
|
||||
- name: Assert return values of coe_cluster_template module
|
||||
assert:
|
||||
that:
|
||||
- coe_cluster_template is not changed
|
||||
|
||||
- name: Delete keypair
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_keypair
|
||||
state: absent
|
||||
14
ci/roles/compute_flavor/defaults/main.yml
Normal file
14
ci/roles/compute_flavor/defaults/main.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
expected_fields:
|
||||
- description
|
||||
- disk
|
||||
- ephemeral
|
||||
- extra_specs
|
||||
- id
|
||||
- is_disabled
|
||||
- is_public
|
||||
- name
|
||||
- original_name
|
||||
- ram
|
||||
- rxtx_factor
|
||||
- swap
|
||||
- vcpus
|
||||
254
ci/roles/compute_flavor/tasks/main.yml
Normal file
254
ci/roles/compute_flavor/tasks/main.yml
Normal file
@@ -0,0 +1,254 @@
|
||||
---
|
||||
- name: Delete resources before tests
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ item }}"
|
||||
loop:
|
||||
- ansible_public_flavor
|
||||
- ansible_private_flavor
|
||||
- ansible_extra_specs_flavor
|
||||
- ansible_defaults_flavor
|
||||
|
||||
- name: Create public flavor
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_public_flavor
|
||||
is_public: True
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
ephemeral: 10
|
||||
swap: 1
|
||||
id: 12345
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that: item in result.flavor
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that: result is changed
|
||||
|
||||
- name: Create public flavor again
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_public_flavor
|
||||
is_public: True
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
ephemeral: 10
|
||||
swap: 1
|
||||
id: 12345
|
||||
register: result
|
||||
|
||||
- name: Assert not changed
|
||||
assert:
|
||||
that: result is not changed
|
||||
|
||||
- name: Delete public flavor
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_public_flavor
|
||||
register: result
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that: result is changed
|
||||
|
||||
- name: Delete public flavor again
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_public_flavor
|
||||
register: result
|
||||
|
||||
- name: Assert not changed
|
||||
assert:
|
||||
that: result is not changed
|
||||
|
||||
- name: Create private flavor
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_private_flavor
|
||||
is_public: False
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
ephemeral: 10
|
||||
swap: 1
|
||||
id: 12345
|
||||
|
||||
- name: Delete private flavor
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_private_flavor
|
||||
|
||||
- name: Create flavor (defaults)
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_defaults_flavor
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
register: result
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that: result is changed
|
||||
|
||||
- name: Create flavor (defaults) again
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_defaults_flavor
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
register: result
|
||||
|
||||
- name: Assert not changed
|
||||
assert:
|
||||
that: result is not changed
|
||||
|
||||
- name: Delete flavor (defaults)
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_defaults_flavor
|
||||
|
||||
- name: Create flavor (extra_specs)
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_extra_specs_flavor
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
extra_specs:
|
||||
"os:secure_boot": "required"
|
||||
register: result
|
||||
|
||||
- name: Assert returned value
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.flavor.extra_specs['os:secure_boot'] == 'required'
|
||||
|
||||
- name: Create flavor (extra_specs) again
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_extra_specs_flavor
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
extra_specs:
|
||||
"os:secure_boot": "required"
|
||||
register: result
|
||||
|
||||
- name: Assert not changed
|
||||
assert:
|
||||
that: result is not changed
|
||||
|
||||
- name: Change extra_specs value
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_extra_specs_flavor
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
extra_specs:
|
||||
"os:secure_boot": "disabled"
|
||||
register: result
|
||||
|
||||
- name: Assert returned value
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.flavor.extra_specs['os:secure_boot'] == 'disabled'
|
||||
|
||||
- name: Append extra_specs value
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_extra_specs_flavor
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
extra_specs:
|
||||
"os:secure_boot": "disabled"
|
||||
"hw_video:ram_max_mb": 200
|
||||
register: result
|
||||
|
||||
- name: Assert returned value
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.flavor.extra_specs | length == 2
|
||||
- "'os:secure_boot' in result.flavor.extra_specs"
|
||||
- "'hw_video:ram_max_mb' in result.flavor.extra_specs"
|
||||
|
||||
- name: Drop extra_specs value
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_extra_specs_flavor
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
extra_specs:
|
||||
"hw_video:ram_max_mb": 200
|
||||
register: result
|
||||
|
||||
- name: Assert returned value
|
||||
assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result.flavor.extra_specs | length == 1
|
||||
- "'hw_video:ram_max_mb' in result.flavor.extra_specs"
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that: result is changed
|
||||
|
||||
- name: Clean up
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ item }}"
|
||||
loop:
|
||||
- ansible_public_flavor
|
||||
- ansible_private_flavor
|
||||
- ansible_extra_specs_flavor
|
||||
- ansible_defaults_flavor
|
||||
|
||||
- name: List flavors
|
||||
openstack.cloud.compute_flavor_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: flavor_info
|
||||
|
||||
- assert:
|
||||
that: item in flavor_info.flavors[0]
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- name: List flavors with filter
|
||||
openstack.cloud.compute_flavor_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "m1.tiny"
|
||||
register: flavor
|
||||
|
||||
- name: Check output of list flavors with filter
|
||||
assert:
|
||||
that:
|
||||
- flavor.flavors | length == 1
|
||||
- flavor.flavors.0.name == "m1.tiny"
|
||||
96
ci/roles/compute_flavor_access/tasks/main.yml
Normal file
96
ci/roles/compute_flavor_access/tasks/main.yml
Normal file
@@ -0,0 +1,96 @@
|
||||
---
|
||||
- name: Create flavor
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: devstack-admin
|
||||
state: present
|
||||
name: ansible_flavor
|
||||
is_public: False
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
ephemeral: 10
|
||||
swap: 1
|
||||
register: flavor
|
||||
|
||||
- name: Fetch demo project
|
||||
openstack.cloud.project_info:
|
||||
cloud: devstack-admin
|
||||
name: demo
|
||||
register: projects
|
||||
|
||||
- name: Verify demo project
|
||||
assert:
|
||||
that:
|
||||
- projects.projects|length == 1
|
||||
- projects.projects.0.name == "demo"
|
||||
|
||||
- name: Grant access to flavor
|
||||
openstack.cloud.compute_flavor_access:
|
||||
cloud: devstack-admin
|
||||
name: ansible_flavor
|
||||
project: demo
|
||||
state: present
|
||||
register: access
|
||||
|
||||
- name: Verify access
|
||||
assert:
|
||||
that:
|
||||
- access is changed
|
||||
- access.flavor.id == flavor.flavor.id
|
||||
|
||||
# TODO: Replace with appropriate Ansible module once available
|
||||
- name: Get compute flavor
|
||||
command: openstack --os-cloud=devstack-admin flavor show ansible_flavor -f json
|
||||
register: flavor_show
|
||||
|
||||
- name: Verify volume type access
|
||||
assert:
|
||||
that:
|
||||
- (flavor_show.stdout | from_json).name == 'ansible_flavor'
|
||||
- projects.projects.0.id in (flavor_show.stdout | from_json).access_project_ids
|
||||
|
||||
- name: Grant access to flavor again
|
||||
openstack.cloud.compute_flavor_access:
|
||||
cloud: devstack-admin
|
||||
name: ansible_flavor
|
||||
project: demo
|
||||
state: present
|
||||
register: access
|
||||
|
||||
- name: Verify access did not change
|
||||
assert:
|
||||
that:
|
||||
- access is not changed
|
||||
|
||||
- name: Revoke access to flavor
|
||||
openstack.cloud.compute_flavor_access:
|
||||
cloud: devstack-admin
|
||||
name: ansible_flavor
|
||||
project: demo
|
||||
state: absent
|
||||
register: access
|
||||
|
||||
- name: Verify revoked access
|
||||
assert:
|
||||
that:
|
||||
- access is changed
|
||||
- access.flavor.id == flavor.flavor.id
|
||||
|
||||
- name: Revoke access to flavor again
|
||||
openstack.cloud.compute_flavor_access:
|
||||
cloud: devstack-admin
|
||||
name: ansible_flavor
|
||||
project: demo
|
||||
state: absent
|
||||
register: access
|
||||
|
||||
- name: Verify access did not change
|
||||
assert:
|
||||
that:
|
||||
- access is not changed
|
||||
|
||||
- name: Delete flavor
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: devstack-admin
|
||||
state: absent
|
||||
name: ansible_flavor
|
||||
11
ci/roles/compute_service/defaults/main.yml
Normal file
11
ci/roles/compute_service/defaults/main.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
expected_fields:
|
||||
- availability_zone
|
||||
- binary
|
||||
- disabled_reason
|
||||
- host
|
||||
- id
|
||||
- is_forced_down
|
||||
- name
|
||||
- state
|
||||
- status
|
||||
- updated_at
|
||||
23
ci/roles/compute_service/tasks/main.yml
Normal file
23
ci/roles/compute_service/tasks/main.yml
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
- name: Fetch compute services
|
||||
openstack.cloud.compute_service_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: compute_services
|
||||
|
||||
- name: Assert return values of compute_service_info module
|
||||
assert:
|
||||
that:
|
||||
- compute_services.compute_services | length > 0
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(compute_services.compute_services[0].keys())|length == 0
|
||||
|
||||
- name: Fetch compute services with filters
|
||||
openstack.cloud.compute_service_info:
|
||||
cloud: "{{ cloud }}"
|
||||
binary: "nova-compute"
|
||||
register: compute_services
|
||||
|
||||
- name: Assert return values of compute_service_info module
|
||||
assert:
|
||||
that:
|
||||
- compute_services.compute_services | length > 0
|
||||
10
ci/roles/config/tasks/main.yml
Normal file
10
ci/roles/config/tasks/main.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
- name: List all cloud profiles
|
||||
openstack.cloud.config:
|
||||
register: config
|
||||
# WARNING: This will output sensitive authentication information!!!!
|
||||
|
||||
- name: Assert config module
|
||||
assert:
|
||||
that:
|
||||
- cloud in (config.clouds | map(attribute='name') | list)
|
||||
17
ci/roles/dns_zone/defaults/main.yml
Normal file
17
ci/roles/dns_zone/defaults/main.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
expected_fields:
|
||||
- action
|
||||
- attributes
|
||||
- created_at
|
||||
- description
|
||||
- email
|
||||
- id
|
||||
- links
|
||||
- masters
|
||||
- name
|
||||
- pool_id
|
||||
- project_id
|
||||
- serial
|
||||
- status
|
||||
- ttl
|
||||
- type
|
||||
- updated_at
|
||||
67
ci/roles/dns_zone/tasks/main.yml
Normal file
67
ci/roles/dns_zone/tasks/main.yml
Normal file
@@ -0,0 +1,67 @@
|
||||
---
|
||||
- name: Create dns zone
|
||||
openstack.cloud.dns_zone:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible.test.zone.
|
||||
type: primary
|
||||
email: test@example.net
|
||||
register: dns_zone
|
||||
|
||||
- name: Assert return values of dns_zone module
|
||||
assert:
|
||||
that:
|
||||
- dns_zone.zone.name == "ansible.test.zone."
|
||||
- dns_zone.zone.type|lower == "primary"
|
||||
- dns_zone.zone.email == "test@example.net"
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(dns_zone.zone.keys())|length == 0
|
||||
|
||||
- name: Update dns zone
|
||||
openstack.cloud.dns_zone:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible.test.zone.
|
||||
description: "Another description"
|
||||
register: dns_zone
|
||||
|
||||
- name: Assert return values of dns_zone module
|
||||
assert:
|
||||
that:
|
||||
- dns_zone.zone.description == "Another description"
|
||||
|
||||
- name: Fetch all dns zones
|
||||
openstack.cloud.dns_zone_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: dns_zones
|
||||
|
||||
- name: Assert return values of dns_zone_info module
|
||||
assert:
|
||||
that:
|
||||
- dns_zones is not changed
|
||||
- dns_zones | length > 0
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(dns_zones.zones[0].keys())|length == 0
|
||||
|
||||
- name: Fetch a dns zone by name
|
||||
openstack.cloud.dns_zone_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible.test.zone.
|
||||
register: dns_zones
|
||||
|
||||
- name: Assert return values of dns_zone_info module
|
||||
assert:
|
||||
that:
|
||||
- dns_zones is not changed
|
||||
- dns_zones.zones | length == 1
|
||||
- dns_zones.zones[0].id == dns_zone.zone.id
|
||||
|
||||
- name: Delete dns zone
|
||||
openstack.cloud.dns_zone:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible.test.zone.
|
||||
state: absent
|
||||
register: dns_zone
|
||||
|
||||
- name: Verify dns zone
|
||||
assert:
|
||||
that:
|
||||
- dns_zone is changed
|
||||
9
ci/roles/endpoint/defaults/main.yaml
Normal file
9
ci/roles/endpoint/defaults/main.yaml
Normal file
@@ -0,0 +1,9 @@
|
||||
expected_fields:
|
||||
- id
|
||||
- interface
|
||||
- is_enabled
|
||||
- links
|
||||
- name
|
||||
- region_id
|
||||
- service_id
|
||||
- url
|
||||
68
ci/roles/endpoint/tasks/main.yml
Normal file
68
ci/roles/endpoint/tasks/main.yml
Normal file
@@ -0,0 +1,68 @@
|
||||
---
|
||||
- name: Create a service endpoint for compute
|
||||
openstack.cloud.endpoint:
|
||||
cloud: "{{ cloud }}"
|
||||
service: nova
|
||||
endpoint_interface: internal
|
||||
url: http://controller:9292
|
||||
region: RegionOne
|
||||
state: present
|
||||
register: endpoint_test
|
||||
|
||||
- debug: var=endpoint_test
|
||||
|
||||
- name: Assert return values of endpoint module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(endpoint_test.endpoint.keys())|length == 0
|
||||
|
||||
- name: Ensure service have the proper endpoint
|
||||
assert:
|
||||
that:
|
||||
- endpoint_test.endpoint.url == "http://controller:9292"
|
||||
|
||||
- name: Create service endpoint for compute again
|
||||
openstack.cloud.endpoint:
|
||||
cloud: "{{ cloud }}"
|
||||
service: nova
|
||||
endpoint_interface: internal
|
||||
url: http://controller:9292
|
||||
region: RegionOne
|
||||
state: present
|
||||
register: endpoint_again
|
||||
|
||||
- name: Ensure changed is false
|
||||
assert:
|
||||
that:
|
||||
- not endpoint_again.changed
|
||||
|
||||
- name: Update service endpoint url
|
||||
openstack.cloud.endpoint:
|
||||
cloud: "{{ cloud }}"
|
||||
service: nova
|
||||
endpoint_interface: internal
|
||||
url: http://controller:9393
|
||||
region: RegionOne
|
||||
state: present
|
||||
register: endpoint_updated
|
||||
|
||||
- name: Ensure service endpoint was updated
|
||||
assert:
|
||||
that:
|
||||
- endpoint_updated.endpoint.url == "http://controller:9393"
|
||||
|
||||
- name: Delete service endpoint
|
||||
openstack.cloud.endpoint:
|
||||
cloud: "{{ cloud }}"
|
||||
service: nova
|
||||
endpoint_interface: internal
|
||||
url: http://controller:9393
|
||||
region: RegionOne
|
||||
state: absent
|
||||
register: endpoint_deleted
|
||||
|
||||
- name: Ensure service endpoint was deleted
|
||||
assert:
|
||||
that:
|
||||
- endpoint_deleted.changed
|
||||
@@ -1,3 +1,7 @@
|
||||
expected_fields:
|
||||
- id
|
||||
- name
|
||||
- rules
|
||||
mapping_name: 'ansible-test-mapping'
|
||||
mapping_name_2: 'ansible-test-mapping-2'
|
||||
mapping_rules_1:
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
- module_defaults:
|
||||
# meta/action_groups.yml glue seems to be missing
|
||||
# group/os:
|
||||
# cloud: "{{ cloud }}"
|
||||
group/openstack.cloud.openstack:
|
||||
cloud: "{{ cloud }}"
|
||||
# Backward compatibility with Ansible 2.9
|
||||
openstack.cloud.federation_mapping:
|
||||
cloud: "{{ cloud }}"
|
||||
openstack.cloud.federation_mapping_info:
|
||||
@@ -12,10 +12,6 @@
|
||||
openstack.cloud.federation_mapping:
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name }}'
|
||||
register: delete_mapping
|
||||
- assert:
|
||||
that:
|
||||
- delete_mapping is successful
|
||||
|
||||
- name: 'Create mapping - CHECK_MODE'
|
||||
openstack.cloud.federation_mapping:
|
||||
@@ -23,20 +19,20 @@
|
||||
name: '{{ mapping_name }}'
|
||||
rules: '{{ mapping_rules_1 }}'
|
||||
register: create_mapping
|
||||
check_mode: yes
|
||||
check_mode: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- create_mapping is successful
|
||||
- create_mapping is changed
|
||||
|
||||
- name: 'Fetch mapping info (mapping should be absent)'
|
||||
openstack.cloud.federation_mapping_info:
|
||||
name: '{{ mapping_name }}'
|
||||
register: mapping_info
|
||||
ignore_errors: yes
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- mapping_info is failed
|
||||
- mapping_info.mappings | length == 0
|
||||
|
||||
- name: 'Create mapping'
|
||||
openstack.cloud.federation_mapping:
|
||||
@@ -44,52 +40,50 @@
|
||||
name: '{{ mapping_name }}'
|
||||
rules: '{{ mapping_rules_1 }}'
|
||||
register: create_mapping
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- create_mapping is successful
|
||||
- create_mapping is changed
|
||||
- '"id" in create_mapping.mapping'
|
||||
- '"name" in create_mapping.mapping'
|
||||
- '"rules" in create_mapping.mapping'
|
||||
- create_mapping.mapping.id == mapping_name
|
||||
- create_mapping.mapping.name == mapping_name
|
||||
- create_mapping.mapping.rules | length == 1
|
||||
|
||||
- name: assert return values of federation_mapping module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(create_mapping.mapping.keys())|length == 0
|
||||
|
||||
- name: 'Fetch mapping info - with name'
|
||||
openstack.cloud.federation_mapping_info:
|
||||
name: '{{ mapping_name }}'
|
||||
register: mapping_info
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- mapping_info is successful
|
||||
- '"mappings" in mapping_info'
|
||||
- mapping_info.mappings | length == 1
|
||||
- '"id" in mapping_0'
|
||||
- '"name" in mapping_0'
|
||||
- '"rules" in mapping_0'
|
||||
- mapping_0.id == mapping_name
|
||||
- mapping_0.name == mapping_name
|
||||
- mapping_0.rules | length == 1
|
||||
vars:
|
||||
mapping_0: '{{ mapping_info.mappings[0] }}'
|
||||
- mapping_info.mappings[0].id == mapping_name
|
||||
- mapping_info.mappings[0].name == mapping_name
|
||||
- mapping_info.mappings[0].rules | length == 1
|
||||
|
||||
- name: Check info about mappings
|
||||
assert:
|
||||
that:
|
||||
- mapping_info.mappings|length > 0
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(mapping_info.mappings[0].keys())|length == 0
|
||||
|
||||
- name: 'Fetch mapping info - without name'
|
||||
openstack.cloud.federation_mapping_info: {}
|
||||
register: mapping_info
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- mapping_info is successful
|
||||
- '"mappings" in mapping_info'
|
||||
# In CI we generally have a clean slate, but this might
|
||||
# not be true for everyone...
|
||||
- mapping_info.mappings | length >= 1
|
||||
- '"id" in mapping_0'
|
||||
- '"name" in mapping_0'
|
||||
- '"rules" in mapping_0'
|
||||
- mapping_name in (mapping_info.mappings | map(attribute='id'))
|
||||
- mapping_name in (mapping_info.mappings | map(attribute='name'))
|
||||
vars:
|
||||
mapping_0: '{{ mapping_info.mappings[0] }}'
|
||||
|
||||
- name: 'Create mapping (retry - no change) - CHECK_MODE'
|
||||
openstack.cloud.federation_mapping:
|
||||
@@ -97,10 +91,10 @@
|
||||
name: '{{ mapping_name }}'
|
||||
rules: '{{ mapping_rules_1 }}'
|
||||
register: create_mapping
|
||||
check_mode: yes
|
||||
check_mode: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- create_mapping is successful
|
||||
- create_mapping is not changed
|
||||
|
||||
- name: 'Create mapping (retry - no change)'
|
||||
@@ -109,13 +103,10 @@
|
||||
name: '{{ mapping_name }}'
|
||||
rules: '{{ mapping_rules_1 }}'
|
||||
register: create_mapping
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- create_mapping is successful
|
||||
- create_mapping is not changed
|
||||
- '"id" in create_mapping.mapping'
|
||||
- '"name" in create_mapping.mapping'
|
||||
- '"rules" in create_mapping.mapping'
|
||||
- create_mapping.mapping.id == mapping_name
|
||||
- create_mapping.mapping.name == mapping_name
|
||||
- create_mapping.mapping.rules | length == 1
|
||||
@@ -126,10 +117,10 @@
|
||||
name: '{{ mapping_name }}'
|
||||
rules: '{{ mapping_rules_2 }}'
|
||||
register: update_mapping
|
||||
check_mode: yes
|
||||
check_mode: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- update_mapping is successful
|
||||
- update_mapping is changed
|
||||
|
||||
- name: 'Update mapping'
|
||||
@@ -138,13 +129,10 @@
|
||||
name: '{{ mapping_name }}'
|
||||
rules: '{{ mapping_rules_2 }}'
|
||||
register: update_mapping
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- update_mapping is successful
|
||||
- update_mapping is changed
|
||||
- '"id" in update_mapping.mapping'
|
||||
- '"name" in update_mapping.mapping'
|
||||
- '"rules" in update_mapping.mapping'
|
||||
- update_mapping.mapping.id == mapping_name
|
||||
- update_mapping.mapping.name == mapping_name
|
||||
- update_mapping.mapping.rules | length == 1
|
||||
@@ -155,13 +143,10 @@
|
||||
name: '{{ mapping_name }}'
|
||||
rules: '{{ mapping_rules_2 }}'
|
||||
register: update_mapping
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- update_mapping is successful
|
||||
- update_mapping is not changed
|
||||
- '"id" in update_mapping.mapping'
|
||||
- '"name" in update_mapping.mapping'
|
||||
- '"rules" in update_mapping.mapping'
|
||||
- update_mapping.mapping.id == mapping_name
|
||||
- update_mapping.mapping.name == mapping_name
|
||||
- update_mapping.mapping.rules | length == 1
|
||||
@@ -172,13 +157,10 @@
|
||||
name: '{{ mapping_name_2 }}'
|
||||
rules: '{{ mapping_rules_1 }}'
|
||||
register: create_mapping
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- create_mapping is successful
|
||||
- create_mapping is changed
|
||||
- '"id" in create_mapping.mapping'
|
||||
- '"name" in create_mapping.mapping'
|
||||
- '"rules" in create_mapping.mapping'
|
||||
- create_mapping.mapping.id == mapping_name_2
|
||||
- create_mapping.mapping.name == mapping_name_2
|
||||
- create_mapping.mapping.rules | length == 1
|
||||
@@ -187,53 +169,37 @@
|
||||
openstack.cloud.federation_mapping_info:
|
||||
name: '{{ mapping_name_2 }}'
|
||||
register: mapping_info
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- mapping_info is successful
|
||||
- '"mappings" in mapping_info'
|
||||
- mapping_info.mappings | length == 1
|
||||
- '"id" in mapping_0'
|
||||
- '"name" in mapping_0'
|
||||
- '"rules" in mapping_0'
|
||||
- mapping_0.id == mapping_name_2
|
||||
- mapping_0.name == mapping_name_2
|
||||
- mapping_0.rules | length == 1
|
||||
vars:
|
||||
mapping_0: '{{ mapping_info.mappings[0] }}'
|
||||
- mapping_info.mappings[0].id == mapping_name_2
|
||||
- mapping_info.mappings[0].name == mapping_name_2
|
||||
- mapping_info.mappings[0].rules | length == 1
|
||||
|
||||
- name: 'Fetch mapping info - without name'
|
||||
openstack.cloud.federation_mapping_info: {}
|
||||
register: mapping_info
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- mapping_info is successful
|
||||
- '"mappings" in mapping_info'
|
||||
# In CI we generally have a clean slate, but this might
|
||||
# not be true for everyone...
|
||||
- mapping_info.mappings | length >= 2
|
||||
- '"id" in mapping_0'
|
||||
- '"name" in mapping_0'
|
||||
- '"rules" in mapping_0'
|
||||
- '"id" in mapping_1'
|
||||
- '"name" in mapping_1'
|
||||
- '"rules" in mapping_1'
|
||||
- mapping_name in (mapping_info.mappings | map(attribute='id'))
|
||||
- mapping_name in (mapping_info.mappings | map(attribute='name'))
|
||||
- mapping_name_2 in (mapping_info.mappings | map(attribute='id'))
|
||||
- mapping_name_2 in (mapping_info.mappings | map(attribute='name'))
|
||||
vars:
|
||||
mapping_0: '{{ mapping_info.mappings[0] }}'
|
||||
mapping_1: '{{ mapping_info.mappings[1] }}'
|
||||
|
||||
- name: 'Delete mapping - CHECK_MODE'
|
||||
openstack.cloud.federation_mapping:
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name }}'
|
||||
register: delete_mapping
|
||||
check_mode: yes
|
||||
check_mode: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- delete_mapping is successful
|
||||
- delete_mapping is changed
|
||||
|
||||
- name: 'Delete mapping'
|
||||
@@ -241,9 +207,9 @@
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name }}'
|
||||
register: delete_mapping
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- delete_mapping is successful
|
||||
- delete_mapping is changed
|
||||
|
||||
- name: 'Delete mapping (retry - no change) - CHECK_MODE'
|
||||
@@ -251,10 +217,10 @@
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name }}'
|
||||
register: delete_mapping
|
||||
check_mode: yes
|
||||
check_mode: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- delete_mapping is successful
|
||||
- delete_mapping is not changed
|
||||
|
||||
- name: 'Delete mapping (retry - no change) '
|
||||
@@ -262,28 +228,28 @@
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name }}'
|
||||
register: delete_mapping
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- delete_mapping is successful
|
||||
- delete_mapping is not changed
|
||||
|
||||
- name: 'Fetch mapping info after deletion'
|
||||
openstack.cloud.federation_mapping_info:
|
||||
name: '{{ mapping_name }}'
|
||||
register: mapping_info
|
||||
ignore_errors: True
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- mapping_info is failed
|
||||
- mapping_info.mappings | length == 0
|
||||
|
||||
- name: 'Delete second mapping'
|
||||
openstack.cloud.federation_mapping:
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name_2 }}'
|
||||
register: delete_mapping
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- delete_mapping is successful
|
||||
- delete_mapping is changed
|
||||
|
||||
always:
|
||||
@@ -291,10 +257,10 @@
|
||||
openstack.cloud.federation_mapping:
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name }}'
|
||||
ignore_errors: yes
|
||||
ignore_errors: true
|
||||
|
||||
- name: 'Delete second mapping'
|
||||
openstack.cloud.federation_mapping:
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name_2 }}'
|
||||
ignore_errors: yes
|
||||
ignore_errors: true
|
||||
21
ci/roles/floating_ip/defaults/main.yml
Normal file
21
ci/roles/floating_ip/defaults/main.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
expected_fields:
|
||||
- created_at
|
||||
- description
|
||||
- dns_domain
|
||||
- dns_name
|
||||
- fixed_ip_address
|
||||
- floating_ip_address
|
||||
- floating_network_id
|
||||
- id
|
||||
- name
|
||||
- port_details
|
||||
- port_id
|
||||
- project_id
|
||||
- qos_policy_id
|
||||
- revision_number
|
||||
- router_id
|
||||
- status
|
||||
- subnet_id
|
||||
- tags
|
||||
- updated_at
|
||||
533
ci/roles/floating_ip/tasks/main.yml
Normal file
533
ci/roles/floating_ip/tasks/main.yml
Normal file
@@ -0,0 +1,533 @@
|
||||
---
|
||||
- name: List all images
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: images
|
||||
|
||||
- name: Identify CirrOS image name
|
||||
set_fact:
|
||||
image_name: "{{ images.images|community.general.json_query(query)|first }}"
|
||||
vars:
|
||||
query: "[?starts_with(name, 'cirros')].name"
|
||||
|
||||
- name: Gather information about public network
|
||||
openstack.cloud.networks_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: public
|
||||
register: public_network
|
||||
|
||||
- name: Assert that public network exists
|
||||
assert:
|
||||
that: public_network.networks|length == 1
|
||||
|
||||
- name: Create external network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_external
|
||||
external: true
|
||||
|
||||
- name: Create external subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
network_name: ansible_external
|
||||
name: ansible_external_subnet
|
||||
cidr: 10.6.6.0/24
|
||||
|
||||
- name: Create external port 1
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_external_port1
|
||||
network: ansible_external
|
||||
fixed_ips:
|
||||
- ip_address: 10.6.6.50
|
||||
|
||||
- name: Create external port 2
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_external_port2
|
||||
network: ansible_external
|
||||
fixed_ips:
|
||||
- ip_address: 10.6.6.51
|
||||
|
||||
- name: Create internal network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_internal
|
||||
external: false
|
||||
|
||||
- name: Create internal subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
network_name: ansible_internal
|
||||
name: ansible_internal_subnet
|
||||
cidr: 10.7.7.0/24
|
||||
|
||||
- name: Create internal port 1
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_internal_port1
|
||||
network: ansible_internal
|
||||
fixed_ips:
|
||||
- ip_address: 10.7.7.100
|
||||
register: port1
|
||||
|
||||
- name: Create internal port 2
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_internal_port2
|
||||
network: ansible_internal
|
||||
fixed_ips:
|
||||
- ip_address: 10.7.7.101
|
||||
register: port2
|
||||
|
||||
- name: Create internal port 3
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_internal_port3
|
||||
network: ansible_internal
|
||||
fixed_ips:
|
||||
- ip_address: 10.7.7.102
|
||||
register: port3
|
||||
|
||||
- name: Create router 1
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_router1
|
||||
network: ansible_external
|
||||
external_fixed_ips:
|
||||
- subnet: ansible_external_subnet
|
||||
ip: 10.6.6.10
|
||||
interfaces:
|
||||
- net: ansible_internal
|
||||
subnet: ansible_internal_subnet
|
||||
portip: 10.7.7.1
|
||||
|
||||
# Router 2 is required for the simplest, first test that assigns a new floating IP to server
|
||||
# from first available external network or nova pool which is DevStack's public network
|
||||
- name: Create router 2
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_router2
|
||||
network: public
|
||||
interfaces:
|
||||
- net: ansible_internal
|
||||
subnet: ansible_internal_subnet
|
||||
portip: 10.7.7.10
|
||||
|
||||
- name: Get all floating ips
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: fips
|
||||
|
||||
- name: Check if public network has any floating ips
|
||||
set_fact:
|
||||
public_network_had_fips: "{{ fips.floating_ips|
|
||||
selectattr('floating_network_id', '==', public_network.networks.0.id)|
|
||||
list|length > 0 }}"
|
||||
|
||||
# TODO: Replace with appropriate Ansible module once available
|
||||
- name: Create a floating ip on public network (required for simplest, first floating ip test)
|
||||
command: openstack --os-cloud={{ cloud }} floating ip create public
|
||||
when: not public_network_had_fips
|
||||
|
||||
# TODO: Replace with appropriate Ansible module once available
|
||||
- name: Create floating ip 1 on external network
|
||||
command: >
|
||||
openstack --os-cloud={{ cloud }} floating ip create
|
||||
--subnet ansible_external_subnet
|
||||
--floating-ip-address 10.6.6.150
|
||||
ansible_external
|
||||
when: fips.floating_ips|length == 0 or
|
||||
"10.6.6.150" not in fips.floating_ips|map(attribute="floating_ip_address")|list
|
||||
|
||||
- name: Create server 1 with one nic
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_server1
|
||||
image: "{{ image_name }}"
|
||||
flavor: m1.tiny
|
||||
nics:
|
||||
# one nic only else simple, first floating ip test does not work
|
||||
- port-name: ansible_internal_port1
|
||||
auto_ip: false
|
||||
wait: true
|
||||
register: server1
|
||||
|
||||
- name: Get server 1 ports
|
||||
openstack.cloud.port_info:
|
||||
cloud: "{{ cloud }}"
|
||||
filters:
|
||||
device_id: "{{ server1.server.id }}"
|
||||
register: server1_ports
|
||||
|
||||
- name: Assert one fixed ip on server 1
|
||||
# If this assertion fails because server has an public ipv4 address (public_v4) then make sure
|
||||
# that no floating ip on public network is associated with "10.7.7.100" before running this role
|
||||
assert:
|
||||
that:
|
||||
- server1_ports.ports|length == 1
|
||||
- server1_ports.ports|sum(attribute='fixed_ips', start=[])|map(attribute='ip_address')|sort|list ==
|
||||
["10.7.7.100"]
|
||||
|
||||
- name: Create server 2 with two nics
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_server2
|
||||
image: "{{ image_name }}"
|
||||
flavor: m1.tiny
|
||||
nics:
|
||||
- port-name: ansible_internal_port2
|
||||
- port-name: ansible_internal_port3
|
||||
auto_ip: false
|
||||
wait: true
|
||||
register: server2
|
||||
|
||||
- name: Get server 2 ports
|
||||
openstack.cloud.port_info:
|
||||
cloud: "{{ cloud }}"
|
||||
filters:
|
||||
device_id: "{{ server2.server.id }}"
|
||||
register: server2_ports
|
||||
|
||||
- name: Assert two fixed ips on server 2
|
||||
assert:
|
||||
that:
|
||||
- server2_ports.ports|length == 2
|
||||
- server2_ports.ports|sum(attribute='fixed_ips', start=[])|map(attribute='ip_address')|sort|list ==
|
||||
["10.7.7.101", "10.7.7.102"]
|
||||
|
||||
- name: Assign new floating IP to server from first available external network or nova pool
|
||||
openstack.cloud.floating_ip:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
server: ansible_server1
|
||||
wait: true
|
||||
|
||||
- name: Get floating ip attached to server 1
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
port: "{{ port1.port.id }}"
|
||||
register: server1_fips
|
||||
# openstacksdk has issues with waiting hence we simply retry
|
||||
retries: 10
|
||||
delay: 3
|
||||
until: server1_fips.floating_ips|length == 1
|
||||
|
||||
- name: Assert fixed ip and floating ip attached to server 1
|
||||
assert:
|
||||
that:
|
||||
- server1_ports.ports|length == 1
|
||||
- server1_ports.ports|sum(attribute='fixed_ips', start=[])|map(attribute='ip_address')|sort|list ==
|
||||
["10.7.7.100"]
|
||||
- server1_fips.floating_ips|length == 1
|
||||
- server1_fips.floating_ips|map(attribute='fixed_ip_address')|sort|list ==
|
||||
["10.7.7.100"]
|
||||
|
||||
- name: Assert return values of floating_ip_info module
|
||||
assert:
|
||||
that:
|
||||
- server1_fips is success
|
||||
- server1_fips is not changed
|
||||
- server1_fips.floating_ips|length > 0
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(server1_fips.floating_ips[0].keys())|length == 0
|
||||
|
||||
- name: Assign floating ip to server 1 again
|
||||
openstack.cloud.floating_ip:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
server: ansible_server1
|
||||
wait: true
|
||||
register: floating_ip
|
||||
|
||||
- name: Assert floating ip on server 1 has not changed
|
||||
assert:
|
||||
that: floating_ip is not changed
|
||||
|
||||
- name: Assert return values of floating_ip module
|
||||
assert:
|
||||
that:
|
||||
- floating_ip.floating_ip|length > 0
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(floating_ip.floating_ip.keys())|length == 0
|
||||
|
||||
- name: Detach floating ip from server 1
|
||||
openstack.cloud.floating_ip:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
server: ansible_server1
|
||||
network: public
|
||||
floating_ip_address: "{{ server1_fips.floating_ips.0.floating_ip_address }}"
|
||||
|
||||
- name: Wait until floating ip is detached from server 1
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
port: "{{ port1.port.id }}"
|
||||
register: server1_fips
|
||||
# When detaching a floating ip from an instance there might be a delay until it is not listed anymore
|
||||
retries: 10
|
||||
delay: 3
|
||||
until: server1_fips.floating_ips|length == 0
|
||||
|
||||
- name: Find all floating ips for debugging
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: fips
|
||||
|
||||
- name: Print all floating ips for debugging
|
||||
debug: var=fips
|
||||
|
||||
- name: Find all servers for debugging
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: servers
|
||||
|
||||
- name: Print all servers for debugging
|
||||
debug: var=servers
|
||||
|
||||
- name: Assign floating ip to server 2
|
||||
openstack.cloud.floating_ip:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
reuse: false # else fixed_address will be ignored
|
||||
server: ansible_server2
|
||||
network: public
|
||||
fixed_address: "{{ port2.port.fixed_ips[0].ip_address }}"
|
||||
wait: true
|
||||
register: server2_fip
|
||||
|
||||
- name: Assert floating ip attached to server 2
|
||||
assert:
|
||||
that:
|
||||
- server2_fip.floating_ip|length > 0
|
||||
|
||||
- name: Find all floating ips for debugging
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: fips
|
||||
|
||||
- name: Print all floating ips for debugging
|
||||
debug: var=fips
|
||||
|
||||
- name: Find all servers for debugging
|
||||
openstack.cloud.server_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: servers
|
||||
|
||||
- name: Print all servers for debugging
|
||||
debug: var=servers
|
||||
|
||||
- name: Get floating ip attached to server 2
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
port: "{{ port2.port.id }}"
|
||||
register: server2_fips
|
||||
|
||||
- name: Assert floating ip attached to server 2
|
||||
assert:
|
||||
that:
|
||||
- server2_fips.floating_ips|length == 1
|
||||
- server2_fips.floating_ips|map(attribute='fixed_ip_address')|sort|list ==
|
||||
["10.7.7.101"]
|
||||
|
||||
- name: Assign a second, specific floating ip to server 2
|
||||
openstack.cloud.floating_ip:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
reuse: false # else fixed_address will be ignored
|
||||
server: ansible_server2
|
||||
network: ansible_external
|
||||
fixed_address: "{{ port3.port.fixed_ips[0].ip_address }}"
|
||||
floating_ip_address: "10.6.6.150"
|
||||
wait: false # does not work anyway and causes issues in local testing
|
||||
|
||||
- name: Get floating ip attached to server 2
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
port: "{{ port3.port.id }}"
|
||||
register: server2_fips
|
||||
# We cannot wait for second floating ip to be attached because OpenStackSDK checks only for first floating ip
|
||||
# Ref.: https://github.com/openstack/openstacksdk/blob/e0372b72af8c5f471fc17e53434d7a814ca958bd/openstack/cloud/_floating_ip.py#L733
|
||||
retries: 10
|
||||
delay: 3
|
||||
until: server2_fips.floating_ips|length == 1
|
||||
|
||||
- name: Assert second floating ip attached to server 2
|
||||
assert:
|
||||
that:
|
||||
- server2_fips.floating_ips|length == 1
|
||||
- server2_fips.floating_ips|map(attribute='fixed_ip_address')|sort|list ==
|
||||
["10.7.7.102"]
|
||||
|
||||
- name: Detach second floating ip from server 2
|
||||
openstack.cloud.floating_ip:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
server: ansible_server2
|
||||
network: ansible_external
|
||||
floating_ip_address: "10.6.6.150"
|
||||
|
||||
- name: Wait until second floating ip is detached from server 2
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
port: "{{ port3.port.id }}"
|
||||
register: server2_fips
|
||||
# When detaching a floating ip from an instance there might be a delay until it is not listed anymore
|
||||
retries: 10
|
||||
delay: 3
|
||||
until: server2_fips.floating_ips|length == 0
|
||||
|
||||
- name: Get first floating ip attached to server 2
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
port: "{{ port2.port.id }}"
|
||||
register: server2_fips
|
||||
|
||||
- name: Detach remaining floating ip from server 2
|
||||
openstack.cloud.floating_ip:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
server: ansible_server2
|
||||
network: public
|
||||
floating_ip_address: "{{ server2_fips.floating_ips.0.floating_ip_address }}"
|
||||
|
||||
- name: Wait until first floating ip is detached from server 2
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
port: "{{ port2.port.id }}"
|
||||
register: server2_fips
|
||||
# When detaching a floating ip from an instance there might be a delay until it is not listed anymore
|
||||
retries: 10
|
||||
delay: 3
|
||||
until: server2_fips.floating_ips|length == 0
|
||||
|
||||
- name: Delete server with two nics
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_server2
|
||||
wait: true
|
||||
|
||||
- name: Delete server with one nic
|
||||
openstack.cloud.server:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_server1
|
||||
wait: true
|
||||
|
||||
- name: Get all floating ips
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: fips
|
||||
|
||||
# TODO: Replace with appropriate Ansible module once available
|
||||
- name: Delete floating ip on public network if we created it
|
||||
when: not public_network_had_fips
|
||||
command: >
|
||||
openstack --os-cloud={{ cloud }} floating ip delete
|
||||
{{ fips.floating_ips|selectattr('floating_network_id', '==', public_network.networks.0.id)|
|
||||
map(attribute="floating_ip_address")|list|join(' ') }}
|
||||
|
||||
# TODO: Replace with appropriate Ansible module once available
|
||||
- name: Delete floating ip 1
|
||||
command: openstack --os-cloud={{ cloud }} floating ip delete 10.6.6.150
|
||||
when: fips.floating_ips|length > 0 and "10.6.6.150" in fips.floating_ips|map(attribute="floating_ip_address")|list
|
||||
|
||||
- name: Get remaining floating ips on external network
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
floating_network: ansible_external
|
||||
register: fips
|
||||
|
||||
# TODO: Replace with appropriate Ansible module once available
|
||||
# The first, simple floating ip test might have allocated a floating ip on the external network.
|
||||
# This floating ip must be removed before external network can be deleted.
|
||||
- name: Delete remaining floating ips on external network
|
||||
when: fips.floating_ips|length > 0
|
||||
command: >
|
||||
openstack --os-cloud={{ cloud }} floating ip delete
|
||||
{{ fips.floating_ips|map(attribute="floating_ip_address")|list|join(' ') }}
|
||||
|
||||
# Remove routers after floating ips have been detached and disassociated else removal fails with
|
||||
# Error detaching interface from router ***: Client Error for url: ***,
|
||||
# Router interface for subnet *** on router *** cannot be deleted,
|
||||
# as it is required by one or more floating IPs.
|
||||
|
||||
- name: Delete router 2
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_router2
|
||||
|
||||
- name: Delete router 1
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_router1
|
||||
|
||||
- name: Delete internal port 3
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_internal_port3
|
||||
|
||||
- name: Delete internal port 2
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_internal_port2
|
||||
|
||||
- name: Delete internal port 1
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_internal_port1
|
||||
|
||||
- name: Delete internal subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_internal_subnet
|
||||
|
||||
- name: Delete internal network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_internal
|
||||
|
||||
- name: Delete external port 2
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_external_port2
|
||||
|
||||
- name: Delete external port 1
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_external_port1
|
||||
|
||||
- name: Delete external subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_external_subnet
|
||||
|
||||
- name: Delete external network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_external
|
||||
@@ -1 +0,0 @@
|
||||
group_name: ansible_group
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
- name: Create group
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ group_name }}"
|
||||
|
||||
- name: Update group
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ group_name }}"
|
||||
description: "updated description"
|
||||
|
||||
- name: Delete group
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ group_name }}"
|
||||
68
ci/roles/group_assignment/tasks/main.yml
Normal file
68
ci/roles/group_assignment/tasks/main.yml
Normal file
@@ -0,0 +1,68 @@
|
||||
---
|
||||
- name: Create user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
password: secret
|
||||
email: ansible.user@nowhere.net
|
||||
domain: default
|
||||
default_project: demo
|
||||
|
||||
- name: Assign user to nonadmins group
|
||||
openstack.cloud.group_assignment:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
user: ansible_user
|
||||
group: nonadmins
|
||||
register: group_assignment
|
||||
|
||||
- name: Assert group assignment
|
||||
assert:
|
||||
that:
|
||||
- group_assignment is changed
|
||||
|
||||
- name: Assign user to nonadmins group again
|
||||
openstack.cloud.group_assignment:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
user: ansible_user
|
||||
group: nonadmins
|
||||
register: group_assignment
|
||||
|
||||
- name: Assert group assignment
|
||||
assert:
|
||||
that:
|
||||
- group_assignment is not changed
|
||||
|
||||
- name: Remove user from nonadmins group
|
||||
openstack.cloud.group_assignment:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
user: ansible_user
|
||||
group: nonadmins
|
||||
register: group_assignment
|
||||
|
||||
- name: Assert group assignment
|
||||
assert:
|
||||
that:
|
||||
- group_assignment is changed
|
||||
|
||||
- name: Remove user from nonadmins group again
|
||||
openstack.cloud.group_assignment:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
user: ansible_user
|
||||
group: nonadmins
|
||||
register: group_assignment
|
||||
|
||||
- name: Assert group assignment
|
||||
assert:
|
||||
that:
|
||||
- group_assignment is not changed
|
||||
|
||||
- name: Delete user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_user
|
||||
11
ci/roles/host_aggregate/defaults/main.yml
Normal file
11
ci/roles/host_aggregate/defaults/main.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
expected_fields:
|
||||
- availability_zone
|
||||
- created_at
|
||||
- deleted_at
|
||||
- hosts
|
||||
- id
|
||||
- is_deleted
|
||||
- metadata
|
||||
- name
|
||||
- updated_at
|
||||
- uuid
|
||||
99
ci/roles/host_aggregate/tasks/main.yml
Normal file
99
ci/roles/host_aggregate/tasks/main.yml
Normal file
@@ -0,0 +1,99 @@
|
||||
---
|
||||
- name: ensure aggregate doesn't exist before tests
|
||||
openstack.cloud.host_aggregate:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: test_aggregate
|
||||
register: aggregate
|
||||
|
||||
- block:
|
||||
- name: create aggregate
|
||||
openstack.cloud.host_aggregate:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: test_aggregate
|
||||
hosts:
|
||||
- "{{ ansible_hostname }}"
|
||||
register: aggregate
|
||||
|
||||
- name: assert aggregate is changed
|
||||
assert:
|
||||
that: aggregate is changed
|
||||
|
||||
- name: assert aggregate fields
|
||||
assert:
|
||||
that: item in aggregate.aggregate
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- block:
|
||||
- name: recreate aggregate
|
||||
openstack.cloud.host_aggregate:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: test_aggregate
|
||||
hosts:
|
||||
- "{{ ansible_hostname }}"
|
||||
register: aggregate
|
||||
|
||||
- name: assert aggregate is not changed
|
||||
assert:
|
||||
that: aggregate is not changed
|
||||
|
||||
- name: assert aggregate fields
|
||||
assert:
|
||||
that: item in aggregate.aggregate
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- block:
|
||||
- name: update aggregate
|
||||
openstack.cloud.host_aggregate:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: test_aggregate
|
||||
metadata:
|
||||
ssd: "true"
|
||||
hosts:
|
||||
- "{{ ansible_hostname }}"
|
||||
register: aggregate
|
||||
|
||||
- name: assert aggregate is changed
|
||||
assert:
|
||||
that: aggregate is changed
|
||||
|
||||
- name: assert aggregate fields
|
||||
assert:
|
||||
that: item in aggregate.aggregate
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- block:
|
||||
- name: purge hosts
|
||||
openstack.cloud.host_aggregate:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: test_aggregate
|
||||
hosts: []
|
||||
purge_hosts: true
|
||||
register: aggregate
|
||||
|
||||
- name: assert hosts were purged
|
||||
assert:
|
||||
that:
|
||||
- aggregate is changed
|
||||
- aggregate.aggregate.hosts | length == 0
|
||||
|
||||
- name: assert aggregate fields
|
||||
assert:
|
||||
that: item in aggregate.aggregate
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- block:
|
||||
- name: delete aggregate
|
||||
openstack.cloud.host_aggregate:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: test_aggregate
|
||||
register: aggregate
|
||||
|
||||
- name: assert aggregate is changed
|
||||
assert:
|
||||
that: aggregate is changed
|
||||
6
ci/roles/identity_domain/defaults/main.yml
Normal file
6
ci/roles/identity_domain/defaults/main.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
expected_fields:
|
||||
- description
|
||||
- id
|
||||
- is_enabled
|
||||
- name
|
||||
- links
|
||||
123
ci/roles/identity_domain/tasks/main.yml
Normal file
123
ci/roles/identity_domain/tasks/main.yml
Normal file
@@ -0,0 +1,123 @@
|
||||
---
|
||||
- name: Create keystone domain
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_domain
|
||||
description: "test description"
|
||||
register: domain
|
||||
|
||||
- name: Assert return values of identity_domain module
|
||||
assert:
|
||||
that:
|
||||
- domain.domain.name == 'ansible_domain'
|
||||
- domain.domain.description == "test description"
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(domain.domain.keys())|length == 0
|
||||
|
||||
- name: Update keystone domain
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_domain
|
||||
description: "updated description"
|
||||
register: domain
|
||||
|
||||
- name: Assert updated domain
|
||||
assert:
|
||||
that:
|
||||
- domain.domain.description == "updated description"
|
||||
|
||||
- name: Fetch domains
|
||||
openstack.cloud.identity_domain_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: domains
|
||||
|
||||
- name: Assert return values of identity_domain_info module
|
||||
assert:
|
||||
that:
|
||||
- domains.domains | length > 0
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(domains.domains.0.keys())|length == 0
|
||||
|
||||
- name: Fetch domain by name
|
||||
openstack.cloud.identity_domain_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_domain
|
||||
register: domains
|
||||
|
||||
- name: Assert named domain
|
||||
assert:
|
||||
that:
|
||||
- domains.domains | length == 1
|
||||
|
||||
- name: Create disabled domain
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_domain_disabled
|
||||
is_enabled: false
|
||||
description: "test description"
|
||||
register: domain
|
||||
|
||||
- name: Fetch all domains
|
||||
openstack.cloud.identity_domain_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: domains
|
||||
|
||||
- name: Assert both ansible domains exist
|
||||
assert:
|
||||
that:
|
||||
- domains.domains | length >= 2
|
||||
|
||||
- name: Fetch disabled domains
|
||||
openstack.cloud.identity_domain_info:
|
||||
cloud: "{{ cloud }}"
|
||||
filters:
|
||||
is_enabled: false
|
||||
register: domains
|
||||
|
||||
- name: Assert at least one disabled domain exists
|
||||
assert:
|
||||
that:
|
||||
- domains.domains | length >= 1
|
||||
|
||||
- name: Fetch enabled domains
|
||||
openstack.cloud.identity_domain_info:
|
||||
cloud: "{{ cloud }}"
|
||||
filters:
|
||||
is_enabled: true
|
||||
register: domains
|
||||
|
||||
- name: Assert returned value
|
||||
assert:
|
||||
that:
|
||||
- item.is_enabled
|
||||
loop: "{{ domains.domains }}"
|
||||
|
||||
- name: Delete disabled domain
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_domain_disabled
|
||||
|
||||
- name: Assert domain is disabled
|
||||
assert:
|
||||
that:
|
||||
- not domain.domain.is_enabled
|
||||
|
||||
- name: Delete domain
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_domain
|
||||
|
||||
- name: Get non-existing domain
|
||||
openstack.cloud.identity_domain_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_domain
|
||||
register: domains
|
||||
|
||||
- name: Assert no results returned
|
||||
assert:
|
||||
that:
|
||||
- domains.domains | length == 0
|
||||
5
ci/roles/identity_group/defaults/main.yml
Normal file
5
ci/roles/identity_group/defaults/main.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
expected_fields:
|
||||
- description
|
||||
- domain_id
|
||||
- id
|
||||
- name
|
||||
220
ci/roles/identity_group/tasks/main.yml
Normal file
220
ci/roles/identity_group/tasks/main.yml
Normal file
@@ -0,0 +1,220 @@
|
||||
---
|
||||
- name: Create group
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
description: "ansible group"
|
||||
name: ansible_group
|
||||
register: group
|
||||
|
||||
- name: Assert return values of identity_group module
|
||||
assert:
|
||||
that:
|
||||
- group.group.name == 'ansible_group'
|
||||
- group.group.description == "ansible group"
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(group.group.keys())|length == 0
|
||||
|
||||
- name: Create group again
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
description: "ansible group"
|
||||
name: ansible_group
|
||||
register: group
|
||||
|
||||
- name: Assert group did not change
|
||||
assert:
|
||||
that:
|
||||
- group is not changed
|
||||
|
||||
- name: Update group
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_group
|
||||
description: "updated description"
|
||||
register: group
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- group is changed
|
||||
- group.group.description == "updated description"
|
||||
|
||||
- name: Fetch all groups
|
||||
openstack.cloud.identity_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: _groups
|
||||
|
||||
- name: Assert return values of identity_group_info module
|
||||
assert:
|
||||
that:
|
||||
- _groups.groups | length > 0
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(_groups.groups.0.keys())|length == 0
|
||||
|
||||
- name: List group with filters
|
||||
openstack.cloud.identity_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
domain: default
|
||||
filters:
|
||||
name: ansible_group
|
||||
register: _groups
|
||||
|
||||
- name: Assert group with filters
|
||||
assert:
|
||||
that:
|
||||
- _groups.groups | length == 1
|
||||
- _groups.groups.0.id == group.group.id
|
||||
|
||||
- name: Create domain
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_domain
|
||||
register: domain
|
||||
|
||||
- name: Create group in specific domain
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_group
|
||||
domain_id: "{{ domain.domain.id }}"
|
||||
register: group
|
||||
|
||||
- name: Assert results
|
||||
assert:
|
||||
that:
|
||||
- group is changed
|
||||
- group.group.domain_id == domain.domain.id
|
||||
|
||||
- name: List group by group name
|
||||
openstack.cloud.identity_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_group
|
||||
register: _groups
|
||||
|
||||
- name: Assert groups by group name
|
||||
assert:
|
||||
that:
|
||||
- _groups.groups | length == 2
|
||||
|
||||
- name: List group by domain_id
|
||||
openstack.cloud.identity_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
domain: ansible_domain
|
||||
register: _groups
|
||||
|
||||
- name: Assert groups by domain_id
|
||||
assert:
|
||||
that:
|
||||
- _groups.groups | length == 1
|
||||
- _groups.groups.0.id == group.group.id
|
||||
- _groups.groups.0.domain_id == domain.domain.id
|
||||
|
||||
- name: List group by domain_id and group name
|
||||
openstack.cloud.identity_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
domain: ansible_domain
|
||||
name: ansible_group
|
||||
register: _groups
|
||||
|
||||
- name: Assert groups by domain_id and group name
|
||||
assert:
|
||||
that:
|
||||
- _groups.groups | length == 1
|
||||
- _groups.groups.0.id == group.group.id
|
||||
|
||||
- name: Create group in specific domain again
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_group
|
||||
domain_id: "{{ domain.domain.id }}"
|
||||
register: group
|
||||
|
||||
- name: Assert not changed
|
||||
assert:
|
||||
that:
|
||||
- group is not changed
|
||||
|
||||
- name: Delete ambiguous group
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_group
|
||||
ignore_errors: true
|
||||
register: group
|
||||
|
||||
- name: Assert failed
|
||||
assert:
|
||||
that:
|
||||
- group is failed
|
||||
|
||||
- name: Delete group in specific domain
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_group
|
||||
domain_id: "{{ domain.domain.id }}"
|
||||
register: group
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- group is changed
|
||||
|
||||
- name: Delete group in specific domain again
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_group
|
||||
domain_id: "{{ domain.domain.id }}"
|
||||
register: group
|
||||
|
||||
- name: Assert not changed
|
||||
assert:
|
||||
that:
|
||||
- group is not changed
|
||||
|
||||
- name: Delete domain
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_domain
|
||||
|
||||
- name: Delete group
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_group
|
||||
register: group
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- group is changed
|
||||
|
||||
- name: Delete group again
|
||||
openstack.cloud.identity_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_group
|
||||
register: group
|
||||
|
||||
- name: Assert not changed
|
||||
assert:
|
||||
that:
|
||||
- group is not changed
|
||||
|
||||
- name: List group
|
||||
openstack.cloud.identity_group_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_group
|
||||
register: _groups
|
||||
|
||||
- name: Assert group does not exist
|
||||
assert:
|
||||
that:
|
||||
- _groups.groups | length == 0
|
||||
6
ci/roles/identity_role/defaults/main.yml
Normal file
6
ci/roles/identity_role/defaults/main.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
expected_fields:
|
||||
- description
|
||||
- domain_id
|
||||
- id
|
||||
- links
|
||||
- name
|
||||
88
ci/roles/identity_role/tasks/main.yml
Normal file
88
ci/roles/identity_role/tasks/main.yml
Normal file
@@ -0,0 +1,88 @@
|
||||
---
|
||||
- name: Create identity role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_role
|
||||
description: "ansible role"
|
||||
register: role
|
||||
|
||||
- name: Assert return values of identity_role module
|
||||
assert:
|
||||
that:
|
||||
- role.role.name == 'ansible_role'
|
||||
- role.role.description == "ansible role"
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(role.role.keys())|length == 0
|
||||
|
||||
- name: Try to get role
|
||||
openstack.cloud.identity_role_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_role
|
||||
register: roles
|
||||
|
||||
- name: Assert role found
|
||||
assert:
|
||||
that:
|
||||
- roles.roles | length == 1
|
||||
- roles.roles.0.name == 'ansible_role'
|
||||
|
||||
- name: Fetch all roles
|
||||
openstack.cloud.identity_role_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: roles
|
||||
|
||||
- name: Assert return values of identity_role_info module
|
||||
assert:
|
||||
that:
|
||||
- roles.roles | length > 0
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(roles.roles.0.keys())|length == 0
|
||||
|
||||
- name: Create identity role again
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_role
|
||||
description: "ansible role"
|
||||
register: role
|
||||
|
||||
- name: Assert role did not change
|
||||
assert:
|
||||
that:
|
||||
- role is not changed
|
||||
|
||||
- name: Delete identity role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_role
|
||||
register: role
|
||||
|
||||
- name: Assert role changed
|
||||
assert:
|
||||
that:
|
||||
- role is changed
|
||||
|
||||
- name: Try to get role
|
||||
openstack.cloud.identity_role_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_role
|
||||
register: roles
|
||||
|
||||
- name: Assert no role found
|
||||
assert:
|
||||
that:
|
||||
- roles.roles | length == 0
|
||||
|
||||
- name: Delete role again
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_role
|
||||
register: role
|
||||
|
||||
- name: Assert role did not change
|
||||
assert:
|
||||
that:
|
||||
- role is not changed
|
||||
11
ci/roles/identity_user/defaults/main.yml
Normal file
11
ci/roles/identity_user/defaults/main.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
expected_fields:
|
||||
- default_project_id
|
||||
- description
|
||||
- domain_id
|
||||
- email
|
||||
- id
|
||||
- is_enabled
|
||||
- links
|
||||
- name
|
||||
- password
|
||||
- password_expires_at
|
||||
218
ci/roles/identity_user/tasks/main.yml
Normal file
218
ci/roles/identity_user/tasks/main.yml
Normal file
@@ -0,0 +1,218 @@
|
||||
---
|
||||
- name: Create a user without a password
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
email: ansible.user@nowhere.net
|
||||
domain: default
|
||||
description: "ansible user"
|
||||
default_project: demo
|
||||
register: user
|
||||
|
||||
- name: Assert return values of identity_user module
|
||||
assert:
|
||||
that:
|
||||
- user.user.name == 'ansible_user'
|
||||
- user.user.description == 'ansible user'
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(user.user.keys())|length == 0
|
||||
|
||||
- name: Fail when update_password is always but no password specified
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
update_password: always
|
||||
email: ansible.user@nowhere.net
|
||||
domain: default
|
||||
default_project: demo
|
||||
register: user
|
||||
ignore_errors: true
|
||||
|
||||
- name: Assert that update failed
|
||||
assert:
|
||||
that:
|
||||
- user is failed
|
||||
- user.msg == "update_password is 'always' but password is missing"
|
||||
|
||||
- name: Delete user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_user
|
||||
|
||||
|
||||
- name: Create user with a password
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
password: secret
|
||||
email: ansible.user@nowhere.net
|
||||
update_password: on_create
|
||||
domain: default
|
||||
default_project: demo
|
||||
|
||||
- name: Create user with a password again
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
password: secret
|
||||
email: ansible.user@nowhere.net
|
||||
update_password: on_create
|
||||
domain: default
|
||||
default_project: demo
|
||||
register: user
|
||||
|
||||
- name: Assert user was not changed
|
||||
assert:
|
||||
that:
|
||||
- user is not changed
|
||||
|
||||
- name: Update user with password
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
password: secret2
|
||||
email: updated.ansible.user@nowhere.net
|
||||
register: user
|
||||
|
||||
- name: Ensure user was changed
|
||||
assert:
|
||||
that:
|
||||
- user is changed
|
||||
|
||||
- name: Update user without password and update_password set to always
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
update_password: always
|
||||
email: updated.ansible.user@nowhere.net
|
||||
register: user
|
||||
ignore_errors: true
|
||||
|
||||
- name: Assert user update failed
|
||||
assert:
|
||||
that:
|
||||
- user is failed
|
||||
- user.msg == "update_password is 'always' but password is missing"
|
||||
|
||||
- name: Ensure user with update_password set to on_create
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
update_password: on_create
|
||||
password: secret3
|
||||
email: updated.ansible.user@nowhere.net
|
||||
register: user
|
||||
|
||||
- name: Ensure user was not changed
|
||||
assert:
|
||||
that:
|
||||
- user is not changed
|
||||
|
||||
- name: Ensure user with update_password set to always
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user
|
||||
update_password: always
|
||||
password: secret3
|
||||
email: updated.ansible.user@nowhere.net
|
||||
register: user
|
||||
|
||||
- name: Ensure user was changed
|
||||
assert:
|
||||
that:
|
||||
- user is changed
|
||||
|
||||
- name: Create user without a password
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_user2
|
||||
password: secret
|
||||
email: ansible.user2@nowhere.net
|
||||
update_password: on_create
|
||||
domain: default
|
||||
default_project: demo
|
||||
register: user
|
||||
|
||||
- name: Fetch users
|
||||
openstack.cloud.identity_user_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: users
|
||||
|
||||
- name: Assert return values of identity_user_info module
|
||||
assert:
|
||||
that:
|
||||
- users.users | length > 0
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(users.users.0.keys())|length == 0
|
||||
|
||||
- name: Fetch user by name
|
||||
openstack.cloud.identity_user_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_user
|
||||
register: users
|
||||
|
||||
- name: Assert named user
|
||||
assert:
|
||||
that:
|
||||
- users.users | length == 1
|
||||
|
||||
- name: Delete user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_user2
|
||||
|
||||
- name: Delete user
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_user
|
||||
|
||||
- name: Ensure user was changed
|
||||
assert:
|
||||
that:
|
||||
- user is changed
|
||||
|
||||
- name: Delete user again
|
||||
openstack.cloud.identity_user:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_user
|
||||
register: user
|
||||
|
||||
- name: Ensure user was not changed
|
||||
assert:
|
||||
that:
|
||||
- user is not changed
|
||||
|
||||
- name: Fetch ansible_user
|
||||
openstack.cloud.identity_user_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_user
|
||||
register: users
|
||||
|
||||
- name: Assert ansible_user does not exist
|
||||
assert:
|
||||
that:
|
||||
- users.users | length == 0
|
||||
|
||||
- name: Fetch ansible_user2
|
||||
openstack.cloud.identity_user_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_user2
|
||||
register: users
|
||||
|
||||
- name: Assert ansible_user2 does not exist
|
||||
assert:
|
||||
that:
|
||||
- users.users | length == 0
|
||||
@@ -1 +1,65 @@
|
||||
image_name: ansible_image
|
||||
expected_fields:
|
||||
- architecture
|
||||
- checksum
|
||||
- container_format
|
||||
- created_at
|
||||
- direct_url
|
||||
- disk_format
|
||||
- file
|
||||
- has_auto_disk_config
|
||||
- hash_algo
|
||||
- hash_value
|
||||
- hw_cpu_cores
|
||||
- hw_cpu_policy
|
||||
- hw_cpu_sockets
|
||||
- hw_cpu_thread_policy
|
||||
- hw_cpu_threads
|
||||
- hw_disk_bus
|
||||
- hw_machine_type
|
||||
- hw_qemu_guest_agent
|
||||
- hw_rng_model
|
||||
- hw_scsi_model
|
||||
- hw_serial_port_count
|
||||
- hw_video_model
|
||||
- hw_video_ram
|
||||
- hw_vif_model
|
||||
- hw_watchdog_action
|
||||
- hypervisor_type
|
||||
- id
|
||||
- instance_type_rxtx_factor
|
||||
- instance_uuid
|
||||
- is_hidden
|
||||
- is_hw_boot_menu_enabled
|
||||
- is_hw_vif_multiqueue_enabled
|
||||
- is_protected
|
||||
- kernel_id
|
||||
- locations
|
||||
- metadata
|
||||
- min_disk
|
||||
- min_ram
|
||||
- name
|
||||
- needs_config_drive
|
||||
- needs_secure_boot
|
||||
- os_admin_user
|
||||
- os_command_line
|
||||
- os_distro
|
||||
- os_require_quiesce
|
||||
- os_shutdown_timeout
|
||||
- os_type
|
||||
- os_version
|
||||
- owner
|
||||
- owner_id
|
||||
- properties
|
||||
- ramdisk_id
|
||||
- schema
|
||||
- size
|
||||
- status
|
||||
- store
|
||||
- tags
|
||||
- updated_at
|
||||
- url
|
||||
- virtual_size
|
||||
- visibility
|
||||
- vm_mode
|
||||
- vmware_adaptertype
|
||||
- vmware_ostype
|
||||
|
||||
@@ -1,54 +1,376 @@
|
||||
---
|
||||
- name: Create a test image file
|
||||
shell: mktemp
|
||||
register: tmp_file
|
||||
- name: Test images
|
||||
block:
|
||||
- name: List all images
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: images
|
||||
|
||||
- name: Fill test image file to 1MB
|
||||
shell: truncate -s 1048576 {{ tmp_file.stdout }}
|
||||
- name: Assert existence of CirrOS image
|
||||
assert:
|
||||
that:
|
||||
- images.images | length > 0
|
||||
|
||||
- name: Create raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ image_name }}"
|
||||
filename: "{{ tmp_file.stdout }}"
|
||||
disk_format: raw
|
||||
register: image
|
||||
- name: Ensure clean environment
|
||||
ansible.builtin.set_fact:
|
||||
tmp_file: !!null
|
||||
|
||||
- debug: var=image
|
||||
- name: Create a test image file
|
||||
ansible.builtin.tempfile:
|
||||
register: tmp_file
|
||||
|
||||
- name: Delete raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ image_name }}"
|
||||
- name: Fill test image file to 1MB
|
||||
community.general.filesize:
|
||||
path: '{{ tmp_file.path }}'
|
||||
size: 1M
|
||||
|
||||
- name: Create raw image (complex)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ image_name }}"
|
||||
filename: "{{ tmp_file.stdout }}"
|
||||
disk_format: raw
|
||||
is_public: True
|
||||
min_disk: 10
|
||||
min_ram: 1024
|
||||
kernel: cirros-vmlinuz
|
||||
ramdisk: cirros-initrd
|
||||
properties:
|
||||
cpu_arch: x86_64
|
||||
distro: ubuntu
|
||||
register: image
|
||||
- name: Calculating file checksum
|
||||
ansible.builtin.stat:
|
||||
path: "{{ tmp_file.path }}"
|
||||
checksum_algorithm: sha512
|
||||
get_checksum: true
|
||||
register: image_details
|
||||
|
||||
- debug: var=image
|
||||
- name: Ensure mock kernel and ramdisk images (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ item }}"
|
||||
filename: "{{ tmp_file.path }}"
|
||||
disk_format: raw
|
||||
loop:
|
||||
- cirros-vmlinuz
|
||||
- cirros-initrd
|
||||
|
||||
- name: Delete raw image (complex)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ image_name }}"
|
||||
- name: Create raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
filename: "{{ tmp_file.path }}"
|
||||
is_protected: true
|
||||
checksum: "{{ image_details.stat.checksum }}"
|
||||
disk_format: raw
|
||||
tags:
|
||||
- test
|
||||
- ansible
|
||||
register: image
|
||||
|
||||
- name: Delete test image file
|
||||
file:
|
||||
name: "{{ tmp_file.stdout }}"
|
||||
state: absent
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
|
||||
- name: Assert return values of image module
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
- image.image.name == 'ansible_image'
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(image.image.keys())|length == 0
|
||||
|
||||
- name: Get details of created image
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: ansible_image
|
||||
register: images
|
||||
|
||||
- name: Assert return values of image_info module
|
||||
assert:
|
||||
that:
|
||||
- images.images | length > 0
|
||||
- images.images.0.name == "ansible_image"
|
||||
- images.images.0.tags | sort == ['test', 'ansible'] | sort
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(images.images.0.keys())|length == 0
|
||||
|
||||
- name: Create raw image again (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
filename: "{{ tmp_file.path }}"
|
||||
is_protected: true
|
||||
disk_format: raw
|
||||
tags:
|
||||
- test
|
||||
- ansible
|
||||
register: image
|
||||
|
||||
- name: Assert not changed
|
||||
assert:
|
||||
that:
|
||||
- image is not changed
|
||||
|
||||
- name: Update is_protected on raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
is_protected: false
|
||||
register: image
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
- image.image.is_protected == false
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
|
||||
- name: Update visibility on raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
is_public: false
|
||||
register: image
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image.image.visibility == 'private'
|
||||
|
||||
- name: Update again visibility on raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
is_public: true
|
||||
register: image
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
- image.image.visibility == 'public'
|
||||
|
||||
- name: Define visibility on raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
visibility: shared
|
||||
register: image
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
- image.image.visibility == 'shared'
|
||||
|
||||
- name: Rename raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
id: "{{ image.image.id }}"
|
||||
name: 'ansible_image-changed'
|
||||
register: image
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
- image.image.name == 'ansible_image-changed'
|
||||
|
||||
- name: Deactivate raw image
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: inactive
|
||||
id: "{{ image.image.id }}"
|
||||
name: 'ansible_image-changed'
|
||||
register: image
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
- image.image.status == 'deactivated'
|
||||
|
||||
- name: Reactivate raw image
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
id: "{{ image.image.id }}"
|
||||
name: 'ansible_image-changed'
|
||||
register: image
|
||||
|
||||
- name: Assert changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
- image.image.status == 'active'
|
||||
|
||||
- name: Rename back raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
id: "{{ image.image.id }}"
|
||||
name: ansible_image
|
||||
register: image
|
||||
|
||||
- name: Delete raw image (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_image
|
||||
register: image
|
||||
|
||||
- name: assert image changed
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
|
||||
- name: Delete raw image again (defaults)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_image
|
||||
register: image
|
||||
|
||||
- name: assert image not changed
|
||||
assert:
|
||||
that:
|
||||
- image is not changed
|
||||
|
||||
- name: Create raw image (complex)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
filename: "{{ tmp_file.path }}"
|
||||
disk_format: raw
|
||||
is_public: True
|
||||
min_disk: 10
|
||||
min_ram: 1024
|
||||
# TODO(rcastillo): upload cirros-vmlinuz, cirros-initrd in test setup
|
||||
kernel: cirros-vmlinuz
|
||||
ramdisk: cirros-initrd
|
||||
properties:
|
||||
cpu_arch: x86_64
|
||||
distro: ubuntu
|
||||
register: image
|
||||
|
||||
- name: Assert visibility
|
||||
assert:
|
||||
that:
|
||||
- image.image.visibility == 'public'
|
||||
|
||||
- name: Delete raw image (complex)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_image
|
||||
|
||||
- name: Try to get details of deleted image
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: ansible_image
|
||||
register: images
|
||||
|
||||
- name: Verify image is deleted
|
||||
assert:
|
||||
that:
|
||||
- images.images | length == 0
|
||||
|
||||
- name: Create owner project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: Project owning test image
|
||||
domain: default
|
||||
is_enabled: True
|
||||
register: project
|
||||
|
||||
- name: Create raw image (owner by project name)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
filename: "{{ tmp_file.path }}"
|
||||
disk_format: raw
|
||||
tags:
|
||||
- test
|
||||
- ansible
|
||||
project: ansible_project
|
||||
register: image
|
||||
|
||||
- name: Get details of created image (owner by project name)
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: ansible_image
|
||||
register: images
|
||||
|
||||
- name: Verify image owner (owner by project name)
|
||||
assert:
|
||||
that:
|
||||
- images.images.0.owner == project.project.id
|
||||
|
||||
- name: Delete raw image (owner by project name)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_image
|
||||
|
||||
- name: Create raw image (owner by project name and domain name)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_image
|
||||
filename: "{{ tmp_file.path }}"
|
||||
disk_format: raw
|
||||
tags:
|
||||
- test
|
||||
- ansible
|
||||
project: ansible_project
|
||||
project_domain: default
|
||||
register: image
|
||||
|
||||
- name: Get details of created image (owner by project name and domain name)
|
||||
openstack.cloud.image_info:
|
||||
cloud: "{{ cloud }}"
|
||||
image: ansible_image
|
||||
register: images
|
||||
|
||||
- name: Verify image owner (owner by project name and domain name)
|
||||
assert:
|
||||
that:
|
||||
- images.images.0.owner == project.project.id
|
||||
|
||||
- name: Delete raw image (owner by project name and domain name)
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_image
|
||||
|
||||
- name: Delete owner project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_project
|
||||
domain: default
|
||||
|
||||
- name: Delete mock kernel and ramdisk images
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ item }}"
|
||||
loop:
|
||||
- cirros-vmlinuz
|
||||
- cirros-initrd
|
||||
|
||||
- name: Delete test image file
|
||||
file:
|
||||
name: "{{ tmp_file.path }}"
|
||||
state: absent
|
||||
|
||||
always:
|
||||
- name: Remove temporary image file
|
||||
ansible.builtin.file:
|
||||
path: "{{ tmp_file.path }}"
|
||||
state: absent
|
||||
when: tmp_file is defined and 'path' in tmp_file
|
||||
|
||||
2
ci/roles/inventory/files/ansible.cfg
Normal file
2
ci/roles/inventory/files/ansible.cfg
Normal file
@@ -0,0 +1,2 @@
|
||||
[inventory]
|
||||
enable_plugins=openstack.cloud.openstack
|
||||
430
ci/roles/inventory/tasks/main.yml
Normal file
430
ci/roles/inventory/tasks/main.yml
Normal file
@@ -0,0 +1,430 @@
|
||||
---
|
||||
- module_defaults:
|
||||
group/openstack.cloud.openstack:
|
||||
cloud: "{{ cloud }}"
|
||||
# Listing modules individually is required for
|
||||
# backward compatibility with Ansible 2.9 only
|
||||
openstack.cloud.resource:
|
||||
cloud: "{{ cloud }}"
|
||||
openstack.cloud.resources:
|
||||
cloud: "{{ cloud }}"
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
block:
|
||||
- name: Create external network
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: network
|
||||
attributes:
|
||||
name: ansible_network_external
|
||||
is_router_external: true
|
||||
wait: true
|
||||
register: network_external
|
||||
|
||||
- name: Create external subnet
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: subnet
|
||||
attributes:
|
||||
cidr: 10.6.6.0/24
|
||||
ip_version: 4
|
||||
name: ansible_external_subnet
|
||||
network_id: "{{ network_external.resource.id }}"
|
||||
register: subnet_external
|
||||
|
||||
- name: Create external port
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: port
|
||||
attributes:
|
||||
name: ansible_port_external
|
||||
network_id: "{{ network_external.resource.id }}"
|
||||
fixed_ips:
|
||||
- ip_address: 10.6.6.50
|
||||
non_updateable_attributes:
|
||||
- fixed_ips
|
||||
register: port_external
|
||||
|
||||
- name: Create internal network
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: network
|
||||
attributes:
|
||||
name: ansible_network_internal
|
||||
is_router_external: false
|
||||
wait: true
|
||||
register: network_internal
|
||||
|
||||
- name: Create internal subnet
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: subnet
|
||||
attributes:
|
||||
cidr: 10.7.7.0/24
|
||||
ip_version: 4
|
||||
name: ansible_internal_subnet
|
||||
network_id: "{{ network_internal.resource.id }}"
|
||||
register: subnet_internal
|
||||
|
||||
- name: Create internal port 1
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: port
|
||||
attributes:
|
||||
name: ansible_port_internal1
|
||||
network_id: "{{ network_internal.resource.id }}"
|
||||
fixed_ips:
|
||||
- ip_address: 10.7.7.100
|
||||
subnet_id: "{{ subnet_internal.resource.id }}"
|
||||
register: port_internal1
|
||||
|
||||
- name: Create internal port 2
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: port
|
||||
attributes:
|
||||
name: ansible_port_internal2
|
||||
network_id: "{{ network_internal.resource.id }}"
|
||||
fixed_ips:
|
||||
- ip_address: 10.7.7.101
|
||||
subnet_id: "{{ subnet_internal.resource.id }}"
|
||||
register: port_internal2
|
||||
|
||||
- name: Create router
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: router
|
||||
attributes:
|
||||
name: ansible_router
|
||||
external_gateway_info:
|
||||
enable_snat: true
|
||||
external_fixed_ips:
|
||||
- ip_address: 10.6.6.10
|
||||
subnet_id: "{{ subnet_external.resource.id }}"
|
||||
network_id: "{{ network_external.resource.id }}"
|
||||
wait: true
|
||||
register: router
|
||||
|
||||
- name: Attach router to internal subnet
|
||||
openstack.cloud.router:
|
||||
name: ansible_router
|
||||
network: "{{ network_external.resource.id }}"
|
||||
external_fixed_ips:
|
||||
- ip: 10.6.6.10
|
||||
subnet: "{{ subnet_external.resource.id }}"
|
||||
interfaces:
|
||||
- net: "{{ network_internal.resource.id }}"
|
||||
subnet: "{{ subnet_internal.resource.id }}"
|
||||
portip: 10.7.7.1
|
||||
|
||||
- name: Create floating ip address 1
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: ip
|
||||
attributes:
|
||||
name: 10.6.6.150
|
||||
floating_ip_address: 10.6.6.150
|
||||
floating_network_id: "{{ network_external.resource.id }}"
|
||||
port_id: "{{ port_internal1.resource.id }}"
|
||||
register: ip1
|
||||
|
||||
- name: List images
|
||||
openstack.cloud.resources:
|
||||
service: image
|
||||
type: image
|
||||
register: images
|
||||
|
||||
- name: Identify CirrOS image id
|
||||
set_fact:
|
||||
image_id: "{{ images.resources|community.general.json_query(query)|first }}"
|
||||
vars:
|
||||
query: "[?starts_with(name, 'cirros')].id"
|
||||
|
||||
- name: List compute flavors
|
||||
openstack.cloud.resources:
|
||||
service: compute
|
||||
type: flavor
|
||||
register: flavors
|
||||
|
||||
- name: Identify m1.tiny flavor id
|
||||
set_fact:
|
||||
flavor_id: "{{ flavors.resources|community.general.json_query(query)|first }}"
|
||||
vars:
|
||||
query: "[?name == 'm1.tiny'].id"
|
||||
|
||||
- name: Create server 1
|
||||
openstack.cloud.resource:
|
||||
service: compute
|
||||
type: server
|
||||
attributes:
|
||||
name: ansible_server1
|
||||
image_id: "{{ image_id }}"
|
||||
flavor_id: "{{ flavor_id }}"
|
||||
networks:
|
||||
- uuid: "{{ network_internal.resource.id }}"
|
||||
port: "{{ port_internal1.resource.id }}"
|
||||
- uuid: "{{ network_internal.resource.id }}"
|
||||
port: "{{ port_internal2.resource.id }}"
|
||||
non_updateable_attributes:
|
||||
- name
|
||||
- image_id
|
||||
- flavor_id
|
||||
- networks
|
||||
wait: true
|
||||
register: server1
|
||||
|
||||
- name: Create server 2
|
||||
openstack.cloud.resource:
|
||||
service: compute
|
||||
type: server
|
||||
attributes:
|
||||
name: ansible_server2
|
||||
image_id: "{{ image_id }}"
|
||||
flavor_id: "{{ flavor_id }}"
|
||||
networks:
|
||||
- uuid: "{{ network_internal.resource.id }}"
|
||||
non_updateable_attributes:
|
||||
- name
|
||||
- image_id
|
||||
- flavor_id
|
||||
- networks
|
||||
wait: true
|
||||
register: server2
|
||||
|
||||
- name: Run inventory plugin tests
|
||||
always:
|
||||
- name: Remove temporary inventory directory after block execution
|
||||
ansible.builtin.file:
|
||||
path: "{{ tmp_dir.path }}"
|
||||
state: absent
|
||||
when: tmp_dir is defined and 'path' in tmp_dir
|
||||
|
||||
block:
|
||||
- name: Ensure clean environment
|
||||
ansible.builtin.set_fact:
|
||||
tmp_dir: !!null
|
||||
|
||||
- name: Create temporary inventory directory
|
||||
ansible.builtin.tempfile:
|
||||
state: directory
|
||||
register: tmp_dir
|
||||
|
||||
- name: Copy ansible.cfg file
|
||||
ansible.builtin.copy:
|
||||
src: ansible.cfg
|
||||
dest: '{{ tmp_dir.path }}/'
|
||||
mode: '0644'
|
||||
|
||||
- name: Create inventory config file
|
||||
ansible.builtin.template:
|
||||
src: openstack.yaml.j2
|
||||
dest: '{{ tmp_dir.path }}/openstack.yaml'
|
||||
mode: '0644'
|
||||
|
||||
- name: List servers with inventory plugin
|
||||
ansible.builtin.command:
|
||||
cmd: ansible-inventory --list --yaml --inventory-file openstack.yaml
|
||||
chdir: "{{ tmp_dir.path }}"
|
||||
environment:
|
||||
ANSIBLE_INVENTORY_CACHE: "True"
|
||||
ANSIBLE_INVENTORY_CACHE_PLUGIN: "jsonfile"
|
||||
ANSIBLE_CACHE_PLUGIN_CONNECTION: "{{ tmp_dir.path }}/.cache/"
|
||||
register: inventory
|
||||
|
||||
- name: Read YAML output from inventory plugin
|
||||
ansible.builtin.set_fact:
|
||||
inventory: "{{ inventory.stdout | from_yaml }}"
|
||||
|
||||
- name: Check YAML output from inventory plugin
|
||||
assert:
|
||||
that:
|
||||
- inventory.all.children.RegionOne.hosts.keys() | sort == ['ansible_server1', 'ansible_server2'] | sort
|
||||
- ansible_server1.ansible_host == '10.6.6.150'
|
||||
- "'10.7.7.' in ansible_server2.ansible_host"
|
||||
- ansible_server1.ci_compose_id == ansible_server1.openstack.id
|
||||
- ansible_server1.ci_compose_project_id == ansible_server1.openstack.project_id
|
||||
vars:
|
||||
ansible_server1: "{{
|
||||
(inventory.all.children.values()
|
||||
| map(attribute='hosts', default={})
|
||||
| map(attribute='ansible_server1', default={})
|
||||
| reject('equalto', {})
|
||||
| list
|
||||
)[0] }}"
|
||||
ansible_server2: "{{
|
||||
(inventory.all.children.values()
|
||||
| map(attribute='hosts', default={})
|
||||
| map(attribute='ansible_server2', default={})
|
||||
| reject('equalto', {})
|
||||
| list
|
||||
)[0] }}"
|
||||
|
||||
- name: Find Ansible's cache file
|
||||
ansible.builtin.find:
|
||||
paths: "{{ tmp_dir.path }}/.cache/"
|
||||
patterns: 'ansible_inventory_*'
|
||||
register: files
|
||||
|
||||
- name: Assert a single cache file only
|
||||
assert:
|
||||
that:
|
||||
- files.files | length == 1
|
||||
|
||||
- name: Read Ansible's cache file
|
||||
ansible.builtin.slurp:
|
||||
src: "{{ files.files.0.path }}"
|
||||
register: cache
|
||||
|
||||
- name: Process Ansible cache
|
||||
ansible.builtin.set_fact:
|
||||
cache: "{{ cache.content | b64decode | from_yaml }}"
|
||||
|
||||
- name: Further process Ansible 2.19+ cache
|
||||
ansible.builtin.set_fact:
|
||||
cache: "{{ cache.__payload__ | from_yaml }}"
|
||||
when: cache.__payload__ is defined
|
||||
|
||||
- name: Check Ansible's cache
|
||||
assert:
|
||||
that:
|
||||
- cache | map(attribute='name') | list | sort == ['ansible_server1', 'ansible_server2'] | sort
|
||||
|
||||
- name: List servers with inventory plugin again
|
||||
ansible.builtin.command:
|
||||
cmd: ansible-inventory --list --yaml --inventory-file openstack.yaml
|
||||
chdir: "{{ tmp_dir.path }}"
|
||||
environment:
|
||||
ANSIBLE_INVENTORY_CACHE: "True"
|
||||
ANSIBLE_INVENTORY_CACHE_PLUGIN: "jsonfile"
|
||||
ANSIBLE_CACHE_PLUGIN_CONNECTION: "{{ tmp_dir.path }}/.cache/"
|
||||
register: inventory
|
||||
|
||||
- name: Read YAML output from inventory plugin again
|
||||
ansible.builtin.set_fact:
|
||||
inventory: "{{ inventory.stdout | from_yaml }}"
|
||||
|
||||
- name: Check YAML output from inventory plugin again
|
||||
assert:
|
||||
that:
|
||||
- inventory.all.children.RegionOne.hosts.keys() | sort == ['ansible_server1', 'ansible_server2'] | sort
|
||||
|
||||
- name: List servers with inventory plugin with IPv4 only
|
||||
ansible.builtin.command:
|
||||
cmd: ansible-inventory --list --yaml --extra-vars only_ipv4=true --inventory-file openstack.yaml
|
||||
chdir: "{{ tmp_dir.path }}"
|
||||
environment:
|
||||
ANSIBLE_INVENTORY_CACHE: "True"
|
||||
ANSIBLE_INVENTORY_CACHE_PLUGIN: "jsonfile"
|
||||
ANSIBLE_CACHE_PLUGIN_CONNECTION: "{{ tmp_dir.path }}/.cache/"
|
||||
register: inventory
|
||||
|
||||
- name: Read YAML output from inventory plugin again
|
||||
ansible.builtin.set_fact:
|
||||
inventory: "{{ inventory.stdout | from_yaml }}"
|
||||
|
||||
- name: Check YAML output from inventory plugin again
|
||||
assert:
|
||||
that:
|
||||
- inventory.all.children.RegionOne.hosts.keys() | sort == ['ansible_server1', 'ansible_server2'] | sort
|
||||
|
||||
- name: Delete server 2
|
||||
openstack.cloud.resource:
|
||||
service: compute
|
||||
type: server
|
||||
attributes:
|
||||
name: ansible_server2
|
||||
state: absent
|
||||
wait: true
|
||||
|
||||
- name: Delete server 1
|
||||
openstack.cloud.resource:
|
||||
service: compute
|
||||
type: server
|
||||
attributes:
|
||||
name: ansible_server1
|
||||
state: absent
|
||||
wait: true
|
||||
|
||||
- name: Delete floating ip address 1
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: ip
|
||||
attributes:
|
||||
floating_ip_address: 10.6.6.150
|
||||
state: absent
|
||||
|
||||
- name: Detach router from internal subnet
|
||||
openstack.cloud.router:
|
||||
name: ansible_router
|
||||
network: "{{ network_external.resource.id }}"
|
||||
external_fixed_ips:
|
||||
- ip: 10.6.6.10
|
||||
subnet: "{{ subnet_external.resource.id }}"
|
||||
interfaces: []
|
||||
|
||||
- name: Delete router
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: router
|
||||
attributes:
|
||||
name: ansible_router
|
||||
state: absent
|
||||
wait: true
|
||||
|
||||
- name: Delete internal port 2
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: port
|
||||
attributes:
|
||||
name: ansible_port_internal2
|
||||
state: absent
|
||||
|
||||
- name: Delete internal port 1
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: port
|
||||
attributes:
|
||||
name: ansible_port_internal1
|
||||
state: absent
|
||||
|
||||
- name: Delete internal subnet
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: subnet
|
||||
attributes:
|
||||
name: ansible_internal_subnet
|
||||
state: absent
|
||||
|
||||
- name: Delete internal network
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: network
|
||||
attributes:
|
||||
name: ansible_network_internal
|
||||
state: absent
|
||||
wait: true
|
||||
|
||||
- name: Delete external port
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: port
|
||||
attributes:
|
||||
name: ansible_port_external
|
||||
state: absent
|
||||
|
||||
- name: Delete external subnet
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: subnet
|
||||
attributes:
|
||||
name: ansible_external_subnet
|
||||
state: absent
|
||||
|
||||
- name: Delete external network
|
||||
openstack.cloud.resource:
|
||||
service: network
|
||||
type: network
|
||||
attributes:
|
||||
name: ansible_network_external
|
||||
state: absent
|
||||
wait: true
|
||||
11
ci/roles/inventory/templates/openstack.yaml.j2
Normal file
11
ci/roles/inventory/templates/openstack.yaml.j2
Normal file
@@ -0,0 +1,11 @@
|
||||
plugin: openstack.cloud.openstack
|
||||
|
||||
all_projects: true
|
||||
compose:
|
||||
ci_compose_id: openstack.id
|
||||
ci_compose_project_id: openstack.project_id
|
||||
expand_hostvars: true
|
||||
fail_on_errors: true
|
||||
only_clouds:
|
||||
- "{{ cloud }}"
|
||||
strict: true
|
||||
@@ -1 +1,11 @@
|
||||
keypair_name: shade_keypair
|
||||
expected_fields:
|
||||
- created_at
|
||||
- fingerprint
|
||||
- id
|
||||
- is_deleted
|
||||
- name
|
||||
- private_key
|
||||
- public_key
|
||||
- type
|
||||
- user_id
|
||||
|
||||
@@ -1,62 +1,162 @@
|
||||
---
|
||||
- name: Create keypair (non-existing)
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
state: present
|
||||
register:
|
||||
keypair
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
state: present
|
||||
register: keypair
|
||||
|
||||
# This assert verifies that Ansible is capable serializing data returned by SDK
|
||||
- name: Ensure private key is returned
|
||||
- name: Assert fields
|
||||
assert:
|
||||
that:
|
||||
- keypair.key.public_key is defined and keypair.key.public_key
|
||||
- item in keypair.keypair
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- name: Get list of all keypairs
|
||||
openstack.cloud.keypair_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: keypairs_all
|
||||
|
||||
- name: Get list of keypairs with filter
|
||||
openstack.cloud.keypair_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
register: keypairs
|
||||
|
||||
- name: Ensure that list of keypairs contains single element
|
||||
assert:
|
||||
that:
|
||||
- keypairs['keypairs']|length == 1
|
||||
|
||||
- name: Assert fields
|
||||
assert:
|
||||
that:
|
||||
- item in keypairs.keypairs.0.keys()
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
# This assert verifies that Ansible is capable serializing data returned by SDK
|
||||
- name: Ensure public key is returned
|
||||
assert:
|
||||
that:
|
||||
- keypair.keypair.public_key is defined and keypair.keypair.public_key|length > 0
|
||||
|
||||
- name: Create another keypair
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}-2"
|
||||
state: present
|
||||
|
||||
- name: Delete keypair (non-existing)
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
state: absent
|
||||
cloud: "{{ cloud }}"
|
||||
name: "non-existing"
|
||||
state: absent
|
||||
|
||||
- name: Delete keypair
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
state: absent
|
||||
|
||||
- name: Get list of keypairs
|
||||
openstack.cloud.keypair_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
register: keypairs
|
||||
|
||||
- name: Ensure that list of keypairs is empty
|
||||
assert:
|
||||
that:
|
||||
- keypairs['keypairs']|length == 0
|
||||
|
||||
- name: Delete another keypair
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}-2"
|
||||
state: absent
|
||||
|
||||
- name: Generate test key file
|
||||
user:
|
||||
name: "{{ ansible_env.USER }}"
|
||||
generate_ssh_key: yes
|
||||
ssh_key_file: .ssh/shade_id_rsa
|
||||
name: "{{ ansible_env.USER }}"
|
||||
generate_ssh_key: true
|
||||
ssh_key_file: .ssh/shade_id_rsa
|
||||
|
||||
- name: Create keypair (file)
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
state: present
|
||||
public_key_file: "{{ ansible_env.HOME }}/.ssh/shade_id_rsa.pub"
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
state: present
|
||||
public_key_file: "{{ ansible_env.HOME }}/.ssh/shade_id_rsa.pub"
|
||||
|
||||
- name: Get list of keypairs
|
||||
openstack.cloud.keypair_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
register: keypairs
|
||||
|
||||
- name: Ensure that list of keypairs contains single element
|
||||
assert:
|
||||
that:
|
||||
- keypairs['keypairs']|length == 1
|
||||
|
||||
- name: Delete keypair (file)
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
state: absent
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
state: absent
|
||||
|
||||
- name: Get list of keypairs
|
||||
openstack.cloud.keypair_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
register: keypairs
|
||||
|
||||
- name: Ensure that list of keypairs is empty
|
||||
assert:
|
||||
that:
|
||||
- keypairs['keypairs']|length == 0
|
||||
|
||||
- name: Create keypair (key)
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
state: present
|
||||
public_key: "{{ lookup('file', '~/.ssh/shade_id_rsa.pub') }}"
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
state: present
|
||||
public_key: "{{ lookup('file', '~/.ssh/shade_id_rsa.pub') }}"
|
||||
|
||||
- name: Get list of keypairs
|
||||
openstack.cloud.keypair_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
register: keypairs
|
||||
|
||||
- name: Ensure that list of keypairs contains single element
|
||||
assert:
|
||||
that:
|
||||
- keypairs['keypairs']|length == 1
|
||||
|
||||
- name: Delete keypair (key)
|
||||
openstack.cloud.keypair:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
state: absent
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
state: absent
|
||||
|
||||
- name: Get list of keypairs
|
||||
openstack.cloud.keypair_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ keypair_name }}"
|
||||
register: keypairs
|
||||
|
||||
- name: Ensure that list of keypairs is empty
|
||||
assert:
|
||||
that:
|
||||
- keypairs['keypairs']|length == 0
|
||||
|
||||
- name: Delete test key pub file
|
||||
file:
|
||||
name: "{{ ansible_env.HOME }}/.ssh/shade_id_rsa.pub"
|
||||
state: absent
|
||||
name: "{{ ansible_env.HOME }}/.ssh/shade_id_rsa.pub"
|
||||
state: absent
|
||||
|
||||
- name: Delete test key pvt file
|
||||
file:
|
||||
name: "{{ ansible_env.HOME }}/.ssh/shade_id_rsa"
|
||||
state: absent
|
||||
name: "{{ ansible_env.HOME }}/.ssh/shade_id_rsa"
|
||||
state: absent
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
domain_name: ansible_domain
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
- name: Create keystone domain
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ domain_name }}"
|
||||
description: "test description"
|
||||
|
||||
- name: Update keystone domain
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ domain_name }}"
|
||||
description: "updated description"
|
||||
|
||||
- name: Delete keystone domain
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ domain_name }}"
|
||||
@@ -1,35 +1,4 @@
|
||||
protocol_name: 'test-protocol'
|
||||
protocol_name_2: 'test-protocol-2'
|
||||
|
||||
# Minimal IDP definition
|
||||
idp_name: 'test-idp'
|
||||
idp_remote_ids:
|
||||
- 'https://auth.example.com/auth/realms/ExampleRealm'
|
||||
|
||||
# Minimal Domain definition
|
||||
domain_name: 'test-domain'
|
||||
|
||||
# Minimal Mapping definition
|
||||
mapping_name_1: 'ansible-test-mapping-1'
|
||||
mapping_name_2: 'ansible-test-mapping-2'
|
||||
mapping_rules_1:
|
||||
- local:
|
||||
- group:
|
||||
domain:
|
||||
name: example_domain
|
||||
name: example-group
|
||||
remote:
|
||||
- type: HTTP_OIDC_GROUPS
|
||||
any_one_of:
|
||||
- group1
|
||||
- group2
|
||||
mapping_rules_2:
|
||||
- local:
|
||||
- group:
|
||||
domain:
|
||||
name: example_domain
|
||||
name: example_group
|
||||
remote:
|
||||
- type: HTTP_OIDC_GROUPS
|
||||
any_one_of:
|
||||
- group1
|
||||
expected_fields:
|
||||
- id
|
||||
- mapping_id
|
||||
- name
|
||||
|
||||
@@ -6,388 +6,336 @@
|
||||
# - Retry change (noop)
|
||||
#
|
||||
- module_defaults:
|
||||
# meta/action_groups.yml glue seems to be missing
|
||||
# group/os:
|
||||
# cloud: "{{ cloud }}"
|
||||
group/openstack.cloud.openstack:
|
||||
cloud: "{{ cloud }}"
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
cloud: "{{ cloud }}" # Backward compatibility with Ansible 2.9
|
||||
idp_id: ansible_idp
|
||||
openstack.cloud.keystone_federation_protocol_info:
|
||||
cloud: "{{ cloud }}" # Backward compatibility with Ansible 2.9
|
||||
idp_id: ansible_idp
|
||||
# Backward compatibility with Ansible 2.9
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
openstack.cloud.federation_idp:
|
||||
cloud: "{{ cloud }}"
|
||||
openstack.cloud.federation_mapping:
|
||||
cloud: "{{ cloud }}"
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
cloud: "{{ cloud }}"
|
||||
idp_id: "{{ idp_name }}"
|
||||
openstack.cloud.keystone_federation_protocol_info:
|
||||
cloud: "{{ cloud }}"
|
||||
idp_id: "{{ idp_name }}"
|
||||
block:
|
||||
# ========================================================================
|
||||
# Initial setup
|
||||
- name: 'Create test Domain'
|
||||
- name: Create test Domain
|
||||
openstack.cloud.identity_domain:
|
||||
name: '{{ domain_name }}'
|
||||
register: create_domain
|
||||
- assert:
|
||||
that:
|
||||
- create_domain is successful
|
||||
- '"id" in create_domain'
|
||||
- name: 'Store domain ID as fact'
|
||||
set_fact:
|
||||
domain_id: '{{ create_domain.id }}'
|
||||
name: ansible_domain
|
||||
register: domain
|
||||
|
||||
- name: 'Create test Identity Provider'
|
||||
- name: Create test Identity Provider
|
||||
openstack.cloud.federation_idp:
|
||||
state: 'present'
|
||||
name: '{{ idp_name }}'
|
||||
domain_id: '{{ domain_id }}'
|
||||
register: create_idp
|
||||
- assert:
|
||||
that:
|
||||
- create_idp is successful
|
||||
state: present
|
||||
name: ansible_idp
|
||||
domain_id: '{{ domain.domain.id }}'
|
||||
|
||||
- name: 'Create test mapping (1)'
|
||||
- name: Create test mapping (1)
|
||||
openstack.cloud.federation_mapping:
|
||||
state: 'present'
|
||||
name: '{{ mapping_name_1 }}'
|
||||
rules: '{{ mapping_rules_1 }}'
|
||||
register: create_mapping
|
||||
- assert:
|
||||
that:
|
||||
- create_mapping is successful
|
||||
- name: 'Create test mapping (2)'
|
||||
state: present
|
||||
name: ansible_mapping1
|
||||
rules:
|
||||
- local:
|
||||
- group:
|
||||
domain:
|
||||
name: example_domain
|
||||
name: example-group
|
||||
remote:
|
||||
- type: HTTP_OIDC_GROUPS
|
||||
any_one_of:
|
||||
- group1
|
||||
- group2
|
||||
|
||||
- name: Create test mapping (2)
|
||||
openstack.cloud.federation_mapping:
|
||||
state: 'present'
|
||||
name: '{{ mapping_name_2 }}'
|
||||
rules: '{{ mapping_rules_2 }}'
|
||||
register: create_mapping
|
||||
- assert:
|
||||
that:
|
||||
- create_mapping is successful
|
||||
state: present
|
||||
name: ansible_mapping2
|
||||
rules:
|
||||
- local:
|
||||
- group:
|
||||
domain:
|
||||
name: example_domain
|
||||
name: example_group
|
||||
remote:
|
||||
- type: HTTP_OIDC_GROUPS
|
||||
any_one_of:
|
||||
- group1
|
||||
|
||||
|
||||
# We *should* have a blank slate to start with, but we also shouldn't
|
||||
# explode if I(state=absent) and the IDP doesn't exist
|
||||
- name: "Ensure Protocol doesn't exist to start"
|
||||
- name: Ensure Protocol does not exist to start
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'absent'
|
||||
name: '{{ protocol_name }}'
|
||||
register: delete_protocol
|
||||
- assert:
|
||||
that:
|
||||
- delete_protocol is successful
|
||||
state: absent
|
||||
name: ansible_protocol1
|
||||
|
||||
# ========================================================================
|
||||
# Creation
|
||||
|
||||
- name: 'Create protocol - CHECK MODE'
|
||||
check_mode: yes
|
||||
- name: Create protocol - CHECK MODE
|
||||
check_mode: true
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'present'
|
||||
name: '{{ protocol_name }}'
|
||||
mapping_id: '{{ mapping_name_1 }}'
|
||||
register: create_protocol
|
||||
state: present
|
||||
name: ansible_protocol1
|
||||
mapping_id: ansible_mapping1
|
||||
register: protocol
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- create_protocol is successful
|
||||
- create_protocol is changed
|
||||
- protocol is changed
|
||||
|
||||
- name: 'Fetch Protocol info (should be absent)'
|
||||
- name: Fetch Protocol info (should be absent)
|
||||
openstack.cloud.keystone_federation_protocol_info:
|
||||
name: '{{ protocol_name }}'
|
||||
register: protocol_info
|
||||
ignore_errors: yes
|
||||
- assert:
|
||||
that:
|
||||
- protocol_info is failed
|
||||
name: ansible_protocol1
|
||||
register: protocols
|
||||
|
||||
- name: 'Create protocol'
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'present'
|
||||
name: '{{ protocol_name }}'
|
||||
mapping_id: '{{ mapping_name_1 }}'
|
||||
register: create_protocol
|
||||
- assert:
|
||||
that:
|
||||
- create_protocol is successful
|
||||
- create_protocol is changed
|
||||
- '"protocol" in create_protocol'
|
||||
- '"id" in protocol'
|
||||
- '"name" in protocol'
|
||||
- '"idp_id" in protocol'
|
||||
- '"mapping_id" in protocol'
|
||||
- protocol.id == protocol_name
|
||||
- protocol.name == protocol_name
|
||||
- protocol.idp_id == idp_name
|
||||
- protocol.mapping_id == mapping_name_1
|
||||
vars:
|
||||
protocol: '{{ create_protocol.protocol }}'
|
||||
- protocols.protocols | length == 0
|
||||
|
||||
- name: 'Create protocol (retry - no change) - CHECK MODE'
|
||||
check_mode: yes
|
||||
- name: Create protocol
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'present'
|
||||
name: '{{ protocol_name }}'
|
||||
mapping_id: '{{ mapping_name_1 }}'
|
||||
register: create_protocol
|
||||
- assert:
|
||||
that:
|
||||
- create_protocol is successful
|
||||
- create_protocol is not changed
|
||||
state: present
|
||||
name: ansible_protocol1
|
||||
mapping_id: ansible_mapping1
|
||||
register: protocol
|
||||
|
||||
- name: 'Create protocol (retry - no change)'
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'present'
|
||||
name: '{{ protocol_name }}'
|
||||
mapping_id: '{{ mapping_name_1 }}'
|
||||
register: create_protocol
|
||||
- assert:
|
||||
that:
|
||||
- create_protocol is successful
|
||||
- create_protocol is not changed
|
||||
- '"protocol" in create_protocol'
|
||||
- '"id" in protocol'
|
||||
- '"name" in protocol'
|
||||
- '"idp_id" in protocol'
|
||||
- '"mapping_id" in protocol'
|
||||
- protocol.id == protocol_name
|
||||
- protocol.name == protocol_name
|
||||
- protocol.idp_id == idp_name
|
||||
- protocol.mapping_id == mapping_name_1
|
||||
vars:
|
||||
protocol: '{{ create_protocol.protocol }}'
|
||||
- protocol is changed
|
||||
- protocol.protocol.id == 'ansible_protocol1'
|
||||
- protocol.protocol.name == 'ansible_protocol1'
|
||||
- protocol.protocol.mapping_id == 'ansible_mapping1'
|
||||
|
||||
- name: assert return values of keystone_federation_protocol module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(protocol.protocol.keys())|length == 0
|
||||
|
||||
- name: Create protocol (retry - no change) - CHECK MODE
|
||||
check_mode: true
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: present
|
||||
name: ansible_protocol1
|
||||
mapping_id: ansible_mapping1
|
||||
register: protocol
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- protocol is not changed
|
||||
|
||||
- name: Create protocol (retry - no change)
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: present
|
||||
name: ansible_protocol1
|
||||
mapping_id: ansible_mapping1
|
||||
register: protocol
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- protocol is not changed
|
||||
- protocol.protocol.id == 'ansible_protocol1'
|
||||
- protocol.protocol.name == 'ansible_protocol1'
|
||||
- protocol.protocol.mapping_id == 'ansible_mapping1'
|
||||
|
||||
# ========================================================================
|
||||
# Update
|
||||
|
||||
- name: 'Update protocol - CHECK MODE'
|
||||
check_mode: yes
|
||||
- name: Update protocol - CHECK MODE
|
||||
check_mode: true
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'present'
|
||||
name: '{{ protocol_name }}'
|
||||
mapping_id: '{{ mapping_name_2 }}'
|
||||
register: update_protocol
|
||||
- assert:
|
||||
that:
|
||||
- update_protocol is successful
|
||||
- update_protocol is changed
|
||||
state: present
|
||||
name: ansible_protocol1
|
||||
mapping_id: ansible_mapping2
|
||||
register: protocol
|
||||
|
||||
- name: 'Update protocol'
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'present'
|
||||
name: '{{ protocol_name }}'
|
||||
mapping_id: '{{ mapping_name_2 }}'
|
||||
register: update_protocol
|
||||
- assert:
|
||||
that:
|
||||
- update_protocol is successful
|
||||
- update_protocol is changed
|
||||
- '"protocol" in update_protocol'
|
||||
- '"id" in protocol'
|
||||
- '"name" in protocol'
|
||||
- '"idp_id" in protocol'
|
||||
- '"mapping_id" in protocol'
|
||||
- protocol.id == protocol_name
|
||||
- protocol.name == protocol_name
|
||||
- protocol.idp_id == idp_name
|
||||
- protocol.mapping_id == mapping_name_2
|
||||
vars:
|
||||
protocol: '{{ update_protocol.protocol }}'
|
||||
- protocol is changed
|
||||
|
||||
- name: 'Update protocol (retry - no change) - CHECK MODE'
|
||||
check_mode: yes
|
||||
- name: Update protocol
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'present'
|
||||
name: '{{ protocol_name }}'
|
||||
mapping_id: '{{ mapping_name_2 }}'
|
||||
register: update_protocol
|
||||
- assert:
|
||||
that:
|
||||
- update_protocol is successful
|
||||
- update_protocol is not changed
|
||||
state: present
|
||||
name: ansible_protocol1
|
||||
mapping_id: ansible_mapping2
|
||||
register: protocol
|
||||
|
||||
- name: 'Update protocol (retry - no change)'
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'present'
|
||||
name: '{{ protocol_name }}'
|
||||
mapping_id: '{{ mapping_name_2 }}'
|
||||
register: update_protocol
|
||||
- assert:
|
||||
that:
|
||||
- update_protocol is successful
|
||||
- update_protocol is not changed
|
||||
- '"protocol" in update_protocol'
|
||||
- '"id" in protocol'
|
||||
- '"name" in protocol'
|
||||
- '"idp_id" in protocol'
|
||||
- '"mapping_id" in protocol'
|
||||
- protocol.id == protocol_name
|
||||
- protocol.name == protocol_name
|
||||
- protocol.idp_id == idp_name
|
||||
- protocol.mapping_id == mapping_name_2
|
||||
vars:
|
||||
protocol: '{{ update_protocol.protocol }}'
|
||||
- protocol is changed
|
||||
- protocol.protocol.id == 'ansible_protocol1'
|
||||
- protocol.protocol.name == 'ansible_protocol1'
|
||||
- protocol.protocol.mapping_id == 'ansible_mapping2'
|
||||
|
||||
- name: Update protocol (retry - no change) - CHECK MODE
|
||||
check_mode: true
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: present
|
||||
name: ansible_protocol1
|
||||
mapping_id: ansible_mapping2
|
||||
register: protocol
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- protocol is not changed
|
||||
|
||||
- name: Update protocol (retry - no change)
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: present
|
||||
name: ansible_protocol1
|
||||
mapping_id: ansible_mapping2
|
||||
register: protocol
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- protocol is not changed
|
||||
- protocol.protocol.id == 'ansible_protocol1'
|
||||
- protocol.protocol.name == 'ansible_protocol1'
|
||||
- protocol.protocol.mapping_id == 'ansible_mapping2'
|
||||
|
||||
# ========================================================================
|
||||
# Create second protocol to test openstack.cloud.keystone_federation_protocol_info
|
||||
|
||||
- name: 'Create protocol (2)'
|
||||
- name: Create protocol (2)
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'present'
|
||||
name: '{{ protocol_name_2 }}'
|
||||
mapping_id: '{{ mapping_name_1 }}'
|
||||
register: create_protocol_2
|
||||
state: present
|
||||
name: ansible_protocol2
|
||||
mapping_id: ansible_mapping1
|
||||
register: protocol
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- create_protocol_2 is successful
|
||||
- create_protocol_2 is changed
|
||||
- '"protocol" in create_protocol_2'
|
||||
- '"id" in protocol'
|
||||
- '"name" in protocol'
|
||||
- '"idp_id" in protocol'
|
||||
- '"mapping_id" in protocol'
|
||||
- protocol.id == protocol_name_2
|
||||
- protocol.name == protocol_name_2
|
||||
- protocol.idp_id == idp_name
|
||||
- protocol.mapping_id == mapping_name_1
|
||||
vars:
|
||||
protocol: '{{ create_protocol_2.protocol }}'
|
||||
- protocol is changed
|
||||
- protocol.protocol.id == 'ansible_protocol2'
|
||||
- protocol.protocol.name == 'ansible_protocol2'
|
||||
- protocol.protocol.mapping_id == 'ansible_mapping1'
|
||||
|
||||
# ========================================================================
|
||||
# Basic tests of openstack.cloud.keystone_federation_protocol_info
|
||||
|
||||
- name: 'Fetch Protocol info (a specific protocol)'
|
||||
- name: Fetch Protocol info (a specific protocol)
|
||||
openstack.cloud.keystone_federation_protocol_info:
|
||||
name: '{{ protocol_name }}'
|
||||
register: protocol_info
|
||||
name: ansible_protocol1
|
||||
register: protocols
|
||||
|
||||
- name: Check info about protocols
|
||||
assert:
|
||||
that:
|
||||
- protocols.protocols|length > 0
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(protocols.protocols[0].keys())|length == 0
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- protocol_info is successful
|
||||
- '"protocols" in protocol_info'
|
||||
- protocol_info.protocols | length == 1
|
||||
- '"id" in protocol'
|
||||
- '"name" in protocol'
|
||||
- '"idp_id" in protocol'
|
||||
- '"mapping_id" in protocol'
|
||||
- protocol.id == protocol_name
|
||||
- protocol.name == protocol_name
|
||||
- protocol.idp_id == idp_name
|
||||
- protocol.mapping_id == mapping_name_2
|
||||
vars:
|
||||
protocol: '{{ protocol_info.protocols[0] }}'
|
||||
- protocols.protocols[0].id == 'ansible_protocol1'
|
||||
- protocols.protocols[0].name == 'ansible_protocol1'
|
||||
- protocols.protocols[0].mapping_id == 'ansible_mapping2'
|
||||
|
||||
- name: 'Fetch Protocol info (all protocols on our test IDP)'
|
||||
- name: Fetch Protocol info (all protocols on our test IDP)
|
||||
openstack.cloud.keystone_federation_protocol_info: {}
|
||||
# idp_id defined in defaults at the start
|
||||
register: protocol_info
|
||||
register: protocols
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- protocol_info is successful
|
||||
- '"protocols" in protocol_info'
|
||||
# We created the IDP, and we're going to delete it:
|
||||
# we should be able to trust what's attached to it
|
||||
- protocol_info.protocols | length == 2
|
||||
- '"id" in protocol_1'
|
||||
- '"name" in protocol_1'
|
||||
- '"idp_id" in protocol_1'
|
||||
- '"mapping_id" in protocol_1'
|
||||
- '"id" in protocol_2'
|
||||
- '"name" in protocol_2'
|
||||
- '"idp_id" in protocol_2'
|
||||
- '"mapping_id" in protocol_2'
|
||||
- protocol_name in (protocol_info.protocols | map(attribute='id'))
|
||||
- protocol_name in (protocol_info.protocols | map(attribute='id'))
|
||||
- protocol_name_2 in (protocol_info.protocols | map(attribute='name'))
|
||||
- protocol_name_2 in (protocol_info.protocols | map(attribute='name'))
|
||||
- mapping_name_1 in (protocol_info.protocols | map(attribute='mapping_id'))
|
||||
- mapping_name_2 in (protocol_info.protocols | map(attribute='mapping_id'))
|
||||
- protocol_1.idp_id == idp_name
|
||||
- protocol_2.idp_id == idp_name
|
||||
vars:
|
||||
protocol_1: '{{ protocol_info.protocols[0] }}'
|
||||
protocol_2: '{{ protocol_info.protocols[1] }}'
|
||||
# We created the IDP, and we're going to delete it:
|
||||
# we should be able to trust what's attached to it
|
||||
- protocols.protocols | length == 2
|
||||
- "'ansible_protocol1' in (protocols.protocols | map(attribute='id'))"
|
||||
- "'ansible_protocol1' in (protocols.protocols | map(attribute='id'))"
|
||||
- "'ansible_protocol2' in (protocols.protocols | map(attribute='name'))"
|
||||
- "'ansible_protocol2' in (protocols.protocols | map(attribute='name'))"
|
||||
- "'ansible_mapping1' in (protocols.protocols | map(attribute='mapping_id'))"
|
||||
- "'ansible_mapping2' in (protocols.protocols | map(attribute='mapping_id'))"
|
||||
|
||||
# ========================================================================
|
||||
# Deletion
|
||||
|
||||
- name: 'Delete protocol - CHECK MODE'
|
||||
check_mode: yes
|
||||
- name: Delete protocol - CHECK MODE
|
||||
check_mode: true
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'absent'
|
||||
name: '{{ protocol_name }}'
|
||||
register: update_protocol
|
||||
- assert:
|
||||
that:
|
||||
- update_protocol is successful
|
||||
- update_protocol is changed
|
||||
state: absent
|
||||
name: ansible_protocol1
|
||||
register: protocol
|
||||
|
||||
- name: 'Delete protocol'
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'absent'
|
||||
name: '{{ protocol_name }}'
|
||||
register: update_protocol
|
||||
- assert:
|
||||
that:
|
||||
- update_protocol is successful
|
||||
- update_protocol is changed
|
||||
- protocol is changed
|
||||
|
||||
- name: 'Delete protocol (retry - no change) - CHECK MODE'
|
||||
check_mode: yes
|
||||
- name: Delete protocol
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'absent'
|
||||
name: '{{ protocol_name }}'
|
||||
register: update_protocol
|
||||
- assert:
|
||||
that:
|
||||
- update_protocol is successful
|
||||
- update_protocol is not changed
|
||||
state: absent
|
||||
name: ansible_protocol1
|
||||
register: protocol
|
||||
|
||||
- name: 'Delete protocol (retry - no change)'
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'absent'
|
||||
name: '{{ protocol_name }}'
|
||||
register: update_protocol
|
||||
- assert:
|
||||
that:
|
||||
- update_protocol is successful
|
||||
- update_protocol is not changed
|
||||
- protocol is changed
|
||||
|
||||
- name: Delete protocol (retry - no change) - CHECK MODE
|
||||
check_mode: true
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: absent
|
||||
name: ansible_protocol1
|
||||
register: protocol
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- protocol is not changed
|
||||
|
||||
- name: Delete protocol (retry - no change)
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: absent
|
||||
name: ansible_protocol1
|
||||
register: protocol
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- protocol is not changed
|
||||
|
||||
# ========================================================================
|
||||
# Clean up after ourselves
|
||||
always:
|
||||
- name: 'Delete protocol'
|
||||
- name: Delete protocol
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'absent'
|
||||
name: '{{ protocol_name }}'
|
||||
idp_id: '{{ idp_name }}'
|
||||
ignore_errors: yes
|
||||
state: absent
|
||||
name: ansible_protocol1
|
||||
idp_id: ansible_idp
|
||||
ignore_errors: true
|
||||
|
||||
- name: 'Delete protocol (2)'
|
||||
- name: Delete protocol (2)
|
||||
openstack.cloud.keystone_federation_protocol:
|
||||
state: 'absent'
|
||||
name: '{{ protocol_name_2 }}'
|
||||
idp_id: '{{ idp_name }}'
|
||||
ignore_errors: yes
|
||||
state: absent
|
||||
name: ansible_protocol2
|
||||
idp_id: ansible_idp
|
||||
ignore_errors: true
|
||||
|
||||
- name: 'Delete mapping 1'
|
||||
- name: Delete mapping 1
|
||||
openstack.cloud.federation_mapping:
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name_1 }}'
|
||||
ignore_errors: yes
|
||||
state: absent
|
||||
name: ansible_mapping1
|
||||
ignore_errors: true
|
||||
|
||||
- name: 'Delete mapping 2'
|
||||
- name: Delete mapping 2
|
||||
openstack.cloud.federation_mapping:
|
||||
state: 'absent'
|
||||
name: '{{ mapping_name_2 }}'
|
||||
ignore_errors: yes
|
||||
state: absent
|
||||
name: ansible_mapping2
|
||||
ignore_errors: true
|
||||
|
||||
- name: 'Delete idp'
|
||||
- name: Delete idp
|
||||
openstack.cloud.federation_idp:
|
||||
state: 'absent'
|
||||
name: '{{ idp_name }}'
|
||||
ignore_errors: yes
|
||||
state: absent
|
||||
name: ansible_idp
|
||||
ignore_errors: true
|
||||
|
||||
- name: 'Delete domain'
|
||||
- name: Delete domain
|
||||
openstack.cloud.identity_domain:
|
||||
state: 'absent'
|
||||
name: '{{ domain_name }}'
|
||||
ignore_errors: yes
|
||||
state: absent
|
||||
name: ansible_domain
|
||||
ignore_errors: true
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
idp_name: 'test-idp'
|
||||
idp_name_2: 'test-idp-2'
|
||||
idp_description: 'My example IDP'
|
||||
idp_description_2: 'My example Identity Provider'
|
||||
|
||||
domain_name: 'test-domain'
|
||||
expected_fields:
|
||||
- description
|
||||
- domain_id
|
||||
- id
|
||||
- is_enabled
|
||||
- name
|
||||
- remote_ids
|
||||
remote_ids_1:
|
||||
- 'https://auth.example.com/auth/realms/ExampleRealm'
|
||||
- 'https://auth.stage.example.com/auth/realms/ExampleRealm'
|
||||
- 'https://auth.example.com/auth/realms/ExampleRealm'
|
||||
- 'https://auth.stage.example.com/auth/realms/ExampleRealm'
|
||||
remote_ids_2:
|
||||
- 'https://auth.example.com/auth/realms/ExampleRealm'
|
||||
- 'https://auth.example.com/auth/realms/ExampleRealm'
|
||||
remote_ids_3:
|
||||
- 'https://auth.stage.example.com/auth/realms/ExampleRealm'
|
||||
- 'https://auth.stage.example.com/auth/realms/ExampleRealm'
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
role_name: ansible_keystone_role
|
||||
@@ -1,12 +0,0 @@
|
||||
---
|
||||
- name: Create keystone role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ role_name }}"
|
||||
|
||||
- name: Delete keystone role
|
||||
openstack.cloud.identity_role:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ role_name }}"
|
||||
22
ci/roles/loadbalancer/defaults/main.yml
Normal file
22
ci/roles/loadbalancer/defaults/main.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
expected_fields:
|
||||
- additional_vips
|
||||
- availability_zone
|
||||
- created_at
|
||||
- description
|
||||
- flavor_id
|
||||
- id
|
||||
- is_admin_state_up
|
||||
- listeners
|
||||
- name
|
||||
- operating_status
|
||||
- pools
|
||||
- project_id
|
||||
- provider
|
||||
- provisioning_status
|
||||
- tags
|
||||
- updated_at
|
||||
- vip_address
|
||||
- vip_network_id
|
||||
- vip_port_id
|
||||
- vip_qos_policy_id
|
||||
- vip_subnet_id
|
||||
322
ci/roles/loadbalancer/tasks/lb_modules.yml
Normal file
322
ci/roles/loadbalancer/tasks/lb_modules.yml
Normal file
@@ -0,0 +1,322 @@
|
||||
---
|
||||
- name: Create external network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
external: true
|
||||
name: ansible_external_network
|
||||
state: present
|
||||
|
||||
- name: Create external subnet
|
||||
openstack.cloud.subnet:
|
||||
cidr: 10.6.6.0/24
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_external_subnet
|
||||
network_name: ansible_external_network
|
||||
state: present
|
||||
|
||||
- name: Create internal network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_internal_network
|
||||
state: present
|
||||
|
||||
- name: Create internal subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
network_name: ansible_internal_network
|
||||
name: ansible_internal_subnet
|
||||
cidr: 10.7.7.0/24
|
||||
|
||||
- name: Create router
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
external_fixed_ips:
|
||||
- subnet: ansible_external_subnet
|
||||
ip: 10.6.6.10
|
||||
interfaces:
|
||||
- net: ansible_internal_network
|
||||
subnet: ansible_internal_subnet
|
||||
portip: 10.7.7.1
|
||||
name: ansible_router
|
||||
network: ansible_external_network
|
||||
state: present
|
||||
|
||||
- name: Create load-balancer
|
||||
openstack.cloud.loadbalancer:
|
||||
assign_floating_ip: true
|
||||
cloud: "{{ cloud }}"
|
||||
floating_ip_network: ansible_external_network
|
||||
name: ansible_lb
|
||||
state: present
|
||||
timeout: 450
|
||||
vip_subnet: ansible_internal_subnet
|
||||
register: load_balancer
|
||||
|
||||
- name: Create load-balancer listener
|
||||
openstack.cloud.lb_listener:
|
||||
cloud: "{{ cloud }}"
|
||||
load_balancer: ansible_lb
|
||||
name: ansible_listener
|
||||
protocol: HTTP
|
||||
protocol_port: 8080
|
||||
state: present
|
||||
register: listener
|
||||
|
||||
- name: Assert return values of lb_listener module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- "['allowed_cidrs', 'alpn_protocols', 'connection_limit', 'created_at', 'default_pool', 'default_pool_id',
|
||||
'default_tls_container_ref', 'description', 'id', 'insert_headers', 'is_admin_state_up', 'l7_policies',
|
||||
'load_balancer_id', 'load_balancers', 'name', 'operating_status', 'project_id', 'protocol', 'protocol_port',
|
||||
'provisioning_status', 'sni_container_refs', 'tags', 'timeout_client_data', 'timeout_member_connect',
|
||||
'timeout_member_data', 'timeout_tcp_inspect', 'tls_ciphers', 'tls_versions', 'updated_at'
|
||||
]|difference(listener.listener.keys())|length == 0"
|
||||
|
||||
- name: Create load-balancer listener again
|
||||
openstack.cloud.lb_listener:
|
||||
cloud: "{{ cloud }}"
|
||||
load_balancer: ansible_lb
|
||||
name: ansible_listener
|
||||
protocol: HTTP
|
||||
protocol_port: 8080
|
||||
state: present
|
||||
register: listener
|
||||
|
||||
- name: Assert return values of lb_listener module
|
||||
assert:
|
||||
that:
|
||||
- listener is not changed
|
||||
|
||||
- name: Update load-balancer listener description
|
||||
openstack.cloud.lb_listener:
|
||||
cloud: "{{ cloud }}"
|
||||
description: "Ansible load-balancer listener"
|
||||
load_balancer: ansible_lb
|
||||
name: ansible_listener
|
||||
protocol: HTTP
|
||||
protocol_port: 8080
|
||||
state: present
|
||||
register: listener
|
||||
|
||||
- name: Assert return values of lb_listener module
|
||||
assert:
|
||||
that:
|
||||
- listener.listener.description == "Ansible load-balancer listener"
|
||||
|
||||
- name: Create load-balancer pool
|
||||
openstack.cloud.lb_pool:
|
||||
cloud: "{{ cloud }}"
|
||||
lb_algorithm: ROUND_ROBIN
|
||||
listener: "{{ listener.listener.id }}"
|
||||
name: ansible_pool
|
||||
protocol: HTTP
|
||||
state: present
|
||||
register: pool
|
||||
|
||||
- name: Assert return values of lb_pool module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- "['alpn_protocols', 'created_at', 'description', 'health_monitor_id', 'id', 'is_admin_state_up', 'lb_algorithm',
|
||||
'listener_id', 'listeners', 'loadbalancer_id', 'loadbalancers', 'members','name', 'operating_status',
|
||||
'project_id', 'protocol', 'provisioning_status', 'session_persistence', 'tags', 'tls_ciphers', 'tls_enabled',
|
||||
'tls_versions', 'updated_at'
|
||||
]|difference(pool.pool.keys())|length == 0"
|
||||
|
||||
- name: Create load-balancer pool again
|
||||
openstack.cloud.lb_pool:
|
||||
cloud: "{{ cloud }}"
|
||||
lb_algorithm: ROUND_ROBIN
|
||||
listener: "{{ listener.listener.id }}"
|
||||
name: ansible_pool
|
||||
protocol: HTTP
|
||||
state: present
|
||||
register: pool
|
||||
|
||||
- name: Assert return values of lb_pool module
|
||||
assert:
|
||||
that:
|
||||
- pool is not changed
|
||||
|
||||
- name: Update load-balancer pool description
|
||||
openstack.cloud.lb_pool:
|
||||
cloud: "{{ cloud }}"
|
||||
description: "Ansible load-balancer pool"
|
||||
lb_algorithm: ROUND_ROBIN
|
||||
listener: "{{ listener.listener.id }}"
|
||||
name: ansible_pool
|
||||
protocol: HTTP
|
||||
state: present
|
||||
register: pool
|
||||
|
||||
- name: Assert return values of lb_pool module
|
||||
assert:
|
||||
that:
|
||||
- pool.pool.description == "Ansible load-balancer pool"
|
||||
|
||||
- name: Create load-balancer pool member
|
||||
openstack.cloud.lb_member:
|
||||
address: 10.7.7.42
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_member
|
||||
pool: ansible_pool
|
||||
protocol_port: 8080
|
||||
state: present
|
||||
register: member
|
||||
|
||||
- name: Assert return values of lb_member module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- "['address', 'backup', 'created_at', 'id', 'is_admin_state_up', 'monitor_address', 'monitor_port', 'name',
|
||||
'operating_status', 'project_id', 'protocol_port', 'provisioning_status', 'subnet_id', 'tags', 'updated_at',
|
||||
'weight'
|
||||
]|difference(member.member.keys())|length == 0"
|
||||
|
||||
- name: Create load-balancer pool member again
|
||||
openstack.cloud.lb_member:
|
||||
address: 10.7.7.42
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_member
|
||||
pool: ansible_pool
|
||||
protocol_port: 8080
|
||||
state: present
|
||||
register: member
|
||||
|
||||
- name: Assert return values of lb_member module
|
||||
assert:
|
||||
that:
|
||||
- member is not changed
|
||||
|
||||
- name: Update load-balancer pool member weight
|
||||
openstack.cloud.lb_member:
|
||||
address: 10.7.7.42
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_member
|
||||
pool: ansible_pool
|
||||
protocol_port: 8080
|
||||
state: present
|
||||
weight: 42
|
||||
register: member
|
||||
|
||||
- name: Assert return values of lb_member module
|
||||
assert:
|
||||
that:
|
||||
- member.member.weight == 42
|
||||
|
||||
- name: Create load-balancer health monitor
|
||||
openstack.cloud.lb_health_monitor:
|
||||
cloud: "{{ cloud }}"
|
||||
delay: 10
|
||||
health_monitor_timeout: 5
|
||||
max_retries: 3
|
||||
name: ansible_health_monitor
|
||||
pool: ansible_pool
|
||||
state: present
|
||||
register: health_monitor
|
||||
|
||||
- name: Assert return values of lb_health_monitor module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- "['created_at', 'delay', 'expected_codes', 'http_method', 'id', 'is_admin_state_up', 'max_retries',
|
||||
'max_retries_down', 'name', 'operating_status', 'pool_id', 'pools', 'project_id', 'provisioning_status',
|
||||
'tags', 'timeout', 'type', 'updated_at', 'url_path'
|
||||
]|difference(health_monitor.health_monitor.keys())|length == 0"
|
||||
|
||||
- name: Create load-balancer health monitor again
|
||||
openstack.cloud.lb_health_monitor:
|
||||
cloud: "{{ cloud }}"
|
||||
delay: 10
|
||||
health_monitor_timeout: 5
|
||||
max_retries: 3
|
||||
name: ansible_health_monitor
|
||||
pool: ansible_pool
|
||||
state: present
|
||||
register: health_monitor
|
||||
|
||||
- name: Assert return values of lb_health_monitor module
|
||||
assert:
|
||||
that:
|
||||
- health_monitor is not changed
|
||||
|
||||
- name: Update load-balancer health monitor delay
|
||||
openstack.cloud.lb_health_monitor:
|
||||
cloud: "{{ cloud }}"
|
||||
delay: 1337
|
||||
health_monitor_timeout: 5
|
||||
max_retries: 3
|
||||
name: ansible_health_monitor
|
||||
pool: ansible_pool
|
||||
state: present
|
||||
register: health_monitor
|
||||
|
||||
- name: Assert return values of lb_health_monitor module
|
||||
assert:
|
||||
that:
|
||||
- health_monitor.health_monitor.delay == 1337
|
||||
|
||||
- name: Delete load-balancer health monitor
|
||||
openstack.cloud.lb_health_monitor:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_health_monitor
|
||||
state: absent
|
||||
|
||||
- name: Delete load-balancer pool member
|
||||
openstack.cloud.lb_member:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_member
|
||||
pool: ansible_pool
|
||||
state: absent
|
||||
|
||||
- name: Delete load-balancer pool
|
||||
openstack.cloud.lb_pool:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_pool
|
||||
state: absent
|
||||
|
||||
- name: Delete load-balancer listener
|
||||
openstack.cloud.lb_listener:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_listener
|
||||
state: absent
|
||||
|
||||
- name: Delete load-balancer
|
||||
openstack.cloud.loadbalancer:
|
||||
cloud: "{{ cloud }}"
|
||||
delete_floating_ip: true
|
||||
name: ansible_lb
|
||||
state: absent
|
||||
timeout: 150
|
||||
|
||||
- name: Delete router
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_router
|
||||
state: absent
|
||||
|
||||
- name: Delete internal subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_internal_subnet
|
||||
state: absent
|
||||
|
||||
- name: Delete internal network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_internal_network
|
||||
state: absent
|
||||
|
||||
- name: Delete external subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_external_subnet
|
||||
state: absent
|
||||
|
||||
- name: Delete external network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_external_network
|
||||
state: absent
|
||||
286
ci/roles/loadbalancer/tasks/main.yml
Normal file
286
ci/roles/loadbalancer/tasks/main.yml
Normal file
@@ -0,0 +1,286 @@
|
||||
---
|
||||
- name: Download Amphora tarball
|
||||
get_url:
|
||||
url: "https://tarballs.openstack.org/octavia/test-images/test-only-amphora-x64-haproxy-ubuntu-bionic.qcow2"
|
||||
dest: /tmp/test-only-amphora-x64-haproxy-ubuntu-bionic.qcow2
|
||||
|
||||
- name: Upload Amphora image for Octavia to test load-balancers
|
||||
openstack.cloud.image:
|
||||
cloud: "{{ cloud }}"
|
||||
container_format: bare
|
||||
disk_format: qcow2
|
||||
filename: /tmp/test-only-amphora-x64-haproxy-ubuntu-bionic.qcow2
|
||||
is_public: false
|
||||
name: test-only-amphora-x64-haproxy-ubuntu-bionic
|
||||
owner: service
|
||||
properties:
|
||||
hw_architecture: x86_64
|
||||
hw_rng_model: virtio
|
||||
state: present
|
||||
tags:
|
||||
- amphora
|
||||
|
||||
- name: Create external network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
external: true
|
||||
name: ansible_external_network
|
||||
state: present
|
||||
register: external_network
|
||||
|
||||
- name: Create external subnet
|
||||
openstack.cloud.subnet:
|
||||
cidr: 10.6.6.0/24
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_external_subnet
|
||||
network_name: ansible_external_network
|
||||
state: present
|
||||
|
||||
- name: Create internal network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_internal_network
|
||||
state: present
|
||||
|
||||
- name: Create internal subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
network_name: ansible_internal_network
|
||||
name: ansible_internal_subnet
|
||||
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 router 1
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
external_fixed_ips:
|
||||
- subnet: ansible_external_subnet
|
||||
ip: 10.6.6.10
|
||||
interfaces:
|
||||
- net: ansible_internal_network
|
||||
subnet: ansible_internal_subnet
|
||||
portip: 192.168.0.1
|
||||
name: ansible_router1
|
||||
network: ansible_external_network
|
||||
state: present
|
||||
|
||||
- name: Create load-balancer
|
||||
openstack.cloud.loadbalancer:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_lb
|
||||
vip_subnet: ansible_internal_subnet
|
||||
timeout: 1200
|
||||
register: load_balancer
|
||||
|
||||
- name: Assert return values of loadbalancer module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(load_balancer.load_balancer.keys())|length == 0
|
||||
|
||||
- name: Create load-balancer again
|
||||
openstack.cloud.loadbalancer:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_lb
|
||||
vip_subnet: ansible_internal_subnet
|
||||
timeout: 1200
|
||||
register: load_balancer
|
||||
|
||||
- name: Assert return values of loadbalancer module
|
||||
assert:
|
||||
that:
|
||||
- load_balancer is not changed
|
||||
|
||||
- name: Update load-balancer description
|
||||
openstack.cloud.loadbalancer:
|
||||
cloud: "{{ cloud }}"
|
||||
description: "Ansible load-balancer"
|
||||
state: present
|
||||
name: ansible_lb
|
||||
vip_subnet: ansible_internal_subnet
|
||||
timeout: 1200
|
||||
register: load_balancer
|
||||
|
||||
- name: Assert return values of loadbalancer module
|
||||
assert:
|
||||
that:
|
||||
- load_balancer.load_balancer.description == "Ansible load-balancer"
|
||||
|
||||
- name: Delete load-balancer
|
||||
openstack.cloud.loadbalancer:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_lb
|
||||
state: absent
|
||||
timeout: 150
|
||||
|
||||
- name: Create load-balancer with floating ip address
|
||||
openstack.cloud.loadbalancer:
|
||||
assign_floating_ip: true
|
||||
cloud: "{{ cloud }}"
|
||||
# Help Octavia to find a external network which is connected to ansible_internal_subnet via a router
|
||||
floating_ip_network: ansible_external_network
|
||||
name: ansible_lb
|
||||
state: present
|
||||
timeout: 1200
|
||||
vip_subnet: ansible_internal_subnet
|
||||
register: load_balancer
|
||||
|
||||
- name: Assert return values of loadbalancer module
|
||||
assert:
|
||||
that:
|
||||
- "'floating_ip' in load_balancer.keys()"
|
||||
- load_balancer.load_balancer.vip_address == load_balancer.floating_ip.fixed_ip_address
|
||||
|
||||
- name: Delete load-balancer with floating ip address
|
||||
openstack.cloud.loadbalancer:
|
||||
cloud: "{{ cloud }}"
|
||||
delete_floating_ip: true
|
||||
name: ansible_lb
|
||||
state: absent
|
||||
timeout: 150
|
||||
|
||||
- name: List all floating ips
|
||||
openstack.cloud.floating_ip_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: floating_ips
|
||||
|
||||
- name: Assert load-balancer's floating ip has been deleted
|
||||
assert:
|
||||
that:
|
||||
- load_balancer.floating_ip.floating_ip_address not in
|
||||
floating_ips.floating_ips|map(attribute='floating_ip_address')|sort|list
|
||||
|
||||
- name: Create load-balancer with floating ip address from specific network
|
||||
openstack.cloud.loadbalancer:
|
||||
assign_floating_ip: true
|
||||
cloud: "{{ cloud }}"
|
||||
floating_ip_network: ansible_external_network
|
||||
name: ansible_lb
|
||||
state: present
|
||||
timeout: 1200
|
||||
vip_subnet: ansible_internal_subnet
|
||||
register: load_balancer
|
||||
|
||||
- name: Assert return values of loadbalancer module
|
||||
assert:
|
||||
that:
|
||||
- load_balancer.floating_ip.floating_network_id == external_network.network.id
|
||||
|
||||
- name: Create load-balancer with floating ip address from specific network again
|
||||
openstack.cloud.loadbalancer:
|
||||
assign_floating_ip: true
|
||||
cloud: "{{ cloud }}"
|
||||
floating_ip_network: ansible_external_network
|
||||
name: ansible_lb
|
||||
state: present
|
||||
timeout: 1200
|
||||
vip_subnet: ansible_internal_subnet
|
||||
register: load_balancer
|
||||
|
||||
- name: Assert return values of loadbalancer module
|
||||
assert:
|
||||
that:
|
||||
- load_balancer is not changed
|
||||
|
||||
# TODO: Replace with appropriate Ansible module once available
|
||||
- name: Disassociate floating ip from load-balancer
|
||||
command: >
|
||||
openstack --os-cloud={{ cloud }} floating ip unset --port {{ load_balancer.floating_ip.floating_ip_address }}
|
||||
|
||||
- name: Reassign floating ip address to load-balancer
|
||||
openstack.cloud.loadbalancer:
|
||||
assign_floating_ip: true
|
||||
cloud: "{{ cloud }}"
|
||||
floating_ip_network: ansible_external_network
|
||||
name: ansible_lb
|
||||
state: present
|
||||
timeout: 1200
|
||||
vip_subnet: ansible_internal_subnet
|
||||
register: load_balancer2
|
||||
|
||||
- name: Assert return values of loadbalancer module
|
||||
assert:
|
||||
that:
|
||||
- load_balancer2.floating_ip.floating_network_id == external_network.network.id
|
||||
- load_balancer.floating_ip.floating_ip_address == load_balancer2.floating_ip.floating_ip_address
|
||||
|
||||
- name: Reassign specific floating ip address to load-balancer
|
||||
openstack.cloud.loadbalancer:
|
||||
assign_floating_ip: true
|
||||
cloud: "{{ cloud }}"
|
||||
floating_ip_address: 10.6.6.42
|
||||
floating_ip_network: ansible_external_network
|
||||
name: ansible_lb
|
||||
state: present
|
||||
timeout: 1200
|
||||
vip_subnet: ansible_internal_subnet
|
||||
register: load_balancer
|
||||
|
||||
- name: Assert return values of loadbalancer module
|
||||
assert:
|
||||
that:
|
||||
- load_balancer.floating_ip.floating_network_id == external_network.network.id
|
||||
- load_balancer.floating_ip.floating_ip_address == '10.6.6.42'
|
||||
|
||||
- name: Disassociate floating ip address with load-balancer
|
||||
openstack.cloud.loadbalancer:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_lb
|
||||
state: present
|
||||
timeout: 1200
|
||||
vip_subnet: ansible_internal_subnet
|
||||
register: load_balancer
|
||||
|
||||
- name: Assert return values of loadbalancer module
|
||||
assert:
|
||||
that:
|
||||
- "'floating_ip' not in load_balancer.keys()"
|
||||
|
||||
- name: Delete load-balancer
|
||||
openstack.cloud.loadbalancer:
|
||||
cloud: "{{ cloud }}"
|
||||
delete_floating_ip: true
|
||||
name: ansible_lb
|
||||
state: absent
|
||||
timeout: 150
|
||||
|
||||
- name: Delete router 1
|
||||
openstack.cloud.router:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_router1
|
||||
state: absent
|
||||
|
||||
- name: Delete internal subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_internal_subnet
|
||||
state: absent
|
||||
|
||||
- name: Delete internal network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_internal_network
|
||||
state: absent
|
||||
|
||||
- name: Delete external subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_external_subnet
|
||||
state: absent
|
||||
|
||||
- name: Delete external network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_external_network
|
||||
state: absent
|
||||
|
||||
- import_tasks: lb_modules.yml
|
||||
1
ci/roles/logging/defaults/main.yaml
Normal file
1
ci/roles/logging/defaults/main.yaml
Normal file
@@ -0,0 +1 @@
|
||||
sdk_log_file_path: "{{ playbook_dir }}/sdk.log"
|
||||
15
ci/roles/logging/tasks/main.yaml
Normal file
15
ci/roles/logging/tasks/main.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
- name: Trigger flavor listing to create logs
|
||||
openstack.cloud.compute_flavor_info:
|
||||
cloud: "{{ cloud }}"
|
||||
sdk_log_path: "{{ sdk_log_file_path }}"
|
||||
sdk_log_level: "DEBUG"
|
||||
|
||||
- name: Read openstacksdk's log file
|
||||
ansible.builtin.slurp:
|
||||
src: "{{ sdk_log_file_path }}"
|
||||
register: log
|
||||
|
||||
- name: Print contents of openstacksdk's log
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ log['content'] | b64decode }}"
|
||||
@@ -1,3 +1,35 @@
|
||||
expected_fields:
|
||||
- availability_zone_hints
|
||||
- availability_zones
|
||||
- created_at
|
||||
- description
|
||||
- dns_domain
|
||||
- id
|
||||
- ipv4_address_scope_id
|
||||
- ipv6_address_scope_id
|
||||
- is_admin_state_up
|
||||
- is_default
|
||||
- is_port_security_enabled
|
||||
- is_router_external
|
||||
- is_shared
|
||||
- is_vlan_transparent
|
||||
- mtu
|
||||
- name
|
||||
- project_id
|
||||
- provider_network_type
|
||||
- provider_physical_network
|
||||
- provider_segmentation_id
|
||||
- qos_policy_id
|
||||
- revision_number
|
||||
- segments
|
||||
- status
|
||||
- subnet_ids
|
||||
- tags
|
||||
- updated_at
|
||||
dns_domain: example.opendev.org
|
||||
mtu: 1250
|
||||
network_name: shade_network
|
||||
network_name_newparams: newparams_network
|
||||
network_name_updates: update_network
|
||||
network_shared: false
|
||||
network_external: false
|
||||
port_security_enabled: false
|
||||
|
||||
@@ -1,14 +1,170 @@
|
||||
---
|
||||
- name: Create network
|
||||
- name: Create network - generic
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name }}"
|
||||
state: present
|
||||
shared: "{{ network_shared }}"
|
||||
external: "{{ network_external }}"
|
||||
external: false
|
||||
register: infonet
|
||||
|
||||
- name: Delete network
|
||||
openstack.cloud.network:
|
||||
- name: Check output of creating network
|
||||
assert:
|
||||
that:
|
||||
- infonet.network is defined
|
||||
- item in infonet.network
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- name: Gather networks info
|
||||
openstack.cloud.networks_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ infonet.network.id }}"
|
||||
register: result
|
||||
|
||||
- name: Check output of network info
|
||||
# TODO: Remove ignore_errors once SDK's search_networks() (re)implemented searching by id
|
||||
ignore_errors: true
|
||||
assert:
|
||||
that:
|
||||
- result.networks|length == 1
|
||||
- infonet.network.id == result.networks[0].id
|
||||
|
||||
- name: Gather networks info - generic
|
||||
openstack.cloud.networks_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name }}"
|
||||
filters:
|
||||
shared: "{{ network_shared|string|capitalize }}"
|
||||
register: result
|
||||
|
||||
- name: Check output of network info
|
||||
assert:
|
||||
that:
|
||||
- item in result.networks[0]
|
||||
loop: "{{ expected_fields }}"
|
||||
|
||||
- name: Gather networks info
|
||||
openstack.cloud.networks_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name }}"
|
||||
filters:
|
||||
shared: "False"
|
||||
register: result
|
||||
|
||||
- name: Verify networks info - generic
|
||||
assert:
|
||||
that:
|
||||
- result.networks.0.name == network_name
|
||||
- "'is_shared' in result.networks.0"
|
||||
- result.networks.0['is_shared']|lower == network_shared|lower
|
||||
- "'is_router_external' in result.networks.0"
|
||||
- not (result.networks[0]['is_router_external'] | bool)
|
||||
|
||||
- name: Create network - with new SDK params
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name_newparams }}"
|
||||
state: present
|
||||
shared: "{{ network_shared }}"
|
||||
external: false
|
||||
mtu: "{{ mtu }}"
|
||||
port_security_enabled: "{{ port_security_enabled }}"
|
||||
register: result_create_nw_with_new_params
|
||||
ignore_errors: true
|
||||
|
||||
- name: Gather networks info - with new SDK params
|
||||
openstack.cloud.networks_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name_newparams }}"
|
||||
register: result_newparams
|
||||
|
||||
- name: Verify networks info - with new SDK params
|
||||
assert:
|
||||
that:
|
||||
- result_newparams.networks.0.name == network_name_newparams
|
||||
- result_newparams.networks.0.mtu == mtu
|
||||
- "'is_port_security_enabled' in result_newparams.networks.0"
|
||||
- result_newparams.networks.0['is_port_security_enabled'] == port_security_enabled
|
||||
|
||||
- name: Delete network - generic and with new SDK params
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
with_items:
|
||||
- "{{ network_name }}"
|
||||
- "{{ network_name_newparams }}"
|
||||
|
||||
- name: Gather networks info - deleted
|
||||
openstack.cloud.networks_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name }}"
|
||||
register: result_nonet
|
||||
|
||||
- name: Verify networks info - deleted
|
||||
assert:
|
||||
that:
|
||||
- result_nonet.networks == []
|
||||
|
||||
- name: Create network - updates
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name_updates }}"
|
||||
state: present
|
||||
shared: "{{ network_shared }}"
|
||||
external: false
|
||||
mtu: "{{ mtu }}"
|
||||
port_security_enabled: "{{ port_security_enabled }}"
|
||||
register: result_create_nw_for_updates
|
||||
|
||||
- name: Update network - update failure
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name_updates }}"
|
||||
state: present
|
||||
shared: "{{ network_shared }}"
|
||||
external: false
|
||||
mtu: "{{ mtu }}"
|
||||
port_security_enabled: "{{ port_security_enabled }}"
|
||||
# You cannot update this property.
|
||||
provider_physical_network: cannot_be_updated
|
||||
ignore_errors: true
|
||||
register: result_nw_update_failure
|
||||
|
||||
- name: Verify networks info - update fail
|
||||
assert:
|
||||
that:
|
||||
- result_nw_update_failure is failed
|
||||
|
||||
- name: Update network - update success
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name_updates }}"
|
||||
state: present
|
||||
shared: "{{ network_shared }}"
|
||||
external: false
|
||||
# NOTE: This property should be updated
|
||||
mtu: "{{ mtu - 50 }}"
|
||||
# NOTE: This property should be updated
|
||||
port_security_enabled: "{{ not port_security_enabled }}"
|
||||
register: result_nw_update_success
|
||||
|
||||
- name: Gather networks info - updates
|
||||
openstack.cloud.networks_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name_updates }}"
|
||||
register: result_network_updates_info
|
||||
|
||||
- name: Verify networks info - update success
|
||||
assert:
|
||||
that:
|
||||
- result_nw_update_success is changed
|
||||
- result_network_updates_info.networks.0.name == network_name_updates
|
||||
- result_network_updates_info.networks.0.mtu == mtu - 50
|
||||
- result_network_updates_info.networks.0['is_port_security_enabled'] == (not port_security_enabled)
|
||||
|
||||
- name: Delete network - updates
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name_updates }}"
|
||||
state: absent
|
||||
|
||||
10
ci/roles/neutron_rbac_policy/defaults/main.yml
Normal file
10
ci/roles/neutron_rbac_policy/defaults/main.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
expected_fields:
|
||||
- action
|
||||
- id
|
||||
- name
|
||||
- object_id
|
||||
- object_type
|
||||
- project_id
|
||||
- target_project_id
|
||||
- tenant_id
|
||||
all_project_symbol: '*'
|
||||
123
ci/roles/neutron_rbac_policy/tasks/main.yml
Normal file
123
ci/roles/neutron_rbac_policy/tasks/main.yml
Normal file
@@ -0,0 +1,123 @@
|
||||
---
|
||||
- name: Create source project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_source_project
|
||||
description: Source project for network RBAC test
|
||||
domain: default
|
||||
is_enabled: True
|
||||
register: source_project
|
||||
|
||||
- name: Create network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "ansible_network"
|
||||
state: present
|
||||
project: "{{ source_project.project.id }}"
|
||||
shared: false
|
||||
external: true
|
||||
register: network
|
||||
|
||||
- name: Create target project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_target_project
|
||||
description: Target project for network RBAC test
|
||||
domain_id: default
|
||||
enabled: True
|
||||
register: target_project
|
||||
|
||||
- name: Create a new network RBAC policy
|
||||
openstack.cloud.neutron_rbac_policy:
|
||||
cloud: "{{ cloud }}"
|
||||
object_id: "{{ network.network.id }}"
|
||||
object_type: 'network'
|
||||
action: 'access_as_shared'
|
||||
target_project_id: "{{ target_project.project.id }}"
|
||||
project_id: "{{ source_project.project.id }}"
|
||||
register: rbac_policy
|
||||
|
||||
- name: Assert return values of neutron_rbac_policy module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(rbac_policy.rbac_policy.keys())|length == 0
|
||||
|
||||
- name: Get all rbac policies for {{ source_project.project.name }} - after creation
|
||||
openstack.cloud.neutron_rbac_policies_info:
|
||||
cloud: "{{ cloud }}"
|
||||
project: "{{ source_project.project.id }}"
|
||||
register: rbac_policies
|
||||
|
||||
- name: Assert return values of neutron_rbac_policy_info module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(rbac_policies.rbac_policies[0].keys())|length == 0
|
||||
|
||||
- name: Verify policy exists - after creation
|
||||
assert:
|
||||
that:
|
||||
- rbac_policy.rbac_policy.id in
|
||||
( rbac_policies.rbac_policies | map(attribute='id') | list )
|
||||
|
||||
- name: Delete RBAC policy
|
||||
openstack.cloud.neutron_rbac_policy:
|
||||
cloud: "{{ cloud }}"
|
||||
id: "{{ rbac_policy.rbac_policy.id }}"
|
||||
state: absent
|
||||
|
||||
- name: Create a new network RBAC policy by targeting all projects
|
||||
openstack.cloud.neutron_rbac_policy:
|
||||
cloud: "{{ cloud }}"
|
||||
object_id: "{{ network.network.id }}"
|
||||
object_type: 'network'
|
||||
action: 'access_as_shared'
|
||||
target_all_project: true
|
||||
project_id: "{{ source_project.project.id }}"
|
||||
register: rbac_policy
|
||||
|
||||
- name: Assert return values of neutron_rbac_policy module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(rbac_policy.rbac_policy.keys())|length == 0
|
||||
- rbac_policy.rbac_policy.target_project_id == all_project_symbol
|
||||
|
||||
- name: Delete RBAC policy
|
||||
openstack.cloud.neutron_rbac_policy:
|
||||
cloud: "{{ cloud }}"
|
||||
id: "{{ rbac_policy.rbac_policy.id }}"
|
||||
state: absent
|
||||
|
||||
- name: Get all rbac policies for {{ source_project.project.name }} - after deletion
|
||||
openstack.cloud.neutron_rbac_policies_info:
|
||||
cloud: "{{ cloud }}"
|
||||
project: "{{ source_project.project.id }}"
|
||||
register: rbac_policies_remaining
|
||||
|
||||
- name: Verify policy does not exist - after deletion
|
||||
assert:
|
||||
that:
|
||||
- rbac_policy.rbac_policy.id not in
|
||||
( rbac_policies_remaining.rbac_policies | map(attribute='id') | list )
|
||||
|
||||
- name: Delete target project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_target_project
|
||||
|
||||
- name: Delete network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "ansible_network"
|
||||
state: absent
|
||||
|
||||
- name: Delete source project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_source_project
|
||||
@@ -1,53 +0,0 @@
|
||||
---
|
||||
- name: Create public flavor
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_public_flavor
|
||||
is_public: True
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
ephemeral: 10
|
||||
swap: 1
|
||||
flavorid: 12345
|
||||
|
||||
- name: Delete public flavor
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_public_flavor
|
||||
|
||||
- name: Create private flavor
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_private_flavor
|
||||
is_public: False
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
ephemeral: 10
|
||||
swap: 1
|
||||
flavorid: 12345
|
||||
|
||||
- name: Delete private flavor
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_private_flavor
|
||||
|
||||
- name: Create flavor (defaults)
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_defaults_flavor
|
||||
ram: 1024
|
||||
vcpus: 1
|
||||
disk: 10
|
||||
|
||||
- name: Delete flavor (defaults)
|
||||
openstack.cloud.compute_flavor:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_defaults_flavor
|
||||
32
ci/roles/object/defaults/main.yml
Normal file
32
ci/roles/object/defaults/main.yml
Normal file
@@ -0,0 +1,32 @@
|
||||
expected_fields:
|
||||
- accept_ranges
|
||||
- access_control_allow_origin
|
||||
- content_disposition
|
||||
- content_encoding
|
||||
- content_length
|
||||
- content_type
|
||||
- copy_from
|
||||
- delete_after
|
||||
- delete_at
|
||||
- etag
|
||||
- expires_at
|
||||
- id
|
||||
- if_match
|
||||
- if_modified_since
|
||||
- if_none_match
|
||||
- if_unmodified_since
|
||||
- is_content_type_detected
|
||||
- is_newest
|
||||
- is_static_large_object
|
||||
- last_modified_at
|
||||
- manifest
|
||||
- metadata
|
||||
- multipart_manifest
|
||||
- name
|
||||
- object_manifest
|
||||
- range
|
||||
- signature
|
||||
- symlink_target
|
||||
- symlink_target_account
|
||||
- timestamp
|
||||
- transfer_encoding
|
||||
@@ -1,37 +1,76 @@
|
||||
---
|
||||
- name: Create a test object file
|
||||
shell: mktemp
|
||||
register: tmp_file
|
||||
|
||||
- name: Create container
|
||||
openstack.cloud.object:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
container: ansible_container
|
||||
container_access: private
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_container
|
||||
|
||||
- name: Put object
|
||||
- name: Create object from data
|
||||
openstack.cloud.object:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_object
|
||||
filename: "{{ tmp_file.stdout }}"
|
||||
container: ansible_container
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_object
|
||||
data: "this is a test"
|
||||
container: ansible_container
|
||||
register: object
|
||||
|
||||
- name: Assert return values of object module
|
||||
assert:
|
||||
that:
|
||||
- object.object.id == "ansible_object"
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(object.object.keys())|length == 0
|
||||
|
||||
- name: Delete object
|
||||
openstack.cloud.object:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_object
|
||||
container: ansible_container
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_object
|
||||
container: ansible_container
|
||||
|
||||
- name: Create object from file
|
||||
block:
|
||||
- name: Create temporary data file
|
||||
ansible.builtin.tempfile:
|
||||
register: tmp_file
|
||||
|
||||
- name: Populate data file
|
||||
ansible.builtin.copy:
|
||||
content: "this is a test"
|
||||
dest: "{{ tmp_file.path }}"
|
||||
|
||||
- name: Create object from data file
|
||||
openstack.cloud.object:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_object
|
||||
filename: "{{ tmp_file.path }}"
|
||||
container: ansible_container
|
||||
register: object
|
||||
|
||||
always:
|
||||
- name: Remove temporary data file
|
||||
ansible.builtin.file:
|
||||
path: "{{ tmp_file.path }}"
|
||||
state: absent
|
||||
when: tmp_file is defined and 'path' in tmp_file
|
||||
|
||||
- name: Assert return values of object module
|
||||
assert:
|
||||
that:
|
||||
- object.object.id == "ansible_object"
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(object.object.keys())|length == 0
|
||||
|
||||
- name: Delete object
|
||||
openstack.cloud.object:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_object
|
||||
container: ansible_container
|
||||
|
||||
- name: Delete container
|
||||
openstack.cloud.object:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
container: ansible_container
|
||||
|
||||
- name: Delete test object file
|
||||
file:
|
||||
name: "{{ tmp_file.stdout }}"
|
||||
state: absent
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_container
|
||||
|
||||
22
ci/roles/object_container/defaults/main.yml
Normal file
22
ci/roles/object_container/defaults/main.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
expected_fields:
|
||||
- bytes
|
||||
- bytes_used
|
||||
- content_type
|
||||
- count
|
||||
- history_location
|
||||
- id
|
||||
- if_none_match
|
||||
- is_content_type_detected
|
||||
- is_newest
|
||||
- meta_temp_url_key
|
||||
- meta_temp_url_key_2
|
||||
- metadata
|
||||
- name
|
||||
- object_count
|
||||
- read_ACL
|
||||
- storage_policy
|
||||
- sync_key
|
||||
- sync_to
|
||||
- timestamp
|
||||
- versions_location
|
||||
- write_ACL
|
||||
108
ci/roles/object_container/tasks/main.yml
Normal file
108
ci/roles/object_container/tasks/main.yml
Normal file
@@ -0,0 +1,108 @@
|
||||
---
|
||||
- name: Create an empty container with public access
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_container
|
||||
read_ACL: ".r:*,.rlistings"
|
||||
register: container
|
||||
|
||||
- name: Assert return values of container module
|
||||
assert:
|
||||
that:
|
||||
- container is changed
|
||||
- container.container.name == "ansible_container"
|
||||
- container.container.read_ACL == ".r:*,.rlistings"
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(container.container.keys())|length == 0
|
||||
|
||||
- name: Set container metadata aka container properties
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_container
|
||||
metadata:
|
||||
'Cache-Control': 'no-cache'
|
||||
'foo': 'bar'
|
||||
register: container
|
||||
|
||||
- name: Verify container metadata was set
|
||||
assert:
|
||||
that:
|
||||
- container is changed
|
||||
- ('cache-control' in container.container.metadata.keys()|map('lower'))
|
||||
- container.container.metadata['foo'] == 'bar'
|
||||
|
||||
- name: Update container metadata
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_container
|
||||
metadata:
|
||||
'foo': 'baz'
|
||||
register: container
|
||||
|
||||
- name: Verify container metadata was updated
|
||||
assert:
|
||||
that:
|
||||
- container is changed
|
||||
- ('cache-control' in container.container.metadata.keys()|map('lower'))
|
||||
- container.container.metadata['foo'] == 'baz'
|
||||
|
||||
- name: Update a container
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_container
|
||||
delete_metadata_keys:
|
||||
- 'Cache-Control'
|
||||
read_ACL: ""
|
||||
register: container
|
||||
|
||||
- name: Verify updated container
|
||||
assert:
|
||||
that:
|
||||
- container is changed
|
||||
- ('cache-control' not in container.container.metadata.keys()|map('lower'))
|
||||
- "container.container.metadata == {'foo': 'baz'}"
|
||||
- container.container.read_ACL is none or container.container.read_ACL == ""
|
||||
|
||||
- name: Delete container
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_container
|
||||
state: absent
|
||||
register: container
|
||||
|
||||
- name: Verify container was deleted
|
||||
assert:
|
||||
that:
|
||||
- container is changed
|
||||
|
||||
- name: Delete container again
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_container
|
||||
state: absent
|
||||
register: container
|
||||
|
||||
- name: Verify container was not deleted again
|
||||
assert:
|
||||
that:
|
||||
- container is not changed
|
||||
|
||||
- name: Create another container for recursive deletion
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_container2
|
||||
|
||||
- name: Load an object into container
|
||||
openstack.cloud.object:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_object
|
||||
data: "this is another test"
|
||||
container: ansible_container2
|
||||
|
||||
- name: Delete container recursively
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_container2
|
||||
delete_with_all_objects: true
|
||||
37
ci/roles/object_containers_info/defaults/main.yml
Normal file
37
ci/roles/object_containers_info/defaults/main.yml
Normal file
@@ -0,0 +1,37 @@
|
||||
---
|
||||
|
||||
test_container_unprefixed_name: ansible-test-container
|
||||
test_container_prefixed_prefix: ansible-prefixed-test-container
|
||||
test_container_prefixed_num: 2
|
||||
|
||||
test_object_data: "Hello, world!"
|
||||
|
||||
expected_fields_single:
|
||||
- bytes
|
||||
- bytes_used
|
||||
- content_type
|
||||
- count
|
||||
- history_location
|
||||
- id
|
||||
- if_none_match
|
||||
- is_content_type_detected
|
||||
- is_newest
|
||||
- meta_temp_url_key
|
||||
- meta_temp_url_key_2
|
||||
- name
|
||||
- object_count
|
||||
- read_ACL
|
||||
- storage_policy
|
||||
- sync_key
|
||||
- sync_to
|
||||
- timestamp
|
||||
- versions_location
|
||||
- write_ACL
|
||||
|
||||
expected_fields_multiple:
|
||||
- bytes
|
||||
- bytes_used
|
||||
- count
|
||||
- id
|
||||
- name
|
||||
- object_count
|
||||
124
ci/roles/object_containers_info/tasks/main.yml
Normal file
124
ci/roles/object_containers_info/tasks/main.yml
Normal file
@@ -0,0 +1,124 @@
|
||||
---
|
||||
|
||||
- name: Generate list of containers to create
|
||||
ansible.builtin.set_fact:
|
||||
all_test_containers: >-
|
||||
{{
|
||||
[test_container_unprefixed_name]
|
||||
+ (
|
||||
[test_container_prefixed_prefix + '-']
|
||||
| product(range(test_container_prefixed_num) | map('string'))
|
||||
| map('join', '')
|
||||
)
|
||||
}}
|
||||
|
||||
- name: Run checks
|
||||
block:
|
||||
|
||||
- name: Create all containers
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ item }}"
|
||||
read_ACL: ".r:*,.rlistings"
|
||||
loop: "{{ all_test_containers }}"
|
||||
|
||||
- name: Create an object in all containers
|
||||
openstack.cloud.object:
|
||||
cloud: "{{ cloud }}"
|
||||
container: "{{ item }}"
|
||||
name: hello.txt
|
||||
data: "{{ test_object_data }}"
|
||||
loop: "{{ all_test_containers }}"
|
||||
|
||||
- name: Fetch single containers by name
|
||||
openstack.cloud.object_containers_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ item }}"
|
||||
register: single_containers
|
||||
loop: "{{ all_test_containers }}"
|
||||
|
||||
- name: Check that all fields are returned for single containers
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- (item.containers | length) == 1
|
||||
- item.containers[0].name == item.item
|
||||
- item.containers[0].bytes == (test_object_data | length)
|
||||
- item.containers[0].read_ACL == ".r:*,.rlistings"
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- (expected_fields_single | difference(item.containers[0].keys()) | length) == 0
|
||||
quiet: true
|
||||
loop: "{{ single_containers.results }}"
|
||||
loop_control:
|
||||
label: "{{ item.item }}"
|
||||
|
||||
- name: Fetch multiple containers by prefix
|
||||
openstack.cloud.object_containers_info:
|
||||
cloud: "{{ cloud }}"
|
||||
prefix: "{{ test_container_prefixed_prefix }}"
|
||||
register: multiple_containers
|
||||
|
||||
- name: Check that the correct number of prefixed containers were returned
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- (multiple_containers.containers | length) == test_container_prefixed_num
|
||||
fail_msg: >-
|
||||
Incorrect number of containers found
|
||||
(found {{ multiple_containers.containers | length }},
|
||||
expected {{ test_container_prefixed_num }})
|
||||
quiet: true
|
||||
|
||||
- name: Check that all prefixed containers exist
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- >-
|
||||
(test_container_prefixed_prefix + '-' + (item | string))
|
||||
in (multiple_containers.containers | map(attribute='name'))
|
||||
fail_msg: "Container not found: {{ test_container_prefixed_prefix + '-' + (item | string) }}"
|
||||
quiet: true
|
||||
loop: "{{ range(test_container_prefixed_num) | list }}"
|
||||
loop_control:
|
||||
label: "{{ test_container_prefixed_prefix + '-' + (item | string) }}"
|
||||
|
||||
- name: Check that the expected fields are returned for all prefixed containers
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- item.name.startswith(test_container_prefixed_prefix)
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- (expected_fields_multiple | difference(item.keys()) | length) == 0
|
||||
quiet: true
|
||||
loop: "{{ multiple_containers.containers | sort(attribute='name') }}"
|
||||
loop_control:
|
||||
label: "{{ item.name }}"
|
||||
|
||||
- name: Fetch all containers
|
||||
openstack.cloud.object_containers_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: all_containers
|
||||
|
||||
- name: Check that all expected containers were returned
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- item in (all_containers.containers | map(attribute='name'))
|
||||
fail_msg: "Container not found: {{ item }}"
|
||||
quiet: true
|
||||
loop: "{{ all_test_containers }}"
|
||||
|
||||
- name: Check that the expected fields are returned for all containers
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- (expected_fields_multiple | difference(item.keys()) | length) == 0
|
||||
quiet: true
|
||||
loop: "{{ all_containers.containers | selectattr('name', 'in', all_test_containers) }}"
|
||||
loop_control:
|
||||
label: "{{ item.name }}"
|
||||
|
||||
always:
|
||||
|
||||
- name: Delete all containers
|
||||
openstack.cloud.object_container:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
delete_with_all_objects: true
|
||||
loop: "{{ all_test_containers }}"
|
||||
@@ -1,6 +1,42 @@
|
||||
expected_fields:
|
||||
- allowed_address_pairs
|
||||
- binding_host_id
|
||||
- binding_profile
|
||||
- binding_vif_details
|
||||
- binding_vif_type
|
||||
- binding_vnic_type
|
||||
- created_at
|
||||
- data_plane_status
|
||||
- description
|
||||
- device_id
|
||||
- device_owner
|
||||
- device_profile
|
||||
- dns_assignment
|
||||
- dns_domain
|
||||
- dns_name
|
||||
- extra_dhcp_opts
|
||||
- fixed_ips
|
||||
- id
|
||||
- ip_allocation
|
||||
- is_admin_state_up
|
||||
- is_port_security_enabled
|
||||
- mac_address
|
||||
- name
|
||||
- network_id
|
||||
- numa_affinity_policy
|
||||
- project_id
|
||||
- propagate_uplink_status
|
||||
- qos_network_policy_id
|
||||
- qos_policy_id
|
||||
- resource_request
|
||||
- revision_number
|
||||
- security_group_ids
|
||||
- status
|
||||
- tags
|
||||
- tenant_id
|
||||
- trunk_details
|
||||
- updated_at
|
||||
network_name: ansible_port_network
|
||||
network_external: true
|
||||
subnet_name: ansible_port_subnet
|
||||
port_name: ansible_port
|
||||
secgroup_name: ansible_port_secgroup
|
||||
no_security_groups: True
|
||||
port_name: ansible_port
|
||||
subnet_name: ansible_port_subnet
|
||||
|
||||
@@ -1,101 +1,269 @@
|
||||
---
|
||||
- name: Create network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ network_name }}"
|
||||
external: "{{ network_external }}"
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ network_name }}"
|
||||
external: true
|
||||
register: network
|
||||
|
||||
- name: Create subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ subnet_name }}"
|
||||
network_name: "{{ network_name }}"
|
||||
cidr: 10.5.5.0/24
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ subnet_name }}"
|
||||
network_name: "{{ network_name }}"
|
||||
cidr: 10.5.5.0/24
|
||||
register: subnet
|
||||
|
||||
- name: Create port (no security group or default security group)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
no_security_groups: "{{ no_security_groups }}"
|
||||
fixed_ips:
|
||||
- ip_address: 10.5.5.69
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
no_security_groups: "{{ no_security_groups }}"
|
||||
fixed_ips:
|
||||
- ip_address: 10.5.5.69
|
||||
register: port
|
||||
|
||||
- debug: var=port
|
||||
|
||||
- name: assert return values of port module
|
||||
assert:
|
||||
that:
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(port.port.keys())|length == 0
|
||||
|
||||
- name: List all ports
|
||||
openstack.cloud.port_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: info
|
||||
|
||||
- name: Get info about all ports
|
||||
openstack.cloud.port_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: info
|
||||
|
||||
- name: Check info about ports
|
||||
assert:
|
||||
that:
|
||||
- info.ports|length > 0
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(info.ports[0].keys())|length == 0
|
||||
|
||||
- name: Get port by id
|
||||
openstack.cloud.port_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ info.ports[0].id }}"
|
||||
register: info_id
|
||||
|
||||
- name: Assert infos by id
|
||||
assert:
|
||||
that:
|
||||
- info_id.ports|length == 1
|
||||
- info_id.ports[0].id == info.ports[0].id
|
||||
|
||||
- name: List port with device_id filter
|
||||
openstack.cloud.port_info:
|
||||
cloud: "{{ cloud }}"
|
||||
filters:
|
||||
device_id: "{{ info.ports[0].device_id }}"
|
||||
register: info_filter
|
||||
|
||||
- name: Assert port was returned
|
||||
assert:
|
||||
that:
|
||||
- info_filter.ports | length >= 1
|
||||
|
||||
- name: Delete port (no security group or default security group)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ port_name }}"
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ port_name }}"
|
||||
|
||||
- name: Create security group
|
||||
openstack.cloud.security_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ secgroup_name }}"
|
||||
description: Test group
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_security_group
|
||||
description: Test group
|
||||
register: security_group
|
||||
|
||||
- name: Create port (with security group)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
fixed_ips:
|
||||
- ip_address: 10.5.5.69
|
||||
security_groups:
|
||||
- "{{ secgroup_name }}"
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
fixed_ips:
|
||||
- ip_address: 10.5.5.69
|
||||
security_groups:
|
||||
- ansible_security_group
|
||||
register: port
|
||||
|
||||
- debug: var=port
|
||||
|
||||
- name: Delete port (with security group)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ port_name }}"
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ port_name }}"
|
||||
|
||||
- name: Create port (with dns_name, dns_domain)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
fixed_ips:
|
||||
- ip_address: 10.5.5.69
|
||||
dns_name: "dns-port-name"
|
||||
dns_domain: "example.com."
|
||||
register: port
|
||||
|
||||
- debug: var=port
|
||||
|
||||
- name: Delete port (with dns name,domain)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ port_name }}"
|
||||
|
||||
- name: Create port (with allowed_address_pairs and extra_dhcp_opts)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
no_security_groups: "{{ no_security_groups }}"
|
||||
allowed_address_pairs:
|
||||
- ip_address: 10.6.7.0/24
|
||||
extra_dhcp_opts:
|
||||
- opt_name: "bootfile-name"
|
||||
opt_value: "testfile.1"
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
no_security_groups: "{{ no_security_groups }}"
|
||||
allowed_address_pairs:
|
||||
- ip_address: 10.6.7.0/24
|
||||
extra_dhcp_opts:
|
||||
- opt_name: "bootfile-name"
|
||||
opt_value: "testfile.1"
|
||||
register: port
|
||||
|
||||
- debug: var=port
|
||||
|
||||
- name: Delete port (with allowed_address_pairs and extra_dhcp_opts)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ port_name }}"
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ port_name }}"
|
||||
|
||||
- name: Create port which will be updated
|
||||
openstack.cloud.port:
|
||||
allowed_address_pairs:
|
||||
- ip_address: 10.6.7.0/24
|
||||
mac_address: "aa:bb:cc:dd:ee:ff"
|
||||
cloud: "{{ cloud }}"
|
||||
description: "What a great port"
|
||||
extra_dhcp_opts:
|
||||
- ip_version: 4
|
||||
opt_name: "bootfile-name"
|
||||
opt_value: "testfile.1"
|
||||
dns_name: "dns-port-name"
|
||||
dns_domain: "example.com."
|
||||
fixed_ips:
|
||||
- ip_address: 10.5.5.69
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
no_security_groups: true
|
||||
state: present
|
||||
register: port
|
||||
|
||||
- name: Create port which will be updated (again)
|
||||
openstack.cloud.port:
|
||||
allowed_address_pairs:
|
||||
- ip_address: 10.6.7.0/24
|
||||
mac_address: "aa:bb:cc:dd:ee:ff"
|
||||
cloud: "{{ cloud }}"
|
||||
description: "What a great port"
|
||||
extra_dhcp_opts:
|
||||
- ip_version: 4
|
||||
opt_name: "bootfile-name"
|
||||
opt_value: "testfile.1"
|
||||
# We have no valid dns name configured
|
||||
#dns_name: "dns-port-name"
|
||||
#dns_domain: "example.com."
|
||||
fixed_ips:
|
||||
- ip_address: 10.5.5.69
|
||||
subnet_id: "{{ subnet.subnet.id }}"
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
no_security_groups: true
|
||||
state: present
|
||||
register: port_again
|
||||
|
||||
- name: Assert port did not change
|
||||
assert:
|
||||
that:
|
||||
- port.port.id == port_again.port.id
|
||||
- port_again is not changed
|
||||
|
||||
- name: Update port
|
||||
openstack.cloud.port:
|
||||
allowed_address_pairs:
|
||||
- ip_address: 11.9.9.0/24
|
||||
mac_address: "aa:aa:aa:bb:bb:bb"
|
||||
cloud: "{{ cloud }}"
|
||||
description: "This port got updated"
|
||||
extra_dhcp_opts:
|
||||
- opt_name: "bootfile-name"
|
||||
opt_value: "testfile.2"
|
||||
# We have no valid dns name configured
|
||||
#dns_name: "dns-port-name-2"
|
||||
#dns_domain: "another.example.com."
|
||||
fixed_ips:
|
||||
- ip_address: 10.5.5.70
|
||||
subnet_id: "{{ subnet.subnet.id }}"
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
security_groups:
|
||||
- ansible_security_group
|
||||
state: present
|
||||
register: port_updated
|
||||
|
||||
- name: Assert updated port
|
||||
assert:
|
||||
that:
|
||||
- port_updated.port.id == port.port.id
|
||||
- port_updated.port.allowed_address_pairs|length == 1
|
||||
- port_updated.port.allowed_address_pairs[0].ip_address == "11.9.9.0/24"
|
||||
- port_updated.port.allowed_address_pairs[0].mac_address == "aa:aa:aa:bb:bb:bb"
|
||||
- port_updated.port.description == "This port got updated"
|
||||
- port_updated.port.extra_dhcp_opts|length == 1
|
||||
- port_updated.port.extra_dhcp_opts[0].opt_value == "testfile.2"
|
||||
# We have no valid dns name configured
|
||||
#- port_updated.port.dns_name == "dns-port-name-2"
|
||||
#- port_updated.port.dns_domain == "another.example.com."
|
||||
- port_updated.port.fixed_ips|length == 1
|
||||
- port_updated.port.fixed_ips[0].ip_address == "10.5.5.70"
|
||||
- port_updated.port.fixed_ips[0].subnet_id == subnet.subnet.id
|
||||
- port_updated.port.security_group_ids|length == 1
|
||||
- port_updated.port.security_group_ids[0] == security_group.security_group.id
|
||||
|
||||
- name: Delete updated port
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ port_name }}"
|
||||
|
||||
- name: Delete security group
|
||||
openstack.cloud.security_group:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ secgroup_name }}"
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_security_group
|
||||
|
||||
- name: Delete subnet
|
||||
openstack.cloud.subnet:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ subnet_name }}"
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ subnet_name }}"
|
||||
|
||||
- name: Delete network
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ network_name }}"
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ network_name }}"
|
||||
|
||||
10
ci/roles/project/defaults/main.yml
Normal file
10
ci/roles/project/defaults/main.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
expected_fields:
|
||||
- description
|
||||
- domain_id
|
||||
- id
|
||||
- is_domain
|
||||
- is_enabled
|
||||
- name
|
||||
- options
|
||||
- parent_id
|
||||
- tags
|
||||
@@ -1,25 +1,178 @@
|
||||
---
|
||||
- name: Create project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: dummy description
|
||||
domain_id: default
|
||||
enabled: True
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: dummy description
|
||||
domain: default
|
||||
is_enabled: True
|
||||
register: project
|
||||
|
||||
- debug: var=project
|
||||
- name: Assert return values of project module
|
||||
assert:
|
||||
that:
|
||||
- project is changed
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(project.project.keys())|length == 0
|
||||
|
||||
- name: Fetch project
|
||||
openstack.cloud.project_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_project
|
||||
register: project
|
||||
|
||||
- name: Assert project
|
||||
assert:
|
||||
that:
|
||||
- project.projects | length == 1
|
||||
- project.projects.0.name == 'ansible_project'
|
||||
- project.projects.0.description == 'dummy description'
|
||||
|
||||
- name: Create project again
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: dummy description
|
||||
domain: default
|
||||
is_enabled: True
|
||||
register: project
|
||||
|
||||
- name: Assert return values of project module
|
||||
assert:
|
||||
that:
|
||||
- project is not changed
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(project.project.keys())|length == 0
|
||||
|
||||
- name: Update project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: new description
|
||||
register: updatedproject
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: new description
|
||||
extra_specs:
|
||||
tags:
|
||||
- example_tag
|
||||
register: project
|
||||
|
||||
- debug: var=updatedproject
|
||||
- name: Assert project changed
|
||||
assert:
|
||||
that:
|
||||
- project is changed
|
||||
- project.project.description == 'new description'
|
||||
|
||||
- name: Fetch all projects
|
||||
openstack.cloud.project_info:
|
||||
cloud: "{{ cloud }}"
|
||||
register: projects
|
||||
|
||||
- name: Assert return values of project_info module
|
||||
assert:
|
||||
that:
|
||||
- projects.projects | length > 0
|
||||
# allow new fields to be introduced but prevent fields from being removed
|
||||
- expected_fields|difference(projects.projects.0.keys())|length == 0
|
||||
|
||||
- name: Fetch project by name
|
||||
openstack.cloud.project_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: 'ansible_project'
|
||||
register: projects
|
||||
|
||||
- name: Assert return values of project_info module
|
||||
assert:
|
||||
that:
|
||||
- projects.projects | length == 1
|
||||
- projects.projects.0.name == 'ansible_project'
|
||||
|
||||
- name: Fetch projects with filter
|
||||
openstack.cloud.project_info:
|
||||
cloud: "{{ cloud }}"
|
||||
filters:
|
||||
name: 'ansible_project'
|
||||
register: projects
|
||||
|
||||
- name: Assert return values of project_info module
|
||||
assert:
|
||||
that:
|
||||
- projects.projects | length == 1
|
||||
- projects.projects.0.name == 'ansible_project'
|
||||
|
||||
- name: Fetch project by name and domain
|
||||
openstack.cloud.project_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: 'ansible_project'
|
||||
domain: 'default'
|
||||
register: projects
|
||||
|
||||
- name: Assert return values of project_info module
|
||||
assert:
|
||||
that:
|
||||
- projects.projects | length == 1
|
||||
- projects.projects.0.name == 'ansible_project'
|
||||
|
||||
- name: Delete project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_project
|
||||
register: project
|
||||
|
||||
- name: Assert project changed
|
||||
assert:
|
||||
that: project is changed
|
||||
|
||||
- name: Get project
|
||||
openstack.cloud.project_info:
|
||||
cloud: "{{ cloud }}"
|
||||
name: ansible_project
|
||||
register: project_info
|
||||
|
||||
- name: Assert project deleted
|
||||
assert:
|
||||
that:
|
||||
- project_info.projects | length == 0
|
||||
|
||||
- name: Delete project again
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_project
|
||||
register: project
|
||||
|
||||
- name: Assert project not changed
|
||||
assert:
|
||||
that: project is not changed
|
||||
|
||||
- name: Create project with extra_specs
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
extra_specs:
|
||||
is_enabled: False
|
||||
register: project
|
||||
|
||||
- name: Assert return values of project module
|
||||
assert:
|
||||
that:
|
||||
- project.project.is_enabled == False
|
||||
|
||||
- name: Update project with extra_specs
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
extra_specs:
|
||||
is_enabled: True
|
||||
register: project
|
||||
|
||||
- name: Assert return values of project module
|
||||
assert:
|
||||
that:
|
||||
- project.project.is_enabled == True
|
||||
|
||||
- name: Delete project
|
||||
openstack.cloud.project:
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
dummy_value: 'test-value'
|
||||
dummy_value_updated: 'test-value-updated'
|
||||
@@ -1,142 +0,0 @@
|
||||
---
|
||||
- name: 'Create project with properties - CHECK_MODE'
|
||||
check_mode: yes
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: dummy description
|
||||
domain_id: default
|
||||
enabled: True
|
||||
properties:
|
||||
dummy_key: '{{ dummy_value }}'
|
||||
register: create_project_cm
|
||||
- assert:
|
||||
that:
|
||||
- create_project_cm is successful
|
||||
- create_project_cm is changed
|
||||
|
||||
- name: 'Create project with properties'
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: dummy description
|
||||
domain_id: default
|
||||
enabled: True
|
||||
properties:
|
||||
dummy_key: '{{ dummy_value }}'
|
||||
register: create_project
|
||||
- assert:
|
||||
that:
|
||||
- create_project is successful
|
||||
- create_project is changed
|
||||
- '"project" in create_project'
|
||||
- '"dummy_key" in create_project["project"]'
|
||||
- create_project["project"].dummy_key == dummy_value
|
||||
|
||||
- name: 'Create project with properties (retry - no change) - CHECK_MODE'
|
||||
check_mode: yes
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: dummy description
|
||||
domain_id: default
|
||||
enabled: True
|
||||
properties:
|
||||
dummy_key: '{{ dummy_value }}'
|
||||
register: create_project_retry_cm
|
||||
- assert:
|
||||
that:
|
||||
- create_project_retry_cm is successful
|
||||
- create_project_retry_cm is not changed
|
||||
|
||||
- name: 'Create project with properties (retry - no change)'
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: dummy description
|
||||
domain_id: default
|
||||
enabled: True
|
||||
properties:
|
||||
dummy_key: '{{ dummy_value }}'
|
||||
register: create_project_retry
|
||||
- assert:
|
||||
that:
|
||||
- create_project_retry is successful
|
||||
- create_project_retry is not changed
|
||||
- '"project" in create_project_retry'
|
||||
- '"dummy_key" in create_project_retry["project"]'
|
||||
- create_project_retry["project"].dummy_key == dummy_value
|
||||
|
||||
- name: 'Update project with properties - CHECK_MODE'
|
||||
check_mode: yes
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: new description
|
||||
properties:
|
||||
dummy_key: '{{ dummy_value_updated }}'
|
||||
register: updated_project_cm
|
||||
- assert:
|
||||
that:
|
||||
- updated_project_cm is successful
|
||||
- updated_project_cm is changed
|
||||
|
||||
- name: 'Update project with properties'
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: new description
|
||||
properties:
|
||||
dummy_key: '{{ dummy_value_updated }}'
|
||||
register: updated_project
|
||||
- assert:
|
||||
that:
|
||||
- updated_project is successful
|
||||
- updated_project is changed
|
||||
- '"project" in updated_project'
|
||||
- '"dummy_key" in updated_project["project"]'
|
||||
- updated_project["project"].dummy_key == dummy_value_updated
|
||||
|
||||
- name: 'Update project with properties (retry - no change) - CHECK_MODE'
|
||||
check_mode: yes
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: new description
|
||||
properties:
|
||||
dummy_key: '{{ dummy_value_updated }}'
|
||||
register: updated_project_retry_cm
|
||||
- assert:
|
||||
that:
|
||||
- updated_project_retry_cm is successful
|
||||
- updated_project_retry_cm is not changed
|
||||
|
||||
- name: 'Update project with properties (retry - no change)'
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: new description
|
||||
properties:
|
||||
dummy_key: '{{ dummy_value_updated }}'
|
||||
register: updated_project_retry
|
||||
- assert:
|
||||
that:
|
||||
- updated_project_retry is successful
|
||||
- updated_project_retry is not changed
|
||||
- '"project" in updated_project_retry'
|
||||
- '"dummy_key" in updated_project_retry["project"]'
|
||||
- updated_project_retry["project"].dummy_key == dummy_value_updated
|
||||
|
||||
- name: Delete project with properties
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_project
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user