python-openstackclient 9.0.0__py3-none-any.whl → 10.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (284) hide show
  1. openstackclient/__init__.py +2 -6
  2. openstackclient/api/api.py +41 -23
  3. openstackclient/api/compute_v2.py +44 -25
  4. openstackclient/api/object_store_v1.py +75 -97
  5. openstackclient/api/volume_v2.py +2 -1
  6. openstackclient/api/volume_v3.py +2 -1
  7. openstackclient/common/availability_zone.py +58 -42
  8. openstackclient/common/clientmanager.py +56 -29
  9. openstackclient/common/configuration.py +10 -3
  10. openstackclient/common/envvars.py +2 -2
  11. openstackclient/common/extension.py +14 -5
  12. openstackclient/common/limits.py +10 -5
  13. openstackclient/common/module.py +14 -6
  14. openstackclient/common/pagination.py +8 -2
  15. openstackclient/common/progressbar.py +7 -6
  16. openstackclient/common/project_cleanup.py +13 -7
  17. openstackclient/common/quota.py +97 -99
  18. openstackclient/common/versions.py +8 -2
  19. openstackclient/compute/client.py +7 -3
  20. openstackclient/compute/v2/agent.py +17 -10
  21. openstackclient/compute/v2/aggregate.py +36 -22
  22. openstackclient/compute/v2/console.py +14 -8
  23. openstackclient/compute/v2/console_connection.py +11 -3
  24. openstackclient/compute/v2/flavor.py +39 -21
  25. openstackclient/compute/v2/host.py +14 -6
  26. openstackclient/compute/v2/hypervisor.py +14 -5
  27. openstackclient/compute/v2/hypervisor_stats.py +10 -2
  28. openstackclient/compute/v2/keypair.py +29 -14
  29. openstackclient/compute/v2/server.py +249 -169
  30. openstackclient/compute/v2/server_backup.py +10 -4
  31. openstackclient/compute/v2/server_event.py +21 -12
  32. openstackclient/compute/v2/server_group.py +21 -11
  33. openstackclient/compute/v2/server_image.py +19 -10
  34. openstackclient/compute/v2/server_migration.py +24 -10
  35. openstackclient/compute/v2/server_share.py +274 -0
  36. openstackclient/compute/v2/server_volume.py +10 -4
  37. openstackclient/compute/v2/service.py +14 -7
  38. openstackclient/compute/v2/usage.py +26 -21
  39. openstackclient/identity/client.py +8 -3
  40. openstackclient/identity/common.py +78 -47
  41. openstackclient/identity/v2_0/catalog.py +14 -7
  42. openstackclient/identity/v2_0/ec2creds.py +21 -10
  43. openstackclient/identity/v2_0/endpoint.py +23 -11
  44. openstackclient/identity/v2_0/project.py +25 -14
  45. openstackclient/identity/v2_0/role.py +28 -14
  46. openstackclient/identity/v2_0/role_assignment.py +9 -3
  47. openstackclient/identity/v2_0/service.py +23 -11
  48. openstackclient/identity/v2_0/token.py +12 -5
  49. openstackclient/identity/v2_0/user.py +26 -15
  50. openstackclient/identity/v3/access_rule.py +26 -12
  51. openstackclient/identity/v3/application_credential.py +59 -24
  52. openstackclient/identity/v3/catalog.py +14 -7
  53. openstackclient/identity/v3/consumer.py +22 -11
  54. openstackclient/identity/v3/credential.py +36 -16
  55. openstackclient/identity/v3/domain.py +37 -18
  56. openstackclient/identity/v3/ec2creds.py +25 -12
  57. openstackclient/identity/v3/endpoint.py +42 -20
  58. openstackclient/identity/v3/endpoint_group.py +28 -17
  59. openstackclient/identity/v3/federation_protocol.py +38 -16
  60. openstackclient/identity/v3/group.py +55 -32
  61. openstackclient/identity/v3/identity_provider.py +92 -57
  62. openstackclient/identity/v3/implied_role.py +21 -9
  63. openstackclient/identity/v3/limit.py +38 -16
  64. openstackclient/identity/v3/mapping.py +26 -13
  65. openstackclient/identity/v3/policy.py +23 -12
  66. openstackclient/identity/v3/project.py +43 -23
  67. openstackclient/identity/v3/region.py +36 -16
  68. openstackclient/identity/v3/registered_limit.py +40 -16
  69. openstackclient/identity/v3/role.py +61 -31
  70. openstackclient/identity/v3/role_assignment.py +23 -6
  71. openstackclient/identity/v3/service.py +36 -16
  72. openstackclient/identity/v3/service_provider.py +37 -15
  73. openstackclient/identity/v3/tag.py +23 -6
  74. openstackclient/identity/v3/token.py +30 -14
  75. openstackclient/identity/v3/trust.py +32 -14
  76. openstackclient/identity/v3/unscoped_saml.py +10 -2
  77. openstackclient/identity/v3/user.py +49 -26
  78. openstackclient/image/client.py +7 -3
  79. openstackclient/image/v1/image.py +33 -26
  80. openstackclient/image/v2/cache.py +14 -9
  81. openstackclient/image/v2/image.py +74 -48
  82. openstackclient/image/v2/info.py +7 -1
  83. openstackclient/image/v2/metadef_namespaces.py +109 -13
  84. openstackclient/image/v2/metadef_objects.py +28 -15
  85. openstackclient/image/v2/metadef_properties.py +24 -13
  86. openstackclient/image/v2/metadef_resource_type_association.py +14 -7
  87. openstackclient/image/v2/metadef_resource_types.py +7 -1
  88. openstackclient/image/v2/task.py +15 -6
  89. openstackclient/locale/tr_TR/LC_MESSAGES/openstackclient.po +7 -192
  90. openstackclient/network/client.py +7 -2
  91. openstackclient/network/common.py +16 -241
  92. openstackclient/network/utils.py +36 -22
  93. openstackclient/network/v2/address_group.py +27 -16
  94. openstackclient/network/v2/address_scope.py +24 -13
  95. openstackclient/network/v2/bgpvpn/bgpvpn.py +463 -0
  96. openstackclient/network/v2/bgpvpn/constants.py +30 -0
  97. openstackclient/network/v2/bgpvpn/network_association.py +214 -0
  98. openstackclient/network/v2/bgpvpn/port_association.py +490 -0
  99. openstackclient/network/v2/bgpvpn/router_association.py +288 -0
  100. openstackclient/network/v2/default_security_group_rule.py +19 -10
  101. openstackclient/network/v2/floating_ip.py +110 -159
  102. openstackclient/network/v2/floating_ip_port_forwarding.py +30 -18
  103. openstackclient/network/v2/fwaas/__init__.py +0 -0
  104. openstackclient/network/v2/fwaas/group.py +466 -0
  105. openstackclient/network/v2/fwaas/policy.py +518 -0
  106. openstackclient/network/v2/fwaas/rule.py +574 -0
  107. openstackclient/network/v2/ip_availability.py +13 -5
  108. openstackclient/network/v2/l3_conntrack_helper.py +22 -13
  109. openstackclient/network/v2/local_ip.py +24 -13
  110. openstackclient/network/v2/local_ip_association.py +14 -7
  111. openstackclient/network/v2/ndp_proxy.py +20 -11
  112. openstackclient/network/v2/network.py +129 -196
  113. openstackclient/network/v2/network_agent.py +46 -25
  114. openstackclient/network/v2/network_auto_allocated_topology.py +22 -11
  115. openstackclient/network/v2/network_flavor.py +27 -16
  116. openstackclient/network/v2/network_flavor_profile.py +23 -12
  117. openstackclient/network/v2/network_meter.py +21 -10
  118. openstackclient/network/v2/network_meter_rule.py +21 -11
  119. openstackclient/network/v2/network_qos_policy.py +25 -15
  120. openstackclient/network/v2/network_qos_rule.py +32 -17
  121. openstackclient/network/v2/network_qos_rule_type.py +13 -5
  122. openstackclient/network/v2/network_rbac.py +23 -12
  123. openstackclient/network/v2/network_segment.py +20 -11
  124. openstackclient/network/v2/network_segment_range.py +56 -29
  125. openstackclient/network/v2/network_service_provider.py +7 -1
  126. openstackclient/network/v2/network_trunk.py +38 -22
  127. openstackclient/network/v2/port.py +54 -29
  128. openstackclient/network/v2/router.py +75 -52
  129. openstackclient/network/v2/security_group.py +87 -157
  130. openstackclient/network/v2/security_group_rule.py +100 -280
  131. openstackclient/network/v2/subnet.py +49 -28
  132. openstackclient/network/v2/subnet_pool.py +30 -17
  133. openstackclient/network/v2/taas/tap_flow.py +22 -11
  134. openstackclient/network/v2/taas/tap_mirror.py +22 -11
  135. openstackclient/network/v2/taas/tap_service.py +23 -12
  136. openstackclient/object/client.py +7 -2
  137. openstackclient/object/v1/account.py +13 -6
  138. openstackclient/object/v1/container.py +25 -15
  139. openstackclient/object/v1/object.py +25 -15
  140. openstackclient/py.typed +0 -0
  141. openstackclient/shell.py +46 -10
  142. openstackclient/tests/functional/base.py +55 -20
  143. openstackclient/tests/functional/common/test_extension.py +4 -0
  144. openstackclient/tests/functional/common/test_quota.py +3 -1
  145. openstackclient/tests/functional/compute/v2/common.py +14 -13
  146. openstackclient/tests/functional/compute/v2/test_flavor.py +3 -1
  147. openstackclient/tests/functional/compute/v2/test_server.py +3 -0
  148. openstackclient/tests/functional/identity/v2/common.py +10 -6
  149. openstackclient/tests/functional/identity/v2/test_role.py +4 -4
  150. openstackclient/tests/functional/identity/v3/common.py +25 -19
  151. openstackclient/tests/functional/identity/v3/test_group.py +20 -20
  152. openstackclient/tests/functional/identity/v3/test_idp.py +3 -1
  153. openstackclient/tests/functional/identity/v3/test_project.py +10 -10
  154. openstackclient/tests/functional/identity/v3/test_role.py +18 -18
  155. openstackclient/tests/functional/identity/v3/test_role_assignment.py +12 -12
  156. openstackclient/tests/functional/identity/v3/test_user.py +8 -8
  157. openstackclient/tests/functional/image/base.py +1 -6
  158. openstackclient/tests/functional/network/v2/common.py +5 -2
  159. openstackclient/tests/functional/network/v2/test_floating_ip.py +10 -4
  160. openstackclient/tests/functional/network/v2/test_ip_availability.py +4 -0
  161. openstackclient/tests/functional/network/v2/test_network_meter_rule.py +3 -2
  162. openstackclient/tests/functional/network/v2/test_network_segment.py +5 -0
  163. openstackclient/tests/functional/network/v2/test_subnet.py +13 -9
  164. openstackclient/tests/functional/object/v1/common.py +4 -0
  165. openstackclient/tests/functional/volume/v2/common.py +4 -0
  166. openstackclient/tests/functional/volume/v2/test_volume_snapshot.py +27 -11
  167. openstackclient/tests/functional/volume/v2/test_volume_type.py +2 -2
  168. openstackclient/tests/functional/volume/v3/common.py +4 -0
  169. openstackclient/tests/functional/volume/v3/test_volume_snapshot.py +11 -7
  170. openstackclient/tests/functional/volume/v3/test_volume_type.py +2 -2
  171. openstackclient/tests/unit/common/test_availability_zone.py +35 -49
  172. openstackclient/tests/unit/common/test_extension.py +2 -2
  173. openstackclient/tests/unit/common/test_module.py +12 -7
  174. openstackclient/tests/unit/common/test_project_cleanup.py +3 -1
  175. openstackclient/tests/unit/common/test_quota.py +6 -26
  176. openstackclient/tests/unit/compute/v2/fakes.py +25 -0
  177. openstackclient/tests/unit/compute/v2/test_flavor.py +28 -2
  178. openstackclient/tests/unit/compute/v2/test_keypair.py +6 -6
  179. openstackclient/tests/unit/compute/v2/test_server.py +11 -96
  180. openstackclient/tests/unit/compute/v2/test_server_share.py +287 -0
  181. openstackclient/tests/unit/identity/v3/fakes.py +3 -0
  182. openstackclient/tests/unit/identity/v3/test_group.py +4 -14
  183. openstackclient/tests/unit/identity/v3/test_identity_provider.py +303 -299
  184. openstackclient/tests/unit/identity/v3/test_user.py +4 -4
  185. openstackclient/tests/unit/image/v2/test_image.py +11 -11
  186. openstackclient/tests/unit/image/v2/test_metadef_namespaces.py +105 -6
  187. openstackclient/tests/unit/network/test_common.py +0 -155
  188. openstackclient/tests/unit/network/v2/bgpvpn/__init__.py +0 -0
  189. openstackclient/tests/unit/network/v2/bgpvpn/fakes.py +179 -0
  190. openstackclient/tests/unit/network/v2/bgpvpn/test_bgpvpn.py +584 -0
  191. openstackclient/tests/unit/network/v2/bgpvpn/test_network_association.py +285 -0
  192. openstackclient/tests/unit/network/v2/bgpvpn/test_port_association.py +384 -0
  193. openstackclient/tests/unit/network/v2/bgpvpn/test_router_association.py +297 -0
  194. openstackclient/tests/unit/network/v2/fwaas/__init__.py +0 -0
  195. openstackclient/tests/unit/network/v2/fwaas/test_group.py +897 -0
  196. openstackclient/tests/unit/network/v2/fwaas/test_policy.py +869 -0
  197. openstackclient/tests/unit/network/v2/fwaas/test_rule.py +980 -0
  198. openstackclient/tests/unit/network/v2/taas/{test_osc_tap_flow.py → test_tap_flow.py} +18 -25
  199. openstackclient/tests/unit/network/v2/taas/{test_osc_tap_mirror.py → test_tap_mirror.py} +19 -29
  200. openstackclient/tests/unit/network/v2/taas/{test_osc_tap_service.py → test_tap_service.py} +19 -29
  201. openstackclient/tests/unit/network/v2/test_address_group.py +2 -2
  202. openstackclient/tests/unit/network/v2/{test_floating_ip_network.py → test_floating_ip.py} +3 -2
  203. openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py +13 -13
  204. openstackclient/tests/unit/network/v2/test_network_agent.py +8 -4
  205. openstackclient/tests/unit/network/v2/test_network_auto_allocated_topology.py +3 -3
  206. openstackclient/tests/unit/network/v2/test_network_flavor.py +2 -2
  207. openstackclient/tests/unit/network/v2/test_network_qos_policy.py +1 -1
  208. openstackclient/tests/unit/network/v2/test_network_qos_rule.py +2 -2
  209. openstackclient/tests/unit/network/v2/test_network_rbac.py +1 -1
  210. openstackclient/tests/unit/network/v2/test_network_segment.py +1 -1
  211. openstackclient/tests/unit/network/v2/test_network_segment_range.py +7 -10
  212. openstackclient/tests/unit/network/v2/test_network_trunk.py +1 -1
  213. openstackclient/tests/unit/network/v2/test_router.py +8 -9
  214. openstackclient/tests/unit/network/v2/{test_security_group_network.py → test_security_group.py} +1 -20
  215. openstackclient/tests/unit/network/v2/{test_security_group_rule_network.py → test_security_group_rule.py} +7 -41
  216. openstackclient/tests/unit/network/v2/test_subnet.py +2 -1
  217. openstackclient/tests/unit/network/v2/test_subnet_pool.py +2 -1
  218. openstackclient/tests/unit/object/v1/fakes.py +8 -7
  219. openstackclient/tests/unit/object/v1/test_container.py +65 -101
  220. openstackclient/tests/unit/object/v1/test_container_all.py +8 -1
  221. openstackclient/tests/unit/object/v1/test_object.py +44 -84
  222. openstackclient/tests/unit/object/v1/test_object_all.py +8 -1
  223. openstackclient/tests/unit/test_hacking.py +108 -0
  224. openstackclient/tests/unit/volume/v2/fakes.py +1 -0
  225. openstackclient/tests/unit/volume/v2/test_volume_backup.py +1 -5
  226. openstackclient/tests/unit/volume/v2/test_volume_snapshot.py +2 -1
  227. openstackclient/tests/unit/volume/v2/test_volume_type.py +2 -4
  228. openstackclient/tests/unit/volume/v3/fakes.py +1 -0
  229. openstackclient/tests/unit/volume/v3/test_volume.py +60 -3
  230. openstackclient/tests/unit/volume/v3/test_volume_attachment.py +1 -1
  231. openstackclient/tests/unit/volume/v3/test_volume_backup.py +1 -5
  232. openstackclient/tests/unit/volume/v3/test_volume_snapshot.py +55 -1
  233. openstackclient/tests/unit/volume/v3/test_volume_type.py +2 -4
  234. openstackclient/volume/client.py +7 -3
  235. openstackclient/volume/v2/backup_record.py +15 -6
  236. openstackclient/volume/v2/consistency_group.py +29 -17
  237. openstackclient/volume/v2/consistency_group_snapshot.py +25 -10
  238. openstackclient/volume/v2/qos_specs.py +28 -17
  239. openstackclient/volume/v2/service.py +17 -6
  240. openstackclient/volume/v2/volume.py +57 -29
  241. openstackclient/volume/v2/volume_backend.py +19 -6
  242. openstackclient/volume/v2/volume_backup.py +46 -20
  243. openstackclient/volume/v2/volume_host.py +6 -4
  244. openstackclient/volume/v2/volume_snapshot.py +50 -24
  245. openstackclient/volume/v2/volume_transfer_request.py +31 -13
  246. openstackclient/volume/v2/volume_type.py +43 -24
  247. openstackclient/volume/v3/block_storage_cleanup.py +11 -3
  248. openstackclient/volume/v3/block_storage_cluster.py +19 -7
  249. openstackclient/volume/v3/block_storage_log_level.py +15 -6
  250. openstackclient/volume/v3/block_storage_manage.py +10 -4
  251. openstackclient/volume/v3/block_storage_resource_filter.py +17 -5
  252. openstackclient/volume/v3/service.py +16 -6
  253. openstackclient/volume/v3/volume.py +89 -39
  254. openstackclient/volume/v3/volume_attachment.py +43 -21
  255. openstackclient/volume/v3/volume_backup.py +53 -24
  256. openstackclient/volume/v3/volume_group.py +23 -13
  257. openstackclient/volume/v3/volume_group_snapshot.py +32 -13
  258. openstackclient/volume/v3/volume_group_type.py +26 -13
  259. openstackclient/volume/v3/volume_message.py +15 -7
  260. openstackclient/volume/v3/volume_snapshot.py +69 -32
  261. openstackclient/volume/v3/volume_transfer_request.py +31 -13
  262. openstackclient/volume/v3/volume_type.py +42 -24
  263. {python_openstackclient-9.0.0.dist-info → python_openstackclient-10.0.0.dist-info}/METADATA +6 -6
  264. {python_openstackclient-9.0.0.dist-info → python_openstackclient-10.0.0.dist-info}/RECORD +271 -260
  265. {python_openstackclient-9.0.0.dist-info → python_openstackclient-10.0.0.dist-info}/WHEEL +1 -1
  266. {python_openstackclient-9.0.0.dist-info → python_openstackclient-10.0.0.dist-info}/entry_points.txt +53 -1
  267. {python_openstackclient-9.0.0.dist-info → python_openstackclient-10.0.0.dist-info}/licenses/AUTHORS +4 -0
  268. python_openstackclient-10.0.0.dist-info/pbr.json +1 -0
  269. openstackclient/api/image_v1.py +0 -69
  270. openstackclient/api/image_v2.py +0 -79
  271. openstackclient/network/v2/floating_ip_pool.py +0 -38
  272. openstackclient/tests/functional/image/v1/test_image.py +0 -97
  273. openstackclient/tests/unit/api/test_image_v1.py +0 -96
  274. openstackclient/tests/unit/api/test_image_v2.py +0 -96
  275. openstackclient/tests/unit/network/v2/test_floating_ip_compute.py +0 -248
  276. openstackclient/tests/unit/network/v2/test_floating_ip_pool_compute.py +0 -49
  277. openstackclient/tests/unit/network/v2/test_floating_ip_pool_network.py +0 -39
  278. openstackclient/tests/unit/network/v2/test_network_compute.py +0 -404
  279. openstackclient/tests/unit/network/v2/test_security_group_compute.py +0 -392
  280. openstackclient/tests/unit/network/v2/test_security_group_rule_compute.py +0 -555
  281. python_openstackclient-9.0.0.dist-info/pbr.json +0 -1
  282. /openstackclient/{tests/functional/image/v1 → network/v2/bgpvpn}/__init__.py +0 -0
  283. {python_openstackclient-9.0.0.dist-info → python_openstackclient-10.0.0.dist-info}/licenses/LICENSE +0 -0
  284. {python_openstackclient-9.0.0.dist-info → python_openstackclient-10.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,466 @@
1
+ # Copyright 2016-2017 FUJITSU LIMITED
2
+ # All Rights Reserved
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may
5
+ # not use this file except in compliance with the License. You may obtain
6
+ # a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations
14
+ # under the License.
15
+
16
+ import argparse
17
+ from collections.abc import Iterable, Sequence
18
+ import logging
19
+ from typing import Any
20
+
21
+ from cliff import columns as cliff_columns
22
+ from osc_lib.cli import identity as identity_utils
23
+ from osc_lib import exceptions
24
+ from osc_lib import utils
25
+ from osc_lib.utils import columns as column_util
26
+
27
+ from openstackclient import command
28
+ from openstackclient.i18n import _
29
+ from openstackclient.identity import common as identity_common
30
+
31
+
32
+ LOG = logging.getLogger(__name__)
33
+
34
+
35
+ class AdminStateColumn(cliff_columns.FormattableColumn[bool]):
36
+ def human_readable(self) -> str:
37
+ return 'UP' if self._value else 'DOWN'
38
+
39
+
40
+ _formatters = {
41
+ 'admin_state_up': AdminStateColumn,
42
+ }
43
+
44
+ _attr_map = (
45
+ ('id', 'ID', column_util.LIST_BOTH),
46
+ ('name', 'Name', column_util.LIST_BOTH),
47
+ ('ingress_firewall_policy_id', 'Ingress Policy ID', column_util.LIST_BOTH),
48
+ ('egress_firewall_policy_id', 'Egress Policy ID', column_util.LIST_BOTH),
49
+ ('description', 'Description', column_util.LIST_LONG_ONLY),
50
+ ('status', 'Status', column_util.LIST_LONG_ONLY),
51
+ ('ports', 'Ports', column_util.LIST_LONG_ONLY),
52
+ ('admin_state_up', 'State', column_util.LIST_LONG_ONLY),
53
+ ('shared', 'Shared', column_util.LIST_LONG_ONLY),
54
+ ('project_id', 'Project', column_util.LIST_LONG_ONLY),
55
+ )
56
+
57
+ _attr_map_dict = {x[0]: x[1] for x in _attr_map}
58
+
59
+
60
+ def _get_common_parser(
61
+ parser: argparse.ArgumentParser,
62
+ ) -> argparse.ArgumentParser:
63
+ parser.add_argument('--name', help=_('Name for the firewall group'))
64
+ parser.add_argument(
65
+ '--description',
66
+ metavar='<description>',
67
+ help=_('Description of the firewall group'),
68
+ )
69
+ ingress_group = parser.add_mutually_exclusive_group()
70
+ ingress_group.add_argument(
71
+ '--ingress-firewall-policy',
72
+ metavar='<ingress-firewall-policy>',
73
+ dest='ingress_firewall_policy',
74
+ help=_('Ingress firewall policy (name or ID)'),
75
+ )
76
+ ingress_group.add_argument(
77
+ '--no-ingress-firewall-policy',
78
+ dest='no_ingress_firewall_policy',
79
+ action='store_true',
80
+ help=_('Detach ingress firewall policy from the firewall group'),
81
+ )
82
+ egress_group = parser.add_mutually_exclusive_group()
83
+ egress_group.add_argument(
84
+ '--egress-firewall-policy',
85
+ metavar='<egress-firewall-policy>',
86
+ dest='egress_firewall_policy',
87
+ help=_('Egress firewall policy (name or ID)'),
88
+ )
89
+ egress_group.add_argument(
90
+ '--no-egress-firewall-policy',
91
+ dest='no_egress_firewall_policy',
92
+ action='store_true',
93
+ help=_('Detach egress firewall policy from the firewall group'),
94
+ )
95
+ shared_group = parser.add_mutually_exclusive_group()
96
+ shared_group.add_argument(
97
+ '--share',
98
+ action='store_true',
99
+ default=None,
100
+ dest='shared',
101
+ help=_(
102
+ 'Share the firewall group to be used in all projects '
103
+ '(by default, it is restricted to be used by the '
104
+ 'current project).'
105
+ ),
106
+ )
107
+ shared_group.add_argument(
108
+ '--no-share',
109
+ action='store_false',
110
+ dest='shared',
111
+ help=_('Restrict use of the firewall group to the current project'),
112
+ )
113
+ admin_group = parser.add_mutually_exclusive_group()
114
+ admin_group.add_argument(
115
+ '--enable',
116
+ action='store_true',
117
+ default=None,
118
+ dest='admin_state_up',
119
+ help=_('Enable firewall group'),
120
+ )
121
+ admin_group.add_argument(
122
+ '--disable',
123
+ action='store_false',
124
+ dest='admin_state_up',
125
+ help=_('Disable firewall group'),
126
+ )
127
+ return parser
128
+
129
+
130
+ def _get_common_attrs(
131
+ client_manager: Any,
132
+ parsed_args: argparse.Namespace,
133
+ is_create: bool = True,
134
+ ) -> dict[str, Any]:
135
+ attrs: dict[str, Any] = {}
136
+ client = client_manager.network
137
+
138
+ if parsed_args.ingress_firewall_policy:
139
+ attrs['ingress_firewall_policy_id'] = client.find_firewall_policy(
140
+ parsed_args.ingress_firewall_policy, ignore_missing=False
141
+ ).id
142
+ elif parsed_args.no_ingress_firewall_policy:
143
+ attrs['ingress_firewall_policy_id'] = None
144
+
145
+ if parsed_args.egress_firewall_policy:
146
+ attrs['egress_firewall_policy_id'] = client.find_firewall_policy(
147
+ parsed_args.egress_firewall_policy, ignore_missing=False
148
+ ).id
149
+ elif parsed_args.no_egress_firewall_policy:
150
+ attrs['egress_firewall_policy_id'] = None
151
+
152
+ if parsed_args.shared is not None:
153
+ attrs['shared'] = parsed_args.shared
154
+ if parsed_args.admin_state_up is not None:
155
+ attrs['admin_state_up'] = parsed_args.admin_state_up
156
+ if parsed_args.name:
157
+ attrs['name'] = parsed_args.name
158
+ if parsed_args.description:
159
+ attrs['description'] = parsed_args.description
160
+ if parsed_args.port and parsed_args.no_port:
161
+ attrs['ports'] = sorted(
162
+ [
163
+ client.find_port(p, ignore_missing=False).id
164
+ for p in set(parsed_args.port)
165
+ ]
166
+ )
167
+ elif parsed_args.port:
168
+ ports = []
169
+ for p in set(parsed_args.port):
170
+ ports.append(client.find_port(p, ignore_missing=False).id)
171
+ if not is_create:
172
+ ports += client.find_firewall_group(
173
+ parsed_args.firewall_group, ignore_missing=False
174
+ ).ports
175
+ attrs['ports'] = sorted(set(ports))
176
+ elif parsed_args.no_port:
177
+ attrs['ports'] = []
178
+ return attrs
179
+
180
+
181
+ class CreateFirewallGroup(command.ShowOne):
182
+ _description = _("Create a new firewall group")
183
+
184
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
185
+ parser = super().get_parser(prog_name)
186
+ _get_common_parser(parser)
187
+ identity_utils.add_project_owner_option_to_parser(parser)
188
+ port_group = parser.add_mutually_exclusive_group()
189
+ port_group.add_argument(
190
+ '--port',
191
+ metavar='<port>',
192
+ action='append',
193
+ help=_(
194
+ 'Port(s) (name or ID) to apply firewall group. This '
195
+ 'option can be repeated'
196
+ ),
197
+ )
198
+ port_group.add_argument(
199
+ '--no-port',
200
+ dest='no_port',
201
+ action='store_true',
202
+ help=_('Detach all port from the firewall group'),
203
+ )
204
+ return parser
205
+
206
+ def take_action(
207
+ self, parsed_args: argparse.Namespace
208
+ ) -> tuple[Sequence[str], Iterable[Any]]:
209
+ client = self.app.client_manager.network
210
+ attrs = _get_common_attrs(self.app.client_manager, parsed_args)
211
+ if 'project' in parsed_args and parsed_args.project is not None:
212
+ attrs['project_id'] = identity_common.find_project(
213
+ self.app.client_manager.identity,
214
+ parsed_args.project,
215
+ parsed_args.project_domain,
216
+ ).id
217
+ obj = client.create_firewall_group(**attrs)
218
+ display_columns, columns = utils.get_osc_show_columns_for_sdk_resource(
219
+ obj, _attr_map_dict, ['location', 'tenant_id']
220
+ )
221
+ data = utils.get_dict_properties(obj, columns, formatters=_formatters)
222
+ return (display_columns, data)
223
+
224
+
225
+ class DeleteFirewallGroup(command.Command):
226
+ _description = _("Delete firewall group(s)")
227
+
228
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
229
+ parser = super().get_parser(prog_name)
230
+ parser.add_argument(
231
+ 'firewall_group',
232
+ metavar='<firewall-group>',
233
+ nargs='+',
234
+ help=_('Firewall group(s) to delete (name or ID)'),
235
+ )
236
+ return parser
237
+
238
+ def take_action(self, parsed_args: argparse.Namespace) -> None:
239
+ client = self.app.client_manager.network
240
+ result = 0
241
+ for fwg in parsed_args.firewall_group:
242
+ try:
243
+ fwg = client.find_firewall_group(fwg, ignore_missing=False)
244
+ client.delete_firewall_group(fwg.id)
245
+ except Exception as e:
246
+ result += 1
247
+ LOG.error(
248
+ _(
249
+ "Failed to delete firewall group with "
250
+ "name or ID '%(firewall_group)s': %(e)s"
251
+ ),
252
+ {'firewall_group': fwg, 'e': e},
253
+ )
254
+
255
+ if result > 0:
256
+ total = len(parsed_args.firewall_group)
257
+ msg = _(
258
+ "%(result)s of %(total)s firewall group(s) failed to delete."
259
+ ) % {'result': result, 'total': total}
260
+ raise exceptions.CommandError(msg)
261
+
262
+
263
+ class ListFirewallGroup(command.Lister):
264
+ _description = _("List firewall groups")
265
+
266
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
267
+ parser = super().get_parser(prog_name)
268
+ parser.add_argument(
269
+ '--long',
270
+ action='store_true',
271
+ help=_("List additional fields in output"),
272
+ )
273
+ return parser
274
+
275
+ def take_action(
276
+ self, parsed_args: argparse.Namespace
277
+ ) -> tuple[Sequence[str], Iterable[tuple[Any, ...]]]:
278
+ client = self.app.client_manager.network
279
+ obj = client.firewall_groups()
280
+ headers, columns = column_util.get_column_definitions(
281
+ list(_attr_map), long_listing=parsed_args.long
282
+ )
283
+ return (
284
+ headers,
285
+ (
286
+ utils.get_dict_properties(s, columns, formatters=_formatters)
287
+ for s in obj
288
+ ),
289
+ )
290
+
291
+
292
+ class SetFirewallGroup(command.Command):
293
+ _description = _("Set firewall group properties")
294
+
295
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
296
+ parser = super().get_parser(prog_name)
297
+ _get_common_parser(parser)
298
+ parser.add_argument(
299
+ 'firewall_group',
300
+ metavar='<firewall-group>',
301
+ help=_('Firewall group to update (name or ID)'),
302
+ )
303
+ parser.add_argument(
304
+ '--port',
305
+ metavar='<port>',
306
+ action='append',
307
+ help=_(
308
+ 'Port(s) (name or ID) to apply firewall group. This '
309
+ 'option can be repeated'
310
+ ),
311
+ )
312
+ parser.add_argument(
313
+ '--no-port',
314
+ dest='no_port',
315
+ action='store_true',
316
+ help=_('Detach all port from the firewall group'),
317
+ )
318
+ return parser
319
+
320
+ def take_action(self, parsed_args: argparse.Namespace) -> None:
321
+ client = self.app.client_manager.network
322
+ fwg_id = client.find_firewall_group(
323
+ parsed_args.firewall_group, ignore_missing=False
324
+ ).id
325
+ attrs = _get_common_attrs(
326
+ self.app.client_manager, parsed_args, is_create=False
327
+ )
328
+ try:
329
+ client.update_firewall_group(fwg_id, **attrs)
330
+ except Exception as e:
331
+ msg = _("Failed to set firewall group '%(group)s': %(e)s") % {
332
+ 'group': parsed_args.firewall_group,
333
+ 'e': e,
334
+ }
335
+ raise exceptions.CommandError(msg)
336
+
337
+
338
+ class ShowFirewallGroup(command.ShowOne):
339
+ _description = _("Display firewall group details")
340
+
341
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
342
+ parser = super().get_parser(prog_name)
343
+ parser.add_argument(
344
+ 'firewall_group',
345
+ metavar='<firewall-group>',
346
+ help=_('Firewall group to show (name or ID)'),
347
+ )
348
+ return parser
349
+
350
+ def take_action(
351
+ self, parsed_args: argparse.Namespace
352
+ ) -> tuple[Sequence[str], Iterable[Any]]:
353
+ client = self.app.client_manager.network
354
+ fwg_id = client.find_firewall_group(
355
+ parsed_args.firewall_group, ignore_missing=False
356
+ ).id
357
+ obj = client.get_firewall_group(fwg_id)
358
+ display_columns, columns = utils.get_osc_show_columns_for_sdk_resource(
359
+ obj, _attr_map_dict, ['location', 'tenant_id']
360
+ )
361
+ data = utils.get_dict_properties(obj, columns, formatters=_formatters)
362
+ return (display_columns, data)
363
+
364
+
365
+ class UnsetFirewallGroup(command.Command):
366
+ _description = _("Unset firewall group properties")
367
+
368
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
369
+ parser = super().get_parser(prog_name)
370
+ parser.add_argument(
371
+ 'firewall_group',
372
+ metavar='<firewall-group>',
373
+ help=_('Firewall group to unset (name or ID)'),
374
+ )
375
+ port_group = parser.add_mutually_exclusive_group()
376
+ port_group.add_argument(
377
+ '--port',
378
+ metavar='<port>',
379
+ action='append',
380
+ help=_(
381
+ 'Port(s) (name or ID) to apply firewall group. This '
382
+ 'option can be repeated'
383
+ ),
384
+ )
385
+ port_group.add_argument(
386
+ '--all-port',
387
+ action='store_true',
388
+ help=_('Remove all ports for this firewall group'),
389
+ )
390
+ parser.add_argument(
391
+ '--ingress-firewall-policy',
392
+ action='store_true',
393
+ help=_('Ingress firewall policy (name or ID) to delete'),
394
+ )
395
+ parser.add_argument(
396
+ '--egress-firewall-policy',
397
+ action='store_true',
398
+ dest='egress_firewall_policy',
399
+ help=_('Egress firewall policy (name or ID) to delete'),
400
+ )
401
+ shared_group = parser.add_mutually_exclusive_group()
402
+ shared_group.add_argument(
403
+ '--share',
404
+ action='store_true',
405
+ help=_(
406
+ '(Deprecated) Use "firewall group set --no-share" instead. '
407
+ 'Restrict use of the firewall group to the current project'
408
+ ),
409
+ )
410
+ parser.add_argument(
411
+ '--enable',
412
+ action='store_true',
413
+ help=_(
414
+ '(Deprecated) Use "firewall group set --disable" instead. '
415
+ 'Disable firewall group'
416
+ ),
417
+ )
418
+ return parser
419
+
420
+ def _get_attrs(
421
+ self, client: Any, parsed_args: argparse.Namespace
422
+ ) -> dict[str, Any]:
423
+ attrs: dict[str, Any] = {}
424
+ if parsed_args.ingress_firewall_policy:
425
+ attrs['ingress_firewall_policy_id'] = None
426
+ if parsed_args.egress_firewall_policy:
427
+ attrs['egress_firewall_policy_id'] = None
428
+ if parsed_args.share:
429
+ LOG.warning(
430
+ 'The --share option is deprecated, please use '
431
+ '"firewall group set --no-share" instead.'
432
+ )
433
+ attrs['shared'] = False
434
+ if parsed_args.enable:
435
+ LOG.warning(
436
+ 'The --enable option is deprecated, please use '
437
+ '"firewall group set --disable" instead.'
438
+ )
439
+ attrs['admin_state_up'] = False
440
+ if parsed_args.port:
441
+ old = client.find_firewall_group(
442
+ parsed_args.firewall_group, ignore_missing=False
443
+ ).ports
444
+ new = [
445
+ client.find_port(r, ignore_missing=False).id
446
+ for r in parsed_args.port
447
+ ]
448
+ attrs['ports'] = sorted(list(set(old) - set(new)))
449
+ if parsed_args.all_port:
450
+ attrs['ports'] = []
451
+ return attrs
452
+
453
+ def take_action(self, parsed_args: argparse.Namespace) -> None:
454
+ client = self.app.client_manager.network
455
+ fwg_id = client.find_firewall_group(
456
+ parsed_args.firewall_group, ignore_missing=False
457
+ ).id
458
+ attrs = self._get_attrs(client, parsed_args)
459
+ try:
460
+ client.update_firewall_group(fwg_id, **attrs)
461
+ except Exception as e:
462
+ msg = _("Failed to unset firewall group '%(group)s': %(e)s") % {
463
+ 'group': parsed_args.firewall_group,
464
+ 'e': e,
465
+ }
466
+ raise exceptions.CommandError(msg)