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,574 @@
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
+ _attr_map = (
36
+ ('id', 'ID', column_util.LIST_BOTH),
37
+ ('name', 'Name', column_util.LIST_BOTH),
38
+ ('enabled', 'Enabled', column_util.LIST_BOTH),
39
+ ('summary', 'Summary', column_util.LIST_SHORT_ONLY),
40
+ ('description', 'Description', column_util.LIST_LONG_ONLY),
41
+ ('firewall_policy_id', 'Firewall Policy', column_util.LIST_BOTH),
42
+ ('ip_version', 'IP Version', column_util.LIST_LONG_ONLY),
43
+ ('action', 'Action', column_util.LIST_LONG_ONLY),
44
+ ('protocol', 'Protocol', column_util.LIST_LONG_ONLY),
45
+ ('source_ip_address', 'Source IP Address', column_util.LIST_LONG_ONLY),
46
+ ('source_port', 'Source Port', column_util.LIST_LONG_ONLY),
47
+ (
48
+ 'destination_ip_address',
49
+ 'Destination IP Address',
50
+ column_util.LIST_LONG_ONLY,
51
+ ),
52
+ ('destination_port', 'Destination Port', column_util.LIST_LONG_ONLY),
53
+ ('shared', 'Shared', column_util.LIST_LONG_ONLY),
54
+ ('project_id', 'Project', column_util.LIST_LONG_ONLY),
55
+ (
56
+ 'source_firewall_group_id',
57
+ 'Source Firewall Group ID',
58
+ column_util.LIST_LONG_ONLY,
59
+ ),
60
+ (
61
+ 'destination_firewall_group_id',
62
+ 'Destination Firewall Group ID',
63
+ column_util.LIST_LONG_ONLY,
64
+ ),
65
+ )
66
+
67
+ _attr_map_dict = {x[0]: x[1] for x in _attr_map}
68
+
69
+
70
+ def _convert_to_lowercase(string: str) -> str:
71
+ return string.lower()
72
+
73
+
74
+ def _get_common_parser(
75
+ parser: argparse.ArgumentParser,
76
+ ) -> argparse.ArgumentParser:
77
+ parser.add_argument(
78
+ '--name', metavar='<name>', help=_('Name of the firewall rule')
79
+ )
80
+ parser.add_argument(
81
+ '--description',
82
+ metavar='<description>',
83
+ help=_('Description of the firewall rule'),
84
+ )
85
+ parser.add_argument(
86
+ '--protocol',
87
+ type=_convert_to_lowercase,
88
+ help=_(
89
+ 'IP protocol (ah, dccp, egp, esp, gre, icmp, igmp, '
90
+ 'ipv6-encap, ipv6-frag, ipv6-icmp, ipv6-nonxt, ipv6-opts, '
91
+ 'ipv6-route, ospf, pgm, rsvp, sctp, tcp, udp, udplite, '
92
+ 'vrrp and integer representations [0-255] or any; '
93
+ 'default: any (all protocols))'
94
+ ),
95
+ )
96
+ parser.add_argument(
97
+ '--action',
98
+ choices=['allow', 'deny', 'reject'],
99
+ type=_convert_to_lowercase,
100
+ help=_('Action for the firewall rule'),
101
+ )
102
+ parser.add_argument(
103
+ '--ip-version',
104
+ metavar='<ip-version>',
105
+ choices=['4', '6'],
106
+ help=_('Set IP version 4 or 6 (default is 4)'),
107
+ )
108
+ src_ip_group = parser.add_mutually_exclusive_group()
109
+ src_ip_group.add_argument(
110
+ '--source-ip-address',
111
+ metavar='<source-ip-address>',
112
+ help=_('Source IP address or subnet'),
113
+ )
114
+ src_ip_group.add_argument(
115
+ '--no-source-ip-address',
116
+ action='store_true',
117
+ help=_('Detach source IP address'),
118
+ )
119
+ dst_ip_group = parser.add_mutually_exclusive_group()
120
+ dst_ip_group.add_argument(
121
+ '--destination-ip-address',
122
+ metavar='<destination-ip-address>',
123
+ help=_('Destination IP address or subnet'),
124
+ )
125
+ dst_ip_group.add_argument(
126
+ '--no-destination-ip-address',
127
+ action='store_true',
128
+ help=_('Detach destination IP address'),
129
+ )
130
+ src_port_group = parser.add_mutually_exclusive_group()
131
+ src_port_group.add_argument(
132
+ '--source-port',
133
+ metavar='<source-port>',
134
+ help=_(
135
+ 'Source port number or range '
136
+ '(integer in [1, 65535] or range like 123:456)'
137
+ ),
138
+ )
139
+ src_port_group.add_argument(
140
+ '--no-source-port',
141
+ action='store_true',
142
+ help=_('Detach source port number or range'),
143
+ )
144
+ dst_port_group = parser.add_mutually_exclusive_group()
145
+ dst_port_group.add_argument(
146
+ '--destination-port',
147
+ metavar='<destination-port>',
148
+ help=_(
149
+ 'Destination port number or range'
150
+ '(integer in [1, 65535] or range like 123:456)'
151
+ ),
152
+ )
153
+ dst_port_group.add_argument(
154
+ '--no-destination-port',
155
+ action='store_true',
156
+ help=_('Detach destination port number or range'),
157
+ )
158
+ shared_group = parser.add_mutually_exclusive_group()
159
+ shared_group.add_argument(
160
+ '--share',
161
+ action='store_true',
162
+ default=None,
163
+ dest='shared',
164
+ help=_(
165
+ 'Share the firewall rule to be used in all projects '
166
+ '(by default, it is restricted to be used by the '
167
+ 'current project).'
168
+ ),
169
+ )
170
+ shared_group.add_argument(
171
+ '--no-share',
172
+ action='store_false',
173
+ dest='shared',
174
+ help=_('Restrict use of the firewall rule to the current project'),
175
+ )
176
+ enable_group = parser.add_mutually_exclusive_group()
177
+ enable_group.add_argument(
178
+ '--enable-rule',
179
+ action='store_true',
180
+ default=None,
181
+ dest='enabled',
182
+ help=_('Enable this rule (default is enabled)'),
183
+ )
184
+ enable_group.add_argument(
185
+ '--disable-rule',
186
+ action='store_false',
187
+ dest='enabled',
188
+ help=_('Disable this rule'),
189
+ )
190
+ src_fwg_group = parser.add_mutually_exclusive_group()
191
+ src_fwg_group.add_argument(
192
+ '--source-firewall-group',
193
+ metavar='<source-firewall-group>',
194
+ help=_('Source firewall group (name or ID)'),
195
+ )
196
+ src_fwg_group.add_argument(
197
+ '--no-source-firewall-group',
198
+ action='store_true',
199
+ help=_('No associated source firewall group'),
200
+ )
201
+ dst_fwg_group = parser.add_mutually_exclusive_group()
202
+ dst_fwg_group.add_argument(
203
+ '--destination-firewall-group',
204
+ metavar='<destination-firewall-group>',
205
+ help=_('Destination firewall group (name or ID)'),
206
+ )
207
+ dst_fwg_group.add_argument(
208
+ '--no-destination-firewall-group',
209
+ action='store_true',
210
+ help=_('No associated destination firewall group'),
211
+ )
212
+ return parser
213
+
214
+
215
+ def _get_common_attrs(
216
+ client_manager: Any,
217
+ parsed_args: argparse.Namespace,
218
+ is_create: bool = True,
219
+ ) -> dict[str, Any]:
220
+ attrs: dict[str, Any] = {}
221
+ client = client_manager.network
222
+ if parsed_args.name:
223
+ attrs['name'] = parsed_args.name
224
+ if parsed_args.description:
225
+ attrs['description'] = parsed_args.description
226
+ if parsed_args.protocol:
227
+ protocol = parsed_args.protocol
228
+ attrs['protocol'] = None if protocol == 'any' else protocol
229
+ if parsed_args.action:
230
+ attrs['action'] = parsed_args.action
231
+ if parsed_args.ip_version:
232
+ attrs['ip_version'] = str(parsed_args.ip_version)
233
+
234
+ if parsed_args.source_port:
235
+ attrs['source_port'] = parsed_args.source_port
236
+ if parsed_args.no_source_port:
237
+ attrs['source_port'] = None
238
+
239
+ if parsed_args.source_ip_address:
240
+ attrs['source_ip_address'] = parsed_args.source_ip_address
241
+ if parsed_args.no_source_ip_address:
242
+ attrs['source_ip_address'] = None
243
+
244
+ if parsed_args.destination_port:
245
+ attrs['destination_port'] = parsed_args.destination_port
246
+ if parsed_args.no_destination_port:
247
+ attrs['destination_port'] = None
248
+
249
+ if parsed_args.destination_ip_address:
250
+ attrs['destination_ip_address'] = parsed_args.destination_ip_address
251
+ if parsed_args.no_destination_ip_address:
252
+ attrs['destination_ip_address'] = None
253
+
254
+ if parsed_args.enabled is not None:
255
+ attrs['enabled'] = parsed_args.enabled
256
+
257
+ if parsed_args.shared is not None:
258
+ attrs['shared'] = parsed_args.shared
259
+
260
+ if parsed_args.source_firewall_group:
261
+ attrs['source_firewall_group_id'] = client.find_firewall_group(
262
+ parsed_args.source_firewall_group, ignore_missing=False
263
+ ).id
264
+ if parsed_args.no_source_firewall_group:
265
+ attrs['source_firewall_group_id'] = None
266
+
267
+ if parsed_args.destination_firewall_group:
268
+ attrs['destination_firewall_group_id'] = client.find_firewall_group(
269
+ parsed_args.destination_firewall_group, ignore_missing=False
270
+ ).id
271
+ if parsed_args.no_destination_firewall_group:
272
+ attrs['destination_firewall_group_id'] = None
273
+
274
+ return attrs
275
+
276
+
277
+ class ProtocolColumn(cliff_columns.FormattableColumn[str | None]):
278
+ def human_readable(self) -> str:
279
+ return self._value if self._value else 'any'
280
+
281
+
282
+ _formatters = {'protocol': ProtocolColumn}
283
+
284
+
285
+ class CreateFirewallRule(command.ShowOne):
286
+ _description = _("Create a new firewall rule")
287
+
288
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
289
+ parser = super().get_parser(prog_name)
290
+ _get_common_parser(parser)
291
+ identity_utils.add_project_owner_option_to_parser(parser)
292
+ return parser
293
+
294
+ def take_action(
295
+ self, parsed_args: argparse.Namespace
296
+ ) -> tuple[Sequence[str], Iterable[Any]]:
297
+ client = self.app.client_manager.network
298
+ attrs = _get_common_attrs(self.app.client_manager, parsed_args)
299
+ if 'project' in parsed_args and parsed_args.project is not None:
300
+ attrs['project_id'] = identity_common.find_project(
301
+ self.app.client_manager.identity,
302
+ parsed_args.project,
303
+ parsed_args.project_domain,
304
+ ).id
305
+ obj = client.create_firewall_rule(**attrs)
306
+ display_columns, columns = utils.get_osc_show_columns_for_sdk_resource(
307
+ obj, _attr_map_dict, ['location', 'tenant_id']
308
+ )
309
+ data = utils.get_dict_properties(obj, columns, formatters=_formatters)
310
+ return display_columns, data
311
+
312
+
313
+ class DeleteFirewallRule(command.Command):
314
+ _description = _("Delete firewall rule(s)")
315
+
316
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
317
+ parser = super().get_parser(prog_name)
318
+ parser.add_argument(
319
+ 'firewall_rule',
320
+ metavar='<firewall-rule>',
321
+ nargs='+',
322
+ help=_('Firewall rule(s) to delete (name or ID)'),
323
+ )
324
+ return parser
325
+
326
+ def take_action(self, parsed_args: argparse.Namespace) -> None:
327
+ client = self.app.client_manager.network
328
+ result = 0
329
+ for fwr in parsed_args.firewall_rule:
330
+ try:
331
+ fwr = client.find_firewall_rule(fwr, ignore_missing=False)
332
+ client.delete_firewall_rule(fwr.id)
333
+ except Exception as e:
334
+ result += 1
335
+ LOG.error(
336
+ _(
337
+ "Failed to delete Firewall rule with "
338
+ "name or ID '%(firewall_rule)s': %(e)s"
339
+ ),
340
+ {'firewall_rule': fwr, 'e': e},
341
+ )
342
+
343
+ if result > 0:
344
+ total = len(parsed_args.firewall_rule)
345
+ msg = _(
346
+ "%(result)s of %(total)s firewall rule(s) failed to delete."
347
+ ) % {'result': result, 'total': total}
348
+ raise exceptions.CommandError(msg)
349
+
350
+
351
+ class ListFirewallRule(command.Lister):
352
+ _description = _("List firewall rules that belong to a given tenant")
353
+
354
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
355
+ parser = super().get_parser(prog_name)
356
+ parser.add_argument(
357
+ '--long',
358
+ action='store_true',
359
+ default=False,
360
+ help=_("List additional fields in output"),
361
+ )
362
+ return parser
363
+
364
+ def extend_list(
365
+ self, data: Iterable[Any], parsed_args: argparse.Namespace
366
+ ) -> list[Any]:
367
+ ext_data = []
368
+ for d in data:
369
+ protocol = d['protocol'].upper() if d['protocol'] else 'ANY'
370
+ src_ip = 'none specified'
371
+ dst_ip = 'none specified'
372
+ src_port = '(none specified)'
373
+ dst_port = '(none specified)'
374
+ if d.get('source_ip_address'):
375
+ src_ip = str(d['source_ip_address']).lower()
376
+ if d.get('source_port'):
377
+ src_port = '(' + str(d['source_port']).lower() + ')'
378
+ if d.get('destination_ip_address'):
379
+ dst_ip = str(d['destination_ip_address']).lower()
380
+ if d.get('destination_port'):
381
+ dst_port = '(' + str(d['destination_port']).lower() + ')'
382
+ action = d['action'] if d.get('action') else 'no-action'
383
+ src = 'source(port): ' + src_ip + src_port
384
+ dst = 'dest(port): ' + dst_ip + dst_port
385
+ d['summary'] = ',\n '.join([protocol, src, dst, action])
386
+ ext_data.append(d)
387
+ return ext_data
388
+
389
+ def take_action(
390
+ self, parsed_args: argparse.Namespace
391
+ ) -> tuple[Sequence[str], Iterable[tuple[Any, ...]]]:
392
+ client = self.app.client_manager.network
393
+ obj = client.firewall_rules()
394
+ obj_extend = self.extend_list(obj, parsed_args)
395
+ headers, columns = column_util.get_column_definitions(
396
+ list(_attr_map), long_listing=parsed_args.long
397
+ )
398
+ return (
399
+ headers,
400
+ (
401
+ utils.get_dict_properties(s, columns, formatters=_formatters)
402
+ for s in obj_extend
403
+ ),
404
+ )
405
+
406
+
407
+ class SetFirewallRule(command.Command):
408
+ _description = _("Set firewall rule properties")
409
+
410
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
411
+ parser = super().get_parser(prog_name)
412
+ _get_common_parser(parser)
413
+ parser.add_argument(
414
+ 'firewall_rule',
415
+ metavar='<firewall-rule>',
416
+ help=_('Firewall rule to set (name or ID)'),
417
+ )
418
+ return parser
419
+
420
+ def take_action(self, parsed_args: argparse.Namespace) -> None:
421
+ client = self.app.client_manager.network
422
+ attrs = _get_common_attrs(
423
+ self.app.client_manager, parsed_args, is_create=False
424
+ )
425
+ fwr_id = client.find_firewall_rule(
426
+ parsed_args.firewall_rule, ignore_missing=False
427
+ ).id
428
+ try:
429
+ client.update_firewall_rule(fwr_id, **attrs)
430
+ except Exception as e:
431
+ msg = _("Failed to set firewall rule '%(rule)s': %(e)s") % {
432
+ 'rule': parsed_args.firewall_rule,
433
+ 'e': e,
434
+ }
435
+ raise exceptions.CommandError(msg)
436
+
437
+
438
+ class ShowFirewallRule(command.ShowOne):
439
+ _description = _("Display firewall rule details")
440
+
441
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
442
+ parser = super().get_parser(prog_name)
443
+ parser.add_argument(
444
+ 'firewall_rule',
445
+ metavar='<firewall-rule>',
446
+ help=_('Firewall rule to display (name or ID)'),
447
+ )
448
+ return parser
449
+
450
+ def take_action(
451
+ self, parsed_args: argparse.Namespace
452
+ ) -> tuple[Sequence[str], Iterable[Any]]:
453
+ client = self.app.client_manager.network
454
+ fwr_id = client.find_firewall_rule(
455
+ parsed_args.firewall_rule, ignore_missing=False
456
+ ).id
457
+ obj = client.get_firewall_rule(fwr_id)
458
+ display_columns, columns = utils.get_osc_show_columns_for_sdk_resource(
459
+ obj, _attr_map_dict, ['location', 'tenant_id']
460
+ )
461
+ data = utils.get_dict_properties(obj, columns, formatters=_formatters)
462
+ return (display_columns, data)
463
+
464
+
465
+ class UnsetFirewallRule(command.Command):
466
+ _description = _("Unset firewall rule properties")
467
+
468
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
469
+ parser = super().get_parser(prog_name)
470
+ parser.add_argument(
471
+ 'firewall_rule',
472
+ metavar='<firewall-rule>',
473
+ help=_('Firewall rule to unset (name or ID)'),
474
+ )
475
+ parser.add_argument(
476
+ '--source-ip-address',
477
+ action='store_true',
478
+ help=_('Source IP address or subnet'),
479
+ )
480
+ parser.add_argument(
481
+ '--destination-ip-address',
482
+ action='store_true',
483
+ help=_('Destination IP address or subnet'),
484
+ )
485
+ parser.add_argument(
486
+ '--source-port',
487
+ action='store_true',
488
+ help=_(
489
+ 'Source port number or range'
490
+ '(integer in [1, 65535] or range like 123:456)'
491
+ ),
492
+ )
493
+ parser.add_argument(
494
+ '--destination-port',
495
+ action='store_true',
496
+ help=_(
497
+ 'Destination port number or range'
498
+ '(integer in [1, 65535] or range like 123:456)'
499
+ ),
500
+ )
501
+ parser.add_argument(
502
+ '--share',
503
+ action='store_true',
504
+ help=_(
505
+ '(Deprecated) Use "firewall rule set --no-share" instead. '
506
+ 'Restrict use of the firewall rule to the current project'
507
+ ),
508
+ )
509
+ parser.add_argument(
510
+ '--enable-rule',
511
+ action='store_true',
512
+ help=_(
513
+ '(Deprecated) Use "firewall rule set --disable-rule" instead. '
514
+ 'Disable this rule'
515
+ ),
516
+ )
517
+
518
+ parser.add_argument(
519
+ '--source-firewall-group',
520
+ action='store_true',
521
+ help=_('Source firewall group (name or ID)'),
522
+ )
523
+
524
+ parser.add_argument(
525
+ '--destination-firewall-group',
526
+ action='store_true',
527
+ help=_('Destination firewall group (name or ID)'),
528
+ )
529
+ return parser
530
+
531
+ def _get_attrs(
532
+ self, client_manager: Any, parsed_args: argparse.Namespace
533
+ ) -> dict[str, Any]:
534
+ attrs: dict[str, Any] = {}
535
+ if parsed_args.source_ip_address:
536
+ attrs['source_ip_address'] = None
537
+ if parsed_args.source_port:
538
+ attrs['source_port'] = None
539
+ if parsed_args.destination_ip_address:
540
+ attrs['destination_ip_address'] = None
541
+ if parsed_args.destination_port:
542
+ attrs['destination_port'] = None
543
+ if parsed_args.share:
544
+ LOG.warning(
545
+ 'The --share option is deprecated, please use '
546
+ '"firewall rule set --no-share" instead.'
547
+ )
548
+ attrs['shared'] = False
549
+ if parsed_args.enable_rule:
550
+ LOG.warning(
551
+ 'The --enable-rule option is deprecated, please use '
552
+ '"firewall rule set --disable-rule" instead.'
553
+ )
554
+ attrs['enabled'] = False
555
+ if parsed_args.source_firewall_group:
556
+ attrs['source_firewall_group_id'] = None
557
+ if parsed_args.destination_firewall_group:
558
+ attrs['destination_firewall_group_id'] = None
559
+ return attrs
560
+
561
+ def take_action(self, parsed_args: argparse.Namespace) -> None:
562
+ client = self.app.client_manager.network
563
+ attrs = self._get_attrs(self.app.client_manager, parsed_args)
564
+ fwr_id = client.find_firewall_rule(
565
+ parsed_args.firewall_rule, ignore_missing=False
566
+ ).id
567
+ try:
568
+ client.update_firewall_rule(fwr_id, **attrs)
569
+ except Exception as e:
570
+ msg = _("Failed to unset firewall rule '%(rule)s': %(e)s") % {
571
+ 'rule': parsed_args.firewall_rule,
572
+ 'e': e,
573
+ }
574
+ raise exceptions.CommandError(msg)
@@ -13,6 +13,10 @@
13
13
 
