python-openstackclient 9.0.0__py3-none-any.whl → 10.1.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 (352) 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 +59 -43
  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 +36 -34
  14. openstackclient/common/pagination.py +50 -6
  15. openstackclient/common/progressbar.py +7 -6
  16. openstackclient/common/project_cleanup.py +11 -6
  17. openstackclient/common/quota.py +105 -103
  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 +42 -22
  25. openstackclient/compute/v2/host.py +14 -6
  26. openstackclient/compute/v2/hypervisor.py +16 -5
  27. openstackclient/compute/v2/hypervisor_stats.py +10 -2
  28. openstackclient/compute/v2/keypair.py +35 -16
  29. openstackclient/compute/v2/server.py +268 -179
  30. openstackclient/compute/v2/server_backup.py +10 -4
  31. openstackclient/compute/v2/server_event.py +28 -12
  32. openstackclient/compute/v2/server_group.py +23 -11
  33. openstackclient/compute/v2/server_image.py +19 -10
  34. openstackclient/compute/v2/server_migration.py +27 -10
  35. openstackclient/compute/v2/server_share.py +274 -0
  36. openstackclient/compute/v2/server_volume.py +13 -5
  37. openstackclient/compute/v2/service.py +17 -8
  38. openstackclient/compute/v2/usage.py +28 -23
  39. openstackclient/identity/client.py +8 -3
  40. openstackclient/identity/common.py +82 -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 +32 -12
  51. openstackclient/identity/v3/application_credential.py +66 -24
  52. openstackclient/identity/v3/catalog.py +14 -7
  53. openstackclient/identity/v3/consumer.py +22 -11
  54. openstackclient/identity/v3/credential.py +39 -17
  55. openstackclient/identity/v3/domain.py +40 -19
  56. openstackclient/identity/v3/ec2creds.py +25 -12
  57. openstackclient/identity/v3/endpoint.py +98 -64
  58. openstackclient/identity/v3/endpoint_group.py +28 -17
  59. openstackclient/identity/v3/federation_protocol.py +44 -20
  60. openstackclient/identity/v3/group.py +64 -40
  61. openstackclient/identity/v3/identity_provider.py +95 -57
  62. openstackclient/identity/v3/implied_role.py +21 -9
  63. openstackclient/identity/v3/limit.py +42 -17
  64. openstackclient/identity/v3/mapping.py +58 -28
  65. openstackclient/identity/v3/policy.py +23 -12
  66. openstackclient/identity/v3/project.py +59 -26
  67. openstackclient/identity/v3/region.py +39 -17
  68. openstackclient/identity/v3/registered_limit.py +41 -16
  69. openstackclient/identity/v3/role.py +62 -31
  70. openstackclient/identity/v3/role_assignment.py +25 -7
  71. openstackclient/identity/v3/service.py +39 -17
  72. openstackclient/identity/v3/service_provider.py +40 -16
  73. openstackclient/identity/v3/tag.py +23 -6
  74. openstackclient/identity/v3/token.py +30 -14
  75. openstackclient/identity/v3/trust.py +39 -18
  76. openstackclient/identity/v3/unscoped_saml.py +10 -2
  77. openstackclient/identity/v3/user.py +86 -36
  78. openstackclient/image/client.py +7 -3
  79. openstackclient/image/v1/image.py +33 -26
  80. openstackclient/image/v2/cache.py +16 -11
  81. openstackclient/image/v2/image.py +88 -56
  82. openstackclient/image/v2/info.py +7 -1
  83. openstackclient/image/v2/metadef_namespaces.py +117 -20
  84. openstackclient/image/v2/metadef_objects.py +32 -19
  85. openstackclient/image/v2/metadef_properties.py +30 -16
  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 +25 -27
  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 +27 -54
  93. openstackclient/network/v2/address_group.py +39 -16
  94. openstackclient/network/v2/address_scope.py +36 -20
  95. openstackclient/network/v2/bgpvpn/bgpvpn.py +477 -0
  96. openstackclient/network/v2/bgpvpn/constants.py +30 -0
  97. openstackclient/network/v2/bgpvpn/network_association.py +226 -0
  98. openstackclient/network/v2/bgpvpn/port_association.py +504 -0
  99. openstackclient/network/v2/bgpvpn/router_association.py +301 -0
  100. openstackclient/network/v2/default_security_group_rule.py +31 -14
  101. openstackclient/network/v2/floating_ip.py +121 -162
  102. openstackclient/network/v2/floating_ip_port_forwarding.py +41 -19
  103. openstackclient/network/v2/fwaas/__init__.py +0 -0
  104. openstackclient/network/v2/fwaas/group.py +499 -0
  105. openstackclient/network/v2/fwaas/policy.py +518 -0
  106. openstackclient/network/v2/fwaas/rule.py +610 -0
  107. openstackclient/network/v2/ip_availability.py +25 -8
  108. openstackclient/network/v2/l3_conntrack_helper.py +35 -13
  109. openstackclient/network/v2/local_ip.py +27 -13
  110. openstackclient/network/v2/local_ip_association.py +17 -7
  111. openstackclient/network/v2/ndp_proxy.py +23 -11
  112. openstackclient/network/v2/network.py +213 -213
  113. openstackclient/network/v2/network_agent.py +77 -34
  114. openstackclient/network/v2/network_auto_allocated_topology.py +27 -15
  115. openstackclient/network/v2/network_flavor.py +45 -21
  116. openstackclient/network/v2/network_flavor_profile.py +42 -17
  117. openstackclient/network/v2/network_meter.py +39 -15
  118. openstackclient/network/v2/network_meter_rule.py +40 -12
  119. openstackclient/network/v2/network_qos_policy.py +39 -21
  120. openstackclient/network/v2/network_qos_rule.py +48 -18
  121. openstackclient/network/v2/network_qos_rule_type.py +28 -9
  122. openstackclient/network/v2/network_rbac.py +34 -16
  123. openstackclient/network/v2/network_segment.py +32 -11
  124. openstackclient/network/v2/network_segment_range.py +70 -31
  125. openstackclient/network/v2/network_service_provider.py +7 -1
  126. openstackclient/network/v2/network_trunk.py +41 -22
  127. openstackclient/network/v2/port.py +141 -40
  128. openstackclient/network/v2/router.py +101 -67
  129. openstackclient/network/v2/security_group.py +97 -198
  130. openstackclient/network/v2/security_group_rule.py +115 -282
  131. openstackclient/network/v2/subnet.py +63 -34
  132. openstackclient/network/v2/subnet_pool.py +42 -24
  133. openstackclient/network/v2/taas/tap_flow.py +35 -14
  134. openstackclient/network/v2/taas/tap_mirror.py +28 -14
  135. openstackclient/network/v2/taas/tap_service.py +26 -12
  136. openstackclient/object/client.py +7 -2
  137. openstackclient/object/v1/account.py +13 -6
  138. openstackclient/object/v1/container.py +28 -16
  139. openstackclient/object/v1/object.py +28 -16
  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 +59 -19
  151. openstackclient/tests/functional/identity/v3/test_application_credential.py +1 -1
  152. openstackclient/tests/functional/identity/v3/test_group.py +20 -20
  153. openstackclient/tests/functional/identity/v3/test_idp.py +3 -1
  154. openstackclient/tests/functional/identity/v3/test_mapping.py +81 -0
  155. openstackclient/tests/functional/identity/v3/test_project.py +10 -10
  156. openstackclient/tests/functional/identity/v3/test_role.py +18 -18
  157. openstackclient/tests/functional/identity/v3/test_role_assignment.py +12 -12
  158. openstackclient/tests/functional/identity/v3/test_user.py +8 -8
  159. openstackclient/tests/functional/image/base.py +1 -6
  160. openstackclient/tests/functional/network/v2/common.py +5 -2
  161. openstackclient/tests/functional/network/v2/test_floating_ip.py +10 -4
  162. openstackclient/tests/functional/network/v2/test_ip_availability.py +4 -0
  163. openstackclient/tests/functional/network/v2/test_network_meter_rule.py +3 -2
  164. openstackclient/tests/functional/network/v2/test_network_segment.py +5 -0
  165. openstackclient/tests/functional/network/v2/test_subnet.py +13 -9
  166. openstackclient/tests/functional/object/v1/common.py +4 -0
  167. openstackclient/tests/functional/volume/v2/common.py +4 -0
  168. openstackclient/tests/functional/volume/v2/test_volume_snapshot.py +27 -11
  169. openstackclient/tests/functional/volume/v2/test_volume_type.py +2 -2
  170. openstackclient/tests/functional/volume/v3/common.py +4 -0
  171. openstackclient/tests/functional/volume/v3/test_volume_group.py +163 -0
  172. openstackclient/tests/functional/volume/v3/test_volume_snapshot.py +11 -7
  173. openstackclient/tests/functional/volume/v3/test_volume_type.py +2 -2
  174. openstackclient/tests/unit/common/test_availability_zone.py +35 -49
  175. openstackclient/tests/unit/common/test_extension.py +2 -2
  176. openstackclient/tests/unit/common/test_limits.py +1 -1
  177. openstackclient/tests/unit/common/test_module.py +82 -44
  178. openstackclient/tests/unit/common/test_project_cleanup.py +3 -1
  179. openstackclient/tests/unit/common/test_quota.py +15 -26
  180. openstackclient/tests/unit/compute/v2/fakes.py +26 -57
  181. openstackclient/tests/unit/compute/v2/test_agent.py +4 -4
  182. openstackclient/tests/unit/compute/v2/test_aggregate.py +1 -1
  183. openstackclient/tests/unit/compute/v2/test_console.py +2 -2
  184. openstackclient/tests/unit/compute/v2/test_console_connection.py +1 -1
  185. openstackclient/tests/unit/compute/v2/test_flavor.py +29 -3
  186. openstackclient/tests/unit/compute/v2/test_host.py +3 -3
  187. openstackclient/tests/unit/compute/v2/test_hypervisor.py +2 -2
  188. openstackclient/tests/unit/compute/v2/test_hypervisor_stats.py +1 -1
  189. openstackclient/tests/unit/compute/v2/test_keypair.py +7 -7
  190. openstackclient/tests/unit/compute/v2/test_server.py +26 -111
  191. openstackclient/tests/unit/compute/v2/test_server_backup.py +1 -1
  192. openstackclient/tests/unit/compute/v2/test_server_event.py +2 -2
  193. openstackclient/tests/unit/compute/v2/test_server_group.py +1 -1
  194. openstackclient/tests/unit/compute/v2/test_server_image.py +1 -1
  195. openstackclient/tests/unit/compute/v2/test_server_migration.py +4 -4
  196. openstackclient/tests/unit/compute/v2/test_server_share.py +287 -0
  197. openstackclient/tests/unit/compute/v2/test_server_volume.py +2 -2
  198. openstackclient/tests/unit/compute/v2/test_service.py +3 -3
  199. openstackclient/tests/unit/compute/v2/test_usage.py +1 -1
  200. openstackclient/tests/unit/identity/v2_0/fakes.py +3 -7
  201. openstackclient/tests/unit/identity/v2_0/test_endpoint.py +1 -1
  202. openstackclient/tests/unit/identity/v2_0/test_project.py +1 -1
  203. openstackclient/tests/unit/identity/v2_0/test_role.py +1 -1
  204. openstackclient/tests/unit/identity/v2_0/test_role_assignment.py +1 -1
  205. openstackclient/tests/unit/identity/v2_0/test_service.py +1 -1
  206. openstackclient/tests/unit/identity/v2_0/test_token.py +2 -2
  207. openstackclient/tests/unit/identity/v2_0/test_user.py +1 -1
  208. openstackclient/tests/unit/identity/v3/fakes.py +8 -38
  209. openstackclient/tests/unit/identity/v3/test_access_rule.py +3 -3
  210. openstackclient/tests/unit/identity/v3/test_application_credential.py +4 -4
  211. openstackclient/tests/unit/identity/v3/test_credential.py +5 -5
  212. openstackclient/tests/unit/identity/v3/test_domain.py +5 -5
  213. openstackclient/tests/unit/identity/v3/test_endpoint.py +6 -6
  214. openstackclient/tests/unit/identity/v3/test_endpoint_group.py +1 -1
  215. openstackclient/tests/unit/identity/v3/test_group.py +12 -22
  216. openstackclient/tests/unit/identity/v3/test_identity_provider.py +303 -299
  217. openstackclient/tests/unit/identity/v3/test_implied_role.py +1 -1
  218. openstackclient/tests/unit/identity/v3/test_limit.py +5 -5
  219. openstackclient/tests/unit/identity/v3/test_mappings.py +163 -79
  220. openstackclient/tests/unit/identity/v3/test_project.py +28 -5
  221. openstackclient/tests/unit/identity/v3/test_protocol.py +3 -3
  222. openstackclient/tests/unit/identity/v3/test_region.py +5 -5
  223. openstackclient/tests/unit/identity/v3/test_registered_limit.py +5 -5
  224. openstackclient/tests/unit/identity/v3/test_role.py +8 -8
  225. openstackclient/tests/unit/identity/v3/test_role_assignment.py +1 -1
  226. openstackclient/tests/unit/identity/v3/test_service.py +5 -5
  227. openstackclient/tests/unit/identity/v3/test_token.py +2 -2
  228. openstackclient/tests/unit/identity/v3/test_trust.py +4 -4
  229. openstackclient/tests/unit/identity/v3/test_user.py +77 -10
  230. openstackclient/tests/unit/image/v2/test_image.py +11 -11
  231. openstackclient/tests/unit/image/v2/test_metadef_namespaces.py +105 -6
  232. openstackclient/tests/unit/network/test_common.py +0 -155
  233. openstackclient/tests/unit/network/v2/bgpvpn/__init__.py +0 -0
  234. openstackclient/tests/unit/network/v2/bgpvpn/fakes.py +179 -0
  235. openstackclient/tests/unit/network/v2/bgpvpn/test_bgpvpn.py +584 -0
  236. openstackclient/tests/unit/network/v2/bgpvpn/test_network_association.py +285 -0
  237. openstackclient/tests/unit/network/v2/bgpvpn/test_port_association.py +384 -0
  238. openstackclient/tests/unit/network/v2/bgpvpn/test_router_association.py +297 -0
  239. openstackclient/tests/unit/network/v2/fakes.py +5 -77
  240. openstackclient/tests/unit/network/v2/fwaas/__init__.py +0 -0
  241. openstackclient/tests/unit/network/v2/fwaas/test_group.py +923 -0
  242. openstackclient/tests/unit/network/v2/fwaas/test_policy.py +869 -0
  243. openstackclient/tests/unit/network/v2/fwaas/test_rule.py +1005 -0
  244. openstackclient/tests/unit/network/v2/taas/{test_osc_tap_flow.py → test_tap_flow.py} +18 -25
  245. openstackclient/tests/unit/network/v2/taas/{test_osc_tap_mirror.py → test_tap_mirror.py} +19 -29
  246. openstackclient/tests/unit/network/v2/taas/{test_osc_tap_service.py → test_tap_service.py} +19 -29
  247. openstackclient/tests/unit/network/v2/test_address_group.py +26 -2
  248. openstackclient/tests/unit/network/v2/test_address_scope.py +24 -0
  249. openstackclient/tests/unit/network/v2/{test_floating_ip_network.py → test_floating_ip.py} +27 -2
  250. openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py +37 -13
  251. openstackclient/tests/unit/network/v2/test_ip_availability.py +25 -0
  252. openstackclient/tests/unit/network/v2/test_l3_conntrack_helper.py +29 -3
  253. openstackclient/tests/unit/network/v2/test_network.py +74 -12
  254. openstackclient/tests/unit/network/v2/test_network_agent.py +58 -5
  255. openstackclient/tests/unit/network/v2/test_network_auto_allocated_topology.py +3 -3
  256. openstackclient/tests/unit/network/v2/test_network_flavor.py +26 -2
  257. openstackclient/tests/unit/network/v2/test_network_flavor_profile.py +24 -0
  258. openstackclient/tests/unit/network/v2/test_network_meter.py +24 -0
  259. openstackclient/tests/unit/network/v2/test_network_qos_policy.py +25 -1
  260. openstackclient/tests/unit/network/v2/test_network_qos_rule.py +2 -2
  261. openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py +24 -0
  262. openstackclient/tests/unit/network/v2/test_network_rbac.py +25 -1
  263. openstackclient/tests/unit/network/v2/test_network_segment.py +25 -1
  264. openstackclient/tests/unit/network/v2/test_network_segment_range.py +31 -10
  265. openstackclient/tests/unit/network/v2/test_network_trunk.py +1 -1
  266. openstackclient/tests/unit/network/v2/test_port.py +166 -0
  267. openstackclient/tests/unit/network/v2/test_router.py +36 -16
  268. openstackclient/tests/unit/network/v2/{test_security_group_network.py → test_security_group.py} +11 -8
  269. openstackclient/tests/unit/network/v2/{test_security_group_rule_network.py → test_security_group_rule.py} +28 -37
  270. openstackclient/tests/unit/network/v2/test_subnet.py +30 -5
  271. openstackclient/tests/unit/network/v2/test_subnet_pool.py +26 -1
  272. openstackclient/tests/unit/object/v1/fakes.py +8 -7
  273. openstackclient/tests/unit/object/v1/test_container.py +65 -101
  274. openstackclient/tests/unit/object/v1/test_container_all.py +8 -1
  275. openstackclient/tests/unit/object/v1/test_object.py +44 -84
  276. openstackclient/tests/unit/object/v1/test_object_all.py +8 -1
  277. openstackclient/tests/unit/test_hacking.py +108 -0
  278. openstackclient/tests/unit/volume/v2/fakes.py +21 -140
  279. openstackclient/tests/unit/volume/v2/test_volume_backup.py +6 -14
  280. openstackclient/tests/unit/volume/v2/test_volume_snapshot.py +8 -1
  281. openstackclient/tests/unit/volume/v2/test_volume_type.py +2 -4
  282. openstackclient/tests/unit/volume/v3/fakes.py +205 -100
  283. openstackclient/tests/unit/volume/v3/test_backup_record.py +114 -0
  284. openstackclient/tests/unit/volume/v3/test_consistency_group.py +720 -0
  285. openstackclient/tests/unit/volume/v3/test_consistency_group_snapshot.py +354 -0
  286. openstackclient/tests/unit/volume/v3/test_qos_specs.py +455 -0
  287. openstackclient/tests/unit/volume/v3/test_volume.py +60 -3
  288. openstackclient/tests/unit/volume/v3/test_volume_attachment.py +3 -1
  289. openstackclient/tests/unit/volume/v3/test_volume_backend.py +158 -0
  290. openstackclient/tests/unit/volume/v3/test_volume_backup.py +6 -14
  291. openstackclient/tests/unit/volume/v3/test_volume_group_type.py +65 -0
  292. openstackclient/tests/unit/volume/v3/test_volume_host.py +115 -0
  293. openstackclient/tests/unit/volume/v3/test_volume_snapshot.py +61 -1
  294. openstackclient/tests/unit/volume/v3/test_volume_type.py +2 -4
  295. openstackclient/volume/client.py +7 -3
  296. openstackclient/volume/v2/backup_record.py +15 -6
  297. openstackclient/volume/v2/consistency_group.py +29 -17
  298. openstackclient/volume/v2/consistency_group_snapshot.py +25 -10
  299. openstackclient/volume/v2/qos_specs.py +28 -17
  300. openstackclient/volume/v2/service.py +17 -6
  301. openstackclient/volume/v2/volume.py +60 -30
  302. openstackclient/volume/v2/volume_backend.py +19 -6
  303. openstackclient/volume/v2/volume_backup.py +48 -23
  304. openstackclient/volume/v2/volume_host.py +6 -4
  305. openstackclient/volume/v2/volume_snapshot.py +49 -24
  306. openstackclient/volume/v2/volume_transfer_request.py +31 -13
  307. openstackclient/volume/v2/volume_type.py +43 -24
  308. openstackclient/volume/v3/backup_record.py +94 -0
  309. openstackclient/volume/v3/block_storage_cleanup.py +11 -3
  310. openstackclient/volume/v3/block_storage_cluster.py +19 -7
  311. openstackclient/volume/v3/block_storage_log_level.py +15 -6
  312. openstackclient/volume/v3/block_storage_manage.py +10 -4
  313. openstackclient/volume/v3/block_storage_resource_filter.py +17 -5
  314. openstackclient/volume/v3/consistency_group.py +400 -0
  315. openstackclient/volume/v3/consistency_group_snapshot.py +225 -0
  316. openstackclient/volume/v3/qos_specs.py +389 -0
  317. openstackclient/volume/v3/service.py +16 -6
  318. openstackclient/volume/v3/volume.py +92 -40
  319. openstackclient/volume/v3/volume_attachment.py +47 -21
  320. openstackclient/volume/v3/volume_backend.py +130 -0
  321. openstackclient/volume/v3/volume_backup.py +55 -27
  322. openstackclient/volume/v3/volume_group.py +23 -13
  323. openstackclient/volume/v3/volume_group_snapshot.py +34 -17
  324. openstackclient/volume/v3/volume_group_type.py +27 -14
  325. openstackclient/volume/v3/volume_host.py +74 -0
  326. openstackclient/volume/v3/volume_message.py +18 -8
  327. openstackclient/volume/v3/volume_snapshot.py +70 -32
  328. openstackclient/volume/v3/volume_transfer_request.py +31 -13
  329. openstackclient/volume/v3/volume_type.py +42 -24
  330. {python_openstackclient-9.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/METADATA +7 -8
  331. python_openstackclient-10.1.0.dist-info/RECORD +524 -0
  332. {python_openstackclient-9.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/WHEEL +1 -1
  333. {python_openstackclient-9.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/entry_points.txt +77 -25
  334. {python_openstackclient-9.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/licenses/AUTHORS +9 -0
  335. python_openstackclient-10.1.0.dist-info/pbr.json +1 -0
  336. openstackclient/api/image_v1.py +0 -69
  337. openstackclient/api/image_v2.py +0 -79
  338. openstackclient/network/v2/floating_ip_pool.py +0 -38
  339. openstackclient/tests/functional/image/v1/test_image.py +0 -97
  340. openstackclient/tests/unit/api/test_image_v1.py +0 -96
  341. openstackclient/tests/unit/api/test_image_v2.py +0 -96
  342. openstackclient/tests/unit/network/v2/test_floating_ip_compute.py +0 -248
  343. openstackclient/tests/unit/network/v2/test_floating_ip_pool_compute.py +0 -49
  344. openstackclient/tests/unit/network/v2/test_floating_ip_pool_network.py +0 -39
  345. openstackclient/tests/unit/network/v2/test_network_compute.py +0 -404
  346. openstackclient/tests/unit/network/v2/test_security_group_compute.py +0 -392
  347. openstackclient/tests/unit/network/v2/test_security_group_rule_compute.py +0 -555
  348. python_openstackclient-9.0.0.dist-info/RECORD +0 -499
  349. python_openstackclient-9.0.0.dist-info/pbr.json +0 -1
  350. /openstackclient/{tests/functional/image/v1 → network/v2/bgpvpn}/__init__.py +0 -0
  351. {python_openstackclient-9.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/licenses/LICENSE +0 -0
  352. {python_openstackclient-9.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/top_level.txt +0 -0
@@ -14,13 +14,17 @@
14
14
  """Security Group Rule action implementations"""
15
15
 
16
16
  import argparse
17
+ from collections.abc import Iterable, Sequence
17
18
  import logging
19
+ from typing import Any
18
20
 
21
+ from openstack.network.v2 import security_group_rule as _security_group_rule
19
22
  from osc_lib.cli import parseractions
20
23
  from osc_lib import exceptions
21
24
  from osc_lib import utils
22
25
 
23
- from openstackclient.api import compute_v2
26
+ from openstackclient import command
27
+ from openstackclient.common import pagination
24
28
  from openstackclient.i18n import _
25
29
  from openstackclient.identity import common as identity_common
26
30
  from openstackclient.network import common
@@ -29,21 +33,22 @@ from openstackclient.network import utils as network_utils
29
33
  LOG = logging.getLogger(__name__)
30
34
 
31
35
 
32
- def _get_columns(item):
36
+ def _get_columns(
37
+ item: _security_group_rule.SecurityGroupRule,
38
+ ) -> tuple[tuple[str, ...], tuple[str, ...]]:
33
39
  hidden_columns = ['location', 'name', 'tenant_id', 'tags']
34
40
  return utils.get_osc_show_columns_for_sdk_resource(
35
41
  item, {}, hidden_columns
36
42
  )
37
43
 
38
44
 
39
- # TODO(abhiraut): Use the SDK resource mapped attribute names once the
40
- # OSC minimum requirements include SDK 1.0.
41
45
  class CreateSecurityGroupRule(
42
- common.NetworkAndComputeShowOne, common.NeutronCommandWithExtraArgs
46
+ command.ShowOne, common.NeutronCommandWithExtraArgs
43
47
  ):
44
48
  _description = _("Create a new security group rule")
45
49
 
46
- def update_parser_common(self, parser):
50
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
51
+ parser = super().get_parser(prog_name)
47
52
  parser.add_argument(
48
53
  'group',
49
54
  metavar='<group>',
@@ -64,24 +69,11 @@ class CreateSecurityGroupRule(
64
69
  metavar="<group>",
65
70
  help=_("Remote security group (name or ID)"),
66
71
  )
67
- if self.is_neutron:
68
- remote_group.add_argument(
69
- "--remote-address-group",
70
- metavar="<group>",
71
- help=_("Remote address group (name or ID)"),
72
- )
73
-
74
- # NOTE(efried): The --dst-port, --protocol, and --proto options exist
75
- # for both nova-network and neutron, but differ slightly. For the sake
76
- # of the docs build, which has to account for both variants, but only
77
- # add each to the parser once, they are handled here rather than in the
78
- # _network- or _compute-specific methods below.
79
-
80
- # --dst-port has a default for nova-net only
81
- if self.is_nova_network:
82
- dst_port_default = dict(default=(0, 0))
83
- else:
84
- dst_port_default = {}
72
+ remote_group.add_argument(
73
+ "--remote-address-group",
74
+ metavar="<group>",
75
+ help=_("Remote address group (name or ID)"),
76
+ )
85
77
  parser.add_argument(
86
78
  '--dst-port',
87
79
  metavar='<port-range>',
@@ -91,115 +83,69 @@ class CreateSecurityGroupRule(
91
83
  "ending port range: 137:139. Required for IP protocols TCP "
92
84
  "and UDP. Ignored for ICMP IP protocols."
93
85
  ),
94
- **dst_port_default,
95
86
  )
96
-
97
- # NOTE(rtheis): Support either protocol option name for now.
98
- # However, consider deprecating and then removing --proto in
99
- # a future release.
100
- protocol_group = parser.add_mutually_exclusive_group()
101
- # --proto[col] has choices for nova-network only
102
- if self.is_nova_network:
103
- proto_choices = dict(choices=['icmp', 'tcp', 'udp'])
104
- else:
105
- proto_choices = {}
106
- protocol_help_compute = _("IP protocol (icmp, tcp, udp; default: tcp)")
107
- protocol_help_network = _(
108
- "IP protocol (ah, dccp, egp, esp, gre, icmp, igmp, ipv6-encap, "
109
- "ipv6-frag, ipv6-icmp, ipv6-nonxt, ipv6-opts, ipv6-route, ospf, "
110
- "pgm, rsvp, sctp, tcp, udp, udplite, vrrp and integer "
111
- "representations [0-255] or any; default: any (all protocols))"
112
- )
113
- if self.is_nova_network:
114
- protocol_help = protocol_help_compute
115
- elif self.is_neutron:
116
- protocol_help = protocol_help_network
117
- else:
118
- # Docs build: compose help for both nova-network and neutron
119
- protocol_help = self.split_help(
120
- protocol_help_network, protocol_help_compute
121
- )
122
-
123
- protocol_group.add_argument(
87
+ parser.add_argument(
124
88
  '--protocol',
125
89
  metavar='<protocol>',
126
90
  type=network_utils.convert_to_lowercase,
127
- help=protocol_help,
128
- **proto_choices,
91
+ help=_(
92
+ "IP protocol (ah, dccp, egp, esp, gre, icmp, igmp, "
93
+ "ipv6-encap, ipv6-frag, ipv6-icmp, ipv6-nonxt, ipv6-opts, "
94
+ "ipv6-route, ospf, pgm, rsvp, sctp, tcp, udp, udplite, vrrp "
95
+ "and integer representations [0-255] or any; "
96
+ "default: any (all protocols))"
97
+ ),
129
98
  )
130
- if not self.is_docs_build:
131
- protocol_group.add_argument(
132
- '--proto',
133
- metavar='<proto>',
134
- type=network_utils.convert_to_lowercase,
135
- help=argparse.SUPPRESS,
136
- **proto_choices,
137
- )
138
-
139
- return parser
140
-
141
- def update_parser_network(self, parser):
142
99
  parser.add_argument(
143
100
  '--description',
144
101
  metavar='<description>',
145
- help=self.enhance_help_neutron(
146
- _("Set security group rule description")
147
- ),
102
+ help=_("Set security group rule description"),
148
103
  )
149
104
  parser.add_argument(
150
105
  '--icmp-type',
151
106
  metavar='<icmp-type>',
152
107
  type=int,
153
- help=self.enhance_help_neutron(
154
- _("ICMP type for ICMP IP protocols")
155
- ),
108
+ help=_("ICMP type for ICMP IP protocols"),
156
109
  )
157
110
  parser.add_argument(
158
111
  '--icmp-code',
159
112
  metavar='<icmp-code>',
160
113
  type=int,
161
- help=self.enhance_help_neutron(
162
- _("ICMP code for ICMP IP protocols")
163
- ),
114
+ help=_("ICMP code for ICMP IP protocols"),
164
115
  )
165
116
  direction_group = parser.add_mutually_exclusive_group()
166
117
  direction_group.add_argument(
167
118
  '--ingress',
168
119
  action='store_true',
169
- help=self.enhance_help_neutron(
170
- _("Rule applies to incoming network traffic (default)")
171
- ),
120
+ help=_("Rule applies to incoming network traffic (default)"),
172
121
  )
173
122
  direction_group.add_argument(
174
123
  '--egress',
175
124
  action='store_true',
176
- help=self.enhance_help_neutron(
177
- _("Rule applies to outgoing network traffic")
178
- ),
125
+ help=_("Rule applies to outgoing network traffic"),
179
126
  )
180
127
  parser.add_argument(
181
128
  '--ethertype',
182
129
  metavar='<ethertype>',
183
130
  choices=['IPv4', 'IPv6'],
184
131
  type=network_utils.convert_ipvx_case,
185
- help=self.enhance_help_neutron(
186
- _(
187
- "Ethertype of network traffic "
188
- "(IPv4, IPv6; default: based on IP protocol)"
189
- )
132
+ help=_(
133
+ "Ethertype of network traffic "
134
+ "(IPv4, IPv6; default: based on IP protocol)"
190
135
  ),
191
136
  )
192
137
  parser.add_argument(
193
138
  '--project',
194
139
  metavar='<project>',
195
- help=self.enhance_help_neutron(_("Owner's project (name or ID)")),
196
- )
197
- identity_common.add_project_domain_option_to_parser(
198
- parser, enhance_help=self.enhance_help_neutron
140
+ help=_("Owner's project (name or ID)"),
199
141
  )
142
+ identity_common.add_project_domain_option_to_parser(parser)
200
143
  return parser
201
144
 
202
- def take_action_network(self, client, parsed_args):
145
+ def take_action(
146
+ self, parsed_args: argparse.Namespace
147
+ ) -> tuple[Sequence[str], Iterable[Any]]:
148
+ client = self.app.client_manager.network
203
149
  # Get the security group ID to hold the rule.
204
150
  security_group_id = client.find_security_group(
205
151
  parsed_args.group, ignore_missing=False
@@ -291,46 +237,12 @@ class CreateSecurityGroupRule(
291
237
  data = utils.get_item_properties(obj, columns)
292
238
  return (display_columns, data)
293
239
 
294
- def take_action_compute(self, client, parsed_args):
295
- group = compute_v2.find_security_group(client, parsed_args.group)
296
- protocol = network_utils.get_protocol(
297
- parsed_args, default_protocol='tcp'
298
- )
299
- if protocol == 'icmp':
300
- from_port, to_port = -1, -1
301
- else:
302
- from_port, to_port = parsed_args.dst_port
303
240
 
304
- remote_ip = None
305
- if parsed_args.remote_group is not None:
306
- parsed_args.remote_group = compute_v2.find_security_group(
307
- client, parsed_args.remote_group
308
- )['id']
309
- if parsed_args.remote_ip is not None:
310
- remote_ip = parsed_args.remote_ip
311
- else:
312
- remote_ip = '0.0.0.0/0'
313
-
314
- obj = compute_v2.create_security_group_rule(
315
- client,
316
- security_group_id=group['id'],
317
- ip_protocol=protocol,
318
- from_port=from_port,
319
- to_port=to_port,
320
- remote_ip=remote_ip,
321
- remote_group=parsed_args.remote_group,
322
- )
323
- return network_utils.format_security_group_rule_show(obj)
324
-
325
-
326
- class DeleteSecurityGroupRule(common.NetworkAndComputeDelete):
241
+ class DeleteSecurityGroupRule(command.Command):
327
242
  _description = _("Delete security group rule(s)")
328
243
 
329
- # Used by base class to find resources in parsed_args.
330
- resource = 'rule'
331
- r = None
332
-
333
- def update_parser_common(self, parser):
244
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
245
+ parser = super().get_parser(prog_name)
334
246
  parser.add_argument(
335
247
  'rule',
336
248
  metavar='<rule>',
@@ -339,131 +251,110 @@ class DeleteSecurityGroupRule(common.NetworkAndComputeDelete):
339
251
  )
340
252
  return parser
341
253
 
342
- def take_action_network(self, client, parsed_args):
343
- obj = client.find_security_group_rule(self.r, ignore_missing=False)
344
- client.delete_security_group_rule(obj)
254
+ def take_action(self, parsed_args: argparse.Namespace) -> None:
255
+ client = self.app.client_manager.network
256
+ result = 0
257
+
258
+ for rule in parsed_args.rule:
259
+ try:
260
+ obj = client.find_security_group_rule(
261
+ rule, ignore_missing=False
262
+ )
263
+ client.delete_security_group_rule(obj)
264
+ except Exception as e:
265
+ result += 1
266
+ LOG.error(
267
+ _(
268
+ "Failed to delete security group rule with "
269
+ "name or ID '%(rule)s': %(e)s"
270
+ ),
271
+ {'rule': rule, 'e': e},
272
+ )
345
273
 
346
- def take_action_compute(self, client, parsed_args):
347
- compute_v2.delete_security_group_rule(client, self.r)
274
+ if result > 0:
275
+ total = len(parsed_args.rule)
276
+ msg = _("%(result)s of %(total)s rules failed to delete.") % {
277
+ 'result': result,
278
+ 'total': total,
279
+ }
280
+ raise exceptions.CommandError(msg)
348
281
 
349
282
 
350
- class ListSecurityGroupRule(common.NetworkAndComputeLister):
283
+ class ListSecurityGroupRule(command.Lister):
351
284
  _description = _("List security group rules")
352
285
 
353
- def _format_network_security_group_rule(self, rule):
286
+ @staticmethod
287
+ def _format_network_security_group_rule(
288
+ rule: _security_group_rule.SecurityGroupRule,
289
+ ) -> dict[str, object]:
354
290
  """Transform the SDK SecurityGroupRule object to a dict
355
291
 
356
292
  The SDK object gets in the way of reformatting columns...
357
293
  Create port_range column from port_range_min and port_range_max
358
294
  """
359
- rule = rule.to_dict()
360
- rule['port_range'] = network_utils.format_network_port_range(rule)
361
- rule['remote_ip_prefix'] = network_utils.format_remote_ip_prefix(rule)
362
- return rule
295
+ data = rule.to_dict()
296
+ data['port_range'] = network_utils.format_network_port_range(data)
297
+ data['remote_ip_prefix'] = network_utils.format_remote_ip_prefix(data)
298
+ return data
363
299
 
364
- def update_parser_common(self, parser):
300
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
301
+ parser = super().get_parser(prog_name)
365
302
  parser.add_argument(
366
303
  'group',
367
304
  metavar='<group>',
368
305
  nargs='?',
369
306
  help=_("List all rules in this security group (name or ID)"),
370
307
  )
371
- return parser
372
-
373
- def update_parser_network(self, parser):
374
- if not self.is_docs_build:
375
- # Accept but hide the argument for consistency with compute.
376
- # Network will always return all projects for an admin.
377
- parser.add_argument(
378
- '--all-projects',
379
- action='store_true',
380
- default=False,
381
- help=argparse.SUPPRESS,
382
- )
383
-
384
308
  parser.add_argument(
385
309
  '--protocol',
386
310
  metavar='<protocol>',
387
311
  type=network_utils.convert_to_lowercase,
388
- help=self.enhance_help_neutron(
389
- _(
390
- "List only rules with the specified IP protocol "
391
- "(ah, dhcp, egp, esp, gre, "
392
- "icmp, igmp, ipv6-encap, ipv6-frag, ipv6-icmp, "
393
- "ipv6-nonxt, ipv6-opts, ipv6-route, ospf, pgm, rsvp, "
394
- "sctp, tcp, udp, udplite, vrrp and integer "
395
- "representations [0-255] or any; "
396
- "default: any (all protocols))"
397
- )
312
+ help=_(
313
+ "List only rules with the specified IP protocol "
314
+ "(ah, dhcp, egp, esp, gre, icmp, igmp, ipv6-encap, "
315
+ "ipv6-frag, ipv6-icmp, ipv6-nonxt, ipv6-opts, ipv6-route, "
316
+ "ospf, pgm, rsvp, sctp, tcp, udp, udplite, vrrp and integer "
317
+ "representations [0-255] or any; "
318
+ "default: any (all protocols))"
398
319
  ),
399
320
  )
400
321
  parser.add_argument(
401
322
  '--ethertype',
402
323
  metavar='<ethertype>',
403
324
  type=network_utils.convert_to_lowercase,
404
- help=self.enhance_help_neutron(
405
- _(
406
- "List only rules with the specified Ethertype "
407
- "(IPv4 or IPv6)"
408
- )
325
+ help=_(
326
+ "List only rules with the specified Ethertype (IPv4 or IPv6)"
409
327
  ),
410
328
  )
411
329
  direction_group = parser.add_mutually_exclusive_group()
412
330
  direction_group.add_argument(
413
331
  '--ingress',
414
332
  action='store_true',
415
- help=self.enhance_help_neutron(
416
- _("List only rules applied to incoming network traffic")
417
- ),
333
+ help=_("List only rules applied to incoming network traffic"),
418
334
  )
419
335
  direction_group.add_argument(
420
336
  '--egress',
421
337
  action='store_true',
422
- help=self.enhance_help_neutron(
423
- _("List only rules applied to outgoing network traffic")
424
- ),
338
+ help=_("List only rules applied to outgoing network traffic"),
425
339
  )
426
340
  parser.add_argument(
427
341
  '--long',
428
342
  action='store_true',
429
343
  default=False,
430
- help=self.enhance_help_neutron(
431
- _("**Deprecated** This argument is no longer needed")
432
- ),
344
+ help=_("**Deprecated** This argument is no longer needed"),
433
345
  )
434
346
  parser.add_argument(
435
347
  '--project',
436
348
  metavar='<project>',
437
- help=self.enhance_help_neutron(
438
- _("List only rules with the specified project (name or ID)")
439
- ),
440
- )
441
- identity_common.add_project_domain_option_to_parser(
442
- parser, enhance_help=self.enhance_help_neutron
443
- )
444
- return parser
445
-
446
- def update_parser_compute(self, parser):
447
- parser.add_argument(
448
- '--all-projects',
449
- action='store_true',
450
- default=False,
451
- help=self.enhance_help_nova_network(
452
- _("Display information from all projects (admin only)")
453
- ),
349
+ help=_("List only rules with the specified project (name or ID)"),
454
350
  )
455
- if not self.is_docs_build:
456
- # Accept but hide the argument for consistency with network.
457
- # There are no additional fields to display at this time.
458
- parser.add_argument(
459
- '--long',
460
- action='store_false',
461
- default=False,
462
- help=argparse.SUPPRESS,
463
- )
351
+ identity_common.add_project_domain_option_to_parser(parser)
352
+ pagination.add_marker_pagination_option_to_parser(parser)
464
353
  return parser
465
354
 
466
- def _get_column_headers(self, parsed_args):
355
+ def _get_column_headers(
356
+ self, parsed_args: argparse.Namespace
357
+ ) -> tuple[str, ...]:
467
358
  column_headers: tuple[str, ...] = (
468
359
  'ID',
469
360
  'IP Protocol',
@@ -472,14 +363,16 @@ class ListSecurityGroupRule(common.NetworkAndComputeLister):
472
363
  'Port Range',
473
364
  'Direction',
474
365
  'Remote Security Group',
366
+ 'Remote Address Group',
475
367
  )
476
- if self.is_neutron:
477
- column_headers += ('Remote Address Group',)
478
368
  if parsed_args.group is None:
479
369
  column_headers += ('Security Group',)
480
370
  return column_headers
481
371
 
482
- def take_action_network(self, client, parsed_args):
372
+ def take_action(
373
+ self, parsed_args: argparse.Namespace
374
+ ) -> tuple[Sequence[str], Iterable[Any]]:
375
+ client = self.app.client_manager.network
483
376
  if parsed_args.long:
484
377
  msg = _(
485
378
  "The --long option has been deprecated and is no longer needed"
@@ -524,9 +417,15 @@ class ListSecurityGroupRule(common.NetworkAndComputeLister):
524
417
  parsed_args.project,
525
418
  parsed_args.project_domain,
526
419
  ).id
527
- query['tenant_id'] = project_id
528
420
  query['project_id'] = project_id
529
421
 
422
+ if parsed_args.marker is not None:
423
+ query['marker'] = parsed_args.marker
424
+ if parsed_args.limit is not None:
425
+ query['limit'] = parsed_args.limit
426
+ if parsed_args.max_items is not None:
427
+ query['max_items'] = parsed_args.max_items
428
+
530
429
  rules = [
531
430
  self._format_network_security_group_rule(r)
532
431
  for r in client.security_group_rules(**query)
@@ -543,57 +442,12 @@ class ListSecurityGroupRule(common.NetworkAndComputeLister):
543
442
  ),
544
443
  )
545
444
 
546
- def take_action_compute(self, client, parsed_args):
547
- column_headers = self._get_column_headers(parsed_args)
548
- columns: tuple[str, ...] = (
549
- "ID",
550
- "IP Protocol",
551
- "Ethertype",
552
- "IP Range",
553
- "Port Range",
554
- "Remote Security Group",
555
- )
556
445
 
557
- rules_to_list = []
558
- if parsed_args.group is not None:
559
- security_group = compute_v2.find_security_group(
560
- client, parsed_args.group
561
- )
562
- rules_to_list = security_group['rules']
563
- else:
564
- columns += ('parent_group_id',)
565
- for security_group in compute_v2.list_security_groups(
566
- client, all_projects=parsed_args.all_projects
567
- ):
568
- rules_to_list.extend(security_group['rules'])
569
-
570
- # NOTE(rtheis): Turn the raw rules into resources.
571
- rules = []
572
- for rule in rules_to_list:
573
- rules.append(
574
- network_utils.transform_compute_security_group_rule(rule),
575
- )
576
- # rules.append(compute_secgroup_rules.SecurityGroupRule(
577
- # client.security_group_rules,
578
- # network_utils.transform_compute_security_group_rule(rule),
579
- # ))
580
-
581
- return (
582
- column_headers,
583
- (
584
- utils.get_dict_properties(
585
- s,
586
- columns,
587
- )
588
- for s in rules
589
- ),
590
- )
591
-
592
-
593
- class ShowSecurityGroupRule(common.NetworkAndComputeShowOne):
446
+ class ShowSecurityGroupRule(command.ShowOne):
594
447
  _description = _("Display security group rule details")
595
448
 
596
- def update_parser_common(self, parser):
449
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
450
+ parser = super().get_parser(prog_name)
597
451
  parser.add_argument(
598
452
  'rule',
599
453
  metavar="<rule>",
@@ -601,7 +455,10 @@ class ShowSecurityGroupRule(common.NetworkAndComputeShowOne):
601
455
  )
602
456
  return parser
603
457
 
604
- def take_action_network(self, client, parsed_args):
458
+ def take_action(
459
+ self, parsed_args: argparse.Namespace
460
+ ) -> tuple[Sequence[str], Iterable[Any]]:
461
+ client = self.app.client_manager.network
605
462
  obj = client.find_security_group_rule(
606
463
  parsed_args.rule, ignore_missing=False
607
464
  )
@@ -613,27 +470,3 @@ class ShowSecurityGroupRule(common.NetworkAndComputeShowOne):
613
470
  display_columns, columns = _get_columns(obj)
614
471
  data = utils.get_item_properties(obj, columns)
615
472
  return (display_columns, data)
616
-
617
- def take_action_compute(self, client, parsed_args):
618
- # NOTE(rtheis): Unfortunately, compute does not have an API
619
- # to get or list security group rules so parse through the
620
- # security groups to find all accessible rules in search of
621
- # the requested rule.
622
- obj = None
623
- security_group_rules = []
624
- for security_group in compute_v2.list_security_groups(client):
625
- security_group_rules.extend(security_group['rules'])
626
- for security_group_rule in security_group_rules:
627
- if parsed_args.rule == str(security_group_rule.get('id')):
628
- obj = security_group_rule
629
- break
630
-
631
- if obj is None:
632
- msg = (
633
- _("Could not find security group rule with ID '%s'")
634
- % parsed_args.rule
635
- )
636
- raise exceptions.CommandError(msg)
637
-
638
- # NOTE(rtheis): Format security group rule
639
- return network_utils.format_security_group_rule_show(obj)