14
14
  """IP Availability Info implementations"""
15
15
 
16
+ import argparse
17
+ from collections.abc import Iterable, Sequence
18
+ from typing import Any
19
+
16
20
  from osc_lib.cli import format_columns
17
21
  from osc_lib import utils
18
22
 
@@ -25,7 +29,7 @@ _formatters = {
25
29
  }
26
30
 
27
31
 
28
- def _get_columns(item):
32
+ def _get_columns(item: Any) -> tuple[tuple[str, ...], tuple[str, ...]]:
29
33
  hidden_columns = ['id', 'name', 'location', 'tenant_id']
30
34
  return utils.get_osc_show_columns_for_sdk_resource(
31
35
  item, {}, hidden_columns
@@ -37,7 +41,7 @@ def _get_columns(item):
37
41
  class ListIPAvailability(command.Lister):
38
42
  _description = _("List IP availability for network")
39
43
 
40
- def get_parser(self, prog_name):
44
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
41
45
  parser = super().get_parser(prog_name)
42
46
  parser.add_argument(
43
47
  '--ip-version',
@@ -62,7 +66,9 @@ class ListIPAvailability(command.Lister):
62
66
  identity_common.add_project_domain_option_to_parser(parser)
63
67
  return parser
64
68
 
65
- def take_action(self, parsed_args):
69
+ def take_action(
70
+ self, parsed_args: argparse.Namespace
71
+ ) -> tuple[tuple[str, ...], Iterable[tuple[Any, ...]]]:
66
72
  client = self.app.client_manager.network
67
73
 
68
74
  columns = (
@@ -106,7 +112,7 @@ class ListIPAvailability(command.Lister):
106
112
  class ShowIPAvailability(command.ShowOne):
107
113
  _description = _("Show network IP availability details")
108
114
 
109
- def get_parser(self, prog_name):
115
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
110
116
  parser = super().get_parser(prog_name)
111
117
  parser.add_argument(
112
118
  'network',
@@ -115,7 +121,9 @@ class ShowIPAvailability(command.ShowOne):
115
121
  )
116
122
  return parser
117
123
 
118
- def take_action(self, parsed_args):
124
+ def take_action(
125
+ self, parsed_args: argparse.Namespace
126
+ ) -> tuple[Sequence[str], Iterable[Any]]:
119
127
  client = self.app.client_manager.network
120
128
  network_id = client.find_network(
121
129
  parsed_args.network, ignore_missing=False