python-openstackclient 7.4.0__py3-none-any.whl → 8.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 (264) hide show
  1. openstackclient/common/availability_zone.py +3 -6
  2. openstackclient/common/clientmanager.py +2 -1
  3. openstackclient/common/envvars.py +57 -0
  4. openstackclient/common/extension.py +3 -11
  5. openstackclient/common/limits.py +1 -1
  6. openstackclient/common/project_cleanup.py +3 -2
  7. openstackclient/common/quota.py +54 -28
  8. openstackclient/compute/client.py +7 -5
  9. openstackclient/compute/v2/agent.py +5 -5
  10. openstackclient/compute/v2/aggregate.py +17 -15
  11. openstackclient/compute/v2/console.py +10 -4
  12. openstackclient/compute/v2/console_connection.py +48 -0
  13. openstackclient/compute/v2/flavor.py +14 -18
  14. openstackclient/compute/v2/host.py +3 -3
  15. openstackclient/compute/v2/hypervisor.py +10 -4
  16. openstackclient/compute/v2/hypervisor_stats.py +1 -1
  17. openstackclient/compute/v2/keypair.py +18 -13
  18. openstackclient/compute/v2/server.py +144 -121
  19. openstackclient/compute/v2/server_backup.py +1 -1
  20. openstackclient/compute/v2/server_event.py +8 -17
  21. openstackclient/compute/v2/server_group.py +6 -6
  22. openstackclient/compute/v2/server_image.py +1 -1
  23. openstackclient/compute/v2/server_migration.py +6 -6
  24. openstackclient/compute/v2/server_volume.py +4 -4
  25. openstackclient/compute/v2/service.py +9 -13
  26. openstackclient/compute/v2/usage.py +4 -6
  27. openstackclient/identity/client.py +2 -4
  28. openstackclient/identity/common.py +95 -17
  29. openstackclient/identity/v2_0/ec2creds.py +4 -3
  30. openstackclient/identity/v2_0/endpoint.py +12 -10
  31. openstackclient/identity/v2_0/project.py +6 -6
  32. openstackclient/identity/v2_0/role.py +1 -1
  33. openstackclient/identity/v2_0/service.py +7 -7
  34. openstackclient/identity/v2_0/user.py +6 -21
  35. openstackclient/identity/v3/access_rule.py +2 -5
  36. openstackclient/identity/v3/application_credential.py +2 -2
  37. openstackclient/identity/v3/consumer.py +4 -3
  38. openstackclient/identity/v3/credential.py +6 -7
  39. openstackclient/identity/v3/domain.py +63 -44
  40. openstackclient/identity/v3/ec2creds.py +4 -3
  41. openstackclient/identity/v3/endpoint.py +104 -88
  42. openstackclient/identity/v3/endpoint_group.py +1 -1
  43. openstackclient/identity/v3/group.py +116 -72
  44. openstackclient/identity/v3/identity_provider.py +1 -2
  45. openstackclient/identity/v3/limit.py +4 -9
  46. openstackclient/identity/v3/mapping.py +4 -3
  47. openstackclient/identity/v3/policy.py +5 -8
  48. openstackclient/identity/v3/project.py +23 -6
  49. openstackclient/identity/v3/region.py +2 -5
  50. openstackclient/identity/v3/registered_limit.py +4 -8
  51. openstackclient/identity/v3/role.py +15 -16
  52. openstackclient/identity/v3/service.py +8 -8
  53. openstackclient/identity/v3/service_provider.py +3 -6
  54. openstackclient/identity/v3/tag.py +2 -2
  55. openstackclient/identity/v3/token.py +1 -2
  56. openstackclient/identity/v3/trust.py +74 -25
  57. openstackclient/identity/v3/user.py +47 -11
  58. openstackclient/image/client.py +7 -5
  59. openstackclient/image/v1/image.py +11 -15
  60. openstackclient/image/v2/cache.py +2 -4
  61. openstackclient/image/v2/image.py +41 -48
  62. openstackclient/image/v2/metadef_namespaces.py +4 -3
  63. openstackclient/image/v2/metadef_resource_type_association.py +1 -2
  64. openstackclient/image/v2/metadef_resource_types.py +1 -2
  65. openstackclient/locale/tr_TR/LC_MESSAGES/openstackclient.po +9 -1370
  66. openstackclient/network/client.py +4 -16
  67. openstackclient/network/common.py +16 -12
  68. openstackclient/network/utils.py +3 -3
  69. openstackclient/network/v2/address_group.py +5 -9
  70. openstackclient/network/v2/address_scope.py +2 -3
  71. openstackclient/network/v2/default_security_group_rule.py +1 -2
  72. openstackclient/network/v2/floating_ip.py +69 -47
  73. openstackclient/network/v2/floating_ip_port_forwarding.py +7 -7
  74. openstackclient/network/v2/ip_availability.py +1 -2
  75. openstackclient/network/v2/l3_conntrack_helper.py +8 -12
  76. openstackclient/network/v2/local_ip.py +24 -26
  77. openstackclient/network/v2/local_ip_association.py +4 -5
  78. openstackclient/network/v2/ndp_proxy.py +9 -10
  79. openstackclient/network/v2/network.py +12 -16
  80. openstackclient/network/v2/network_agent.py +29 -37
  81. openstackclient/network/v2/network_auto_allocated_topology.py +4 -5
  82. openstackclient/network/v2/network_flavor.py +1 -1
  83. openstackclient/network/v2/network_flavor_profile.py +5 -5
  84. openstackclient/network/v2/network_meter.py +3 -3
  85. openstackclient/network/v2/network_meter_rule.py +5 -8
  86. openstackclient/network/v2/network_qos_policy.py +4 -4
  87. openstackclient/network/v2/network_qos_rule.py +7 -16
  88. openstackclient/network/v2/network_rbac.py +4 -4
  89. openstackclient/network/v2/network_segment.py +6 -7
  90. openstackclient/network/v2/network_segment_range.py +16 -20
  91. openstackclient/network/v2/network_trunk.py +24 -16
  92. openstackclient/network/v2/port.py +28 -29
  93. openstackclient/network/v2/router.py +53 -42
  94. openstackclient/network/v2/security_group.py +13 -19
  95. openstackclient/network/v2/security_group_rule.py +10 -11
  96. openstackclient/network/v2/subnet.py +31 -30
  97. openstackclient/network/v2/subnet_pool.py +4 -4
  98. openstackclient/object/client.py +2 -3
  99. openstackclient/object/v1/container.py +2 -3
  100. openstackclient/object/v1/object.py +2 -9
  101. openstackclient/shell.py +22 -5
  102. openstackclient/tests/functional/base.py +7 -3
  103. openstackclient/tests/functional/common/test_quota.py +3 -1
  104. openstackclient/tests/functional/compute/v2/common.py +12 -6
  105. openstackclient/tests/functional/compute/v2/test_keypair.py +41 -5
  106. openstackclient/tests/functional/compute/v2/test_server.py +2 -3
  107. openstackclient/tests/functional/compute/v2/test_server_event.py +1 -1
  108. openstackclient/tests/functional/identity/v2/test_user.py +1 -1
  109. openstackclient/tests/functional/identity/v3/common.py +3 -8
  110. openstackclient/tests/functional/identity/v3/test_application_credential.py +10 -10
  111. openstackclient/tests/functional/identity/v3/test_endpoint.py +3 -3
  112. openstackclient/tests/functional/identity/v3/test_group.py +3 -3
  113. openstackclient/tests/functional/identity/v3/test_idp.py +3 -7
  114. openstackclient/tests/functional/identity/v3/test_limit.py +4 -4
  115. openstackclient/tests/functional/identity/v3/test_project.py +5 -14
  116. openstackclient/tests/functional/identity/v3/test_region.py +1 -3
  117. openstackclient/tests/functional/identity/v3/test_registered_limit.py +3 -3
  118. openstackclient/tests/functional/identity/v3/test_role.py +1 -1
  119. openstackclient/tests/functional/identity/v3/test_role_assignment.py +13 -31
  120. openstackclient/tests/functional/identity/v3/test_service_provider.py +3 -7
  121. openstackclient/tests/functional/identity/v3/test_user.py +8 -8
  122. openstackclient/tests/functional/network/v2/common.py +7 -3
  123. openstackclient/tests/functional/network/v2/test_address_group.py +4 -0
  124. openstackclient/tests/functional/network/v2/test_l3_conntrack_helper.py +15 -11
  125. openstackclient/tests/functional/network/v2/test_local_ip.py +4 -0
  126. openstackclient/tests/functional/network/v2/test_network_meter_rule.py +2 -2
  127. openstackclient/tests/functional/network/v2/test_network_ndp_proxy.py +2 -3
  128. openstackclient/tests/functional/network/v2/test_network_rbac.py +2 -2
  129. openstackclient/tests/functional/network/v2/test_network_trunk.py +1 -1
  130. openstackclient/tests/functional/network/v2/test_port.py +17 -7
  131. openstackclient/tests/functional/network/v2/test_router.py +42 -0
  132. openstackclient/tests/functional/network/v2/test_subnet_pool.py +4 -0
  133. openstackclient/tests/unit/api/test_compute_v2.py +67 -87
  134. openstackclient/tests/unit/common/test_availability_zone.py +6 -14
  135. openstackclient/tests/unit/common/test_command.py +1 -1
  136. openstackclient/tests/unit/common/test_extension.py +5 -7
  137. openstackclient/tests/unit/common/test_limits.py +1 -1
  138. openstackclient/tests/unit/common/test_project_cleanup.py +5 -6
  139. openstackclient/tests/unit/common/test_quota.py +51 -28
  140. openstackclient/tests/unit/compute/v2/fakes.py +85 -315
  141. openstackclient/tests/unit/compute/v2/test_agent.py +16 -16
  142. openstackclient/tests/unit/compute/v2/test_aggregate.py +56 -60
  143. openstackclient/tests/unit/compute/v2/test_console.py +34 -17
  144. openstackclient/tests/unit/compute/v2/test_console_connection.py +72 -0
  145. openstackclient/tests/unit/compute/v2/test_flavor.py +72 -72
  146. openstackclient/tests/unit/compute/v2/test_host.py +8 -8
  147. openstackclient/tests/unit/compute/v2/test_hypervisor.py +22 -30
  148. openstackclient/tests/unit/compute/v2/test_hypervisor_stats.py +2 -2
  149. openstackclient/tests/unit/compute/v2/test_keypair.py +36 -29
  150. openstackclient/tests/unit/compute/v2/test_server.py +693 -606
  151. openstackclient/tests/unit/compute/v2/test_server_backup.py +36 -77
  152. openstackclient/tests/unit/compute/v2/test_server_event.py +18 -20
  153. openstackclient/tests/unit/compute/v2/test_server_group.py +25 -31
  154. openstackclient/tests/unit/compute/v2/test_server_image.py +37 -78
  155. openstackclient/tests/unit/compute/v2/test_server_migration.py +41 -41
  156. openstackclient/tests/unit/compute/v2/test_server_volume.py +12 -12
  157. openstackclient/tests/unit/compute/v2/test_service.py +39 -45
  158. openstackclient/tests/unit/compute/v2/test_usage.py +5 -5
  159. openstackclient/tests/unit/identity/v2_0/fakes.py +1 -1
  160. openstackclient/tests/unit/identity/v3/test_access_rule.py +1 -3
  161. openstackclient/tests/unit/identity/v3/test_application_credential.py +48 -26
  162. openstackclient/tests/unit/identity/v3/test_domain.py +115 -105
  163. openstackclient/tests/unit/identity/v3/test_endpoint.py +167 -172
  164. openstackclient/tests/unit/identity/v3/test_group.py +353 -202
  165. openstackclient/tests/unit/identity/v3/test_mappings.py +2 -2
  166. openstackclient/tests/unit/identity/v3/test_project.py +16 -0
  167. openstackclient/tests/unit/identity/v3/test_trust.py +5 -2
  168. openstackclient/tests/unit/identity/v3/test_user.py +102 -6
  169. openstackclient/tests/unit/image/v1/fakes.py +2 -2
  170. openstackclient/tests/unit/image/v1/test_image.py +8 -9
  171. openstackclient/tests/unit/image/v2/test_image.py +84 -46
  172. openstackclient/tests/unit/integ/cli/test_shell.py +1 -2
  173. openstackclient/tests/unit/network/test_common.py +2 -2
  174. openstackclient/tests/unit/network/v2/fakes.py +405 -485
  175. openstackclient/tests/unit/network/v2/test_floating_ip_compute.py +8 -14
  176. openstackclient/tests/unit/network/v2/test_floating_ip_network.py +62 -54
  177. openstackclient/tests/unit/network/v2/test_floating_ip_pool_compute.py +1 -1
  178. openstackclient/tests/unit/network/v2/test_l3_conntrack_helper.py +2 -2
  179. openstackclient/tests/unit/network/v2/test_ndp_proxy.py +1 -3
  180. openstackclient/tests/unit/network/v2/test_network.py +4 -4
  181. openstackclient/tests/unit/network/v2/test_network_agent.py +15 -29
  182. openstackclient/tests/unit/network/v2/test_network_compute.py +11 -11
  183. openstackclient/tests/unit/network/v2/test_network_qos_policy.py +16 -19
  184. openstackclient/tests/unit/network/v2/test_network_qos_rule.py +79 -152
  185. openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py +4 -6
  186. openstackclient/tests/unit/network/v2/test_network_rbac.py +2 -2
  187. openstackclient/tests/unit/network/v2/test_network_trunk.py +2 -2
  188. openstackclient/tests/unit/network/v2/test_port.py +21 -22
  189. openstackclient/tests/unit/network/v2/test_router.py +130 -51
  190. openstackclient/tests/unit/network/v2/test_security_group_compute.py +11 -19
  191. openstackclient/tests/unit/network/v2/test_security_group_network.py +25 -27
  192. openstackclient/tests/unit/network/v2/test_security_group_rule_compute.py +15 -17
  193. openstackclient/tests/unit/network/v2/test_security_group_rule_network.py +33 -39
  194. openstackclient/tests/unit/object/v1/test_object_all.py +4 -3
  195. openstackclient/tests/unit/test_shell.py +16 -13
  196. openstackclient/tests/unit/volume/v2/fakes.py +1 -2
  197. openstackclient/tests/unit/volume/v2/test_service.py +57 -91
  198. openstackclient/tests/unit/volume/v2/test_volume.py +109 -106
  199. openstackclient/tests/unit/volume/v2/test_volume_backup.py +141 -148
  200. openstackclient/tests/unit/volume/v2/test_volume_snapshot.py +293 -283
  201. openstackclient/tests/unit/volume/v2/test_volume_transfer_request.py +1 -1
  202. openstackclient/tests/unit/volume/v3/fakes.py +2 -8
  203. openstackclient/tests/unit/volume/v3/test_block_storage_log_level.py +61 -71
  204. openstackclient/tests/unit/volume/v3/test_service.py +221 -141
  205. openstackclient/tests/unit/volume/v3/test_volume.py +131 -120
  206. openstackclient/tests/unit/volume/v3/test_volume_attachment.py +4 -4
  207. openstackclient/tests/unit/volume/v3/test_volume_backup.py +198 -203
  208. openstackclient/tests/unit/volume/v3/test_volume_snapshot.py +683 -49
  209. openstackclient/tests/unit/volume/v3/test_volume_transfer_request.py +1 -1
  210. openstackclient/volume/client.py +1 -3
  211. openstackclient/volume/v2/consistency_group.py +4 -8
  212. openstackclient/volume/v2/consistency_group_snapshot.py +1 -2
  213. openstackclient/volume/v2/qos_specs.py +1 -2
  214. openstackclient/volume/v2/service.py +41 -38
  215. openstackclient/volume/v2/volume.py +71 -53
  216. openstackclient/volume/v2/volume_backup.py +15 -10
  217. openstackclient/volume/v2/volume_snapshot.py +129 -93
  218. openstackclient/volume/v2/volume_transfer_request.py +0 -3
  219. openstackclient/volume/v2/volume_type.py +10 -21
  220. openstackclient/volume/v3/block_storage_cluster.py +3 -3
  221. openstackclient/volume/v3/block_storage_log_level.py +22 -28
  222. openstackclient/volume/v3/block_storage_manage.py +1 -3
  223. openstackclient/volume/v3/service.py +105 -14
  224. openstackclient/volume/v3/volume.py +218 -58
  225. openstackclient/volume/v3/volume_attachment.py +3 -2
  226. openstackclient/volume/v3/volume_backup.py +31 -27
  227. openstackclient/volume/v3/volume_group.py +2 -1
  228. openstackclient/volume/v3/volume_group_snapshot.py +2 -1
  229. openstackclient/volume/v3/volume_snapshot.py +489 -13
  230. openstackclient/volume/v3/volume_type.py +10 -21
  231. {python_openstackclient-7.4.0.dist-info → python_openstackclient-8.1.0.dist-info}/AUTHORS +11 -0
  232. python_openstackclient-8.1.0.dist-info/METADATA +264 -0
  233. {python_openstackclient-7.4.0.dist-info → python_openstackclient-8.1.0.dist-info}/RECORD +238 -259
  234. {python_openstackclient-7.4.0.dist-info → python_openstackclient-8.1.0.dist-info}/WHEEL +1 -1
  235. {python_openstackclient-7.4.0.dist-info → python_openstackclient-8.1.0.dist-info}/entry_points.txt +7 -47
  236. python_openstackclient-8.1.0.dist-info/pbr.json +1 -0
  237. openstackclient/tests/functional/volume/v1/__init__.py +0 -0
  238. openstackclient/tests/functional/volume/v1/common.py +0 -35
  239. openstackclient/tests/functional/volume/v1/test_qos.py +0 -100
  240. openstackclient/tests/functional/volume/v1/test_service.py +0 -76
  241. openstackclient/tests/functional/volume/v1/test_snapshot.py +0 -232
  242. openstackclient/tests/functional/volume/v1/test_transfer_request.py +0 -111
  243. openstackclient/tests/functional/volume/v1/test_volume.py +0 -228
  244. openstackclient/tests/functional/volume/v1/test_volume_type.py +0 -213
  245. openstackclient/tests/unit/volume/v1/__init__.py +0 -0
  246. openstackclient/tests/unit/volume/v1/fakes.py +0 -615
  247. openstackclient/tests/unit/volume/v1/test_qos_specs.py +0 -471
  248. openstackclient/tests/unit/volume/v1/test_service.py +0 -295
  249. openstackclient/tests/unit/volume/v1/test_transfer_request.py +0 -380
  250. openstackclient/tests/unit/volume/v1/test_type.py +0 -633
  251. openstackclient/tests/unit/volume/v1/test_volume.py +0 -1447
  252. openstackclient/tests/unit/volume/v1/test_volume_backup.py +0 -435
  253. openstackclient/volume/v1/__init__.py +0 -0
  254. openstackclient/volume/v1/qos_specs.py +0 -377
  255. openstackclient/volume/v1/service.py +0 -136
  256. openstackclient/volume/v1/volume.py +0 -734
  257. openstackclient/volume/v1/volume_backup.py +0 -302
  258. openstackclient/volume/v1/volume_snapshot.py +0 -433
  259. openstackclient/volume/v1/volume_transfer_request.py +0 -200
  260. openstackclient/volume/v1/volume_type.py +0 -520
  261. python_openstackclient-7.4.0.dist-info/METADATA +0 -172
  262. python_openstackclient-7.4.0.dist-info/pbr.json +0 -1
  263. {python_openstackclient-7.4.0.dist-info → python_openstackclient-8.1.0.dist-info}/LICENSE +0 -0
  264. {python_openstackclient-7.4.0.dist-info → python_openstackclient-8.1.0.dist-info}/top_level.txt +0 -0
@@ -15,6 +15,7 @@
15
15
 
16
16
  import copy
17
17
  import logging
18
+ import typing as ty
18
19
 
19
20
  from cliff import columns as cliff_columns
20
21
  from osc_lib.cli import format_columns
@@ -84,8 +85,8 @@ def _get_common_parse_arguments(parser, is_create=True):
84
85
  action=parseractions.MultiKeyValueAction,
85
86
  required_keys=['start', 'end'],
86
87
  help=_(
87
- "Allocation pool IP addresses for this subnet "
88
- "e.g.: start=192.168.199.2,end=192.168.199.254 "
88
+ "Allocation pool IP addresses for this subnet, "
89
+ "for example, start=192.168.199.2,end=192.168.199.254 "
89
90
  "(repeat option to add multiple IP addresses)"
90
91
  ),
91
92
  )
@@ -127,10 +128,10 @@ def _get_common_parse_arguments(parser, is_create=True):
127
128
  action=parseractions.MultiKeyValueAction,
128
129
  required_keys=['destination', 'gateway'],
129
130
  help=_(
130
- "Additional route for this subnet "
131
- "e.g.: destination=10.10.0.0/16,gateway=192.168.71.254 "
131
+ "Additional route for this subnet, "
132
+ "for example, destination=10.10.0.0/16,gateway=192.168.71.254 "
132
133
  "destination: destination subnet (in CIDR notation) "
133
- "gateway: nexthop IP address "
134
+ "gateway: next-hop IP address "
134
135
  "(repeat option to add multiple routes)"
135
136
  ),
136
137
  )
@@ -150,8 +151,8 @@ def _get_common_parse_arguments(parser, is_create=True):
150
151
  action='append',
151
152
  dest='service_types',
152
153
  help=_(
153
- "Service type for this subnet "
154
- "e.g.: network:floatingip_agent_gateway. "
154
+ "Service type for this subnet, "
155
+ "for example, network:floatingip_agent_gateway. "
155
156
  "Must be a valid device owner value for a network port "
156
157
  "(repeat option to set multiple service types)"
157
158
  ),
@@ -365,8 +366,8 @@ class CreateSubnet(command.ShowOne, common.NeutronCommandWithExtraArgs):
365
366
  "<ip-address>: Specific IP address to use as the gateway, "
366
367
  "'auto': Gateway address should automatically be chosen "
367
368
  "from within the subnet itself, 'none': This subnet will "
368
- "not use a gateway, e.g.: --gateway 192.168.9.1, "
369
- "--gateway auto, --gateway none (default is 'auto')."
369
+ "not use a gateway. For example, --gateway 192.168.9.1, "
370
+ "--gateway auto or --gateway none (default is 'auto')."
370
371
  ),
371
372
  )
372
373
  parser.add_argument(
@@ -375,7 +376,7 @@ class CreateSubnet(command.ShowOne, common.NeutronCommandWithExtraArgs):
375
376
  default=4,
376
377
  choices=[4, 6],
377
378
  help=_(
378
- "IP version (default is 4). Note that when subnet pool is "
379
+ "IP version (default is 4). Note that when subnet pool is "
379
380
  "specified, IP version is determined from the subnet pool "
380
381
  "and this option is ignored."
381
382
  ),
@@ -400,7 +401,7 @@ class CreateSubnet(command.ShowOne, common.NeutronCommandWithExtraArgs):
400
401
  '--network-segment',
401
402
  metavar='<network-segment>',
402
403
  help=_(
403
- "Network segment to associate with this subnet " "(name or ID)"
404
+ "Network segment to associate with this subnet (name or ID)"
404
405
  ),
405
406
  )
406
407
  parser.add_argument(
@@ -465,7 +466,7 @@ class DeleteSubnet(command.Command):
465
466
 
466
467
  if result > 0:
467
468
  total = len(parsed_args.subnet)
468
- msg = _("%(result)s of %(total)s subnets failed " "to delete.") % {
469
+ msg = _("%(result)s of %(total)s subnets failed to delete.") % {
469
470
  'result': result,
470
471
  'total': total,
471
472
  }
@@ -513,10 +514,10 @@ class ListSubnet(command.Lister):
513
514
  action='append',
514
515
  dest='service_types',
515
516
  help=_(
516
- "List only subnets of a given service type in output "
517
- "e.g.: network:floatingip_agent_gateway. "
517
+ "List only subnets of a given service type in output, "
518
+ "for example, network:floatingip_agent_gateway. "
518
519
  "Must be a valid device owner value for a network port "
519
- "(repeat option to list multiple service types)"
520
+ "(repeat option to list multiple service types)."
520
521
  ),
521
522
  )
522
523
  parser.add_argument(
@@ -551,8 +552,8 @@ class ListSubnet(command.Lister):
551
552
  metavar='<subnet-range>',
552
553
  help=_(
553
554
  "List only subnets of given subnet range "
554
- "(in CIDR notation) in output "
555
- "e.g.: --subnet-range 10.10.0.0/16"
555
+ "(in CIDR notation) in output. "
556
+ "For example, --subnet-range 10.10.0.0/16"
556
557
  ),
557
558
  )
558
559
  parser.add_argument(
@@ -560,7 +561,7 @@ class ListSubnet(command.Lister):
560
561
  metavar='<subnet-pool>',
561
562
  help=_(
562
563
  "List only subnets which belong to a given subnet pool "
563
- "in output (Name or ID)"
564
+ "in output (name or ID)"
564
565
  ),
565
566
  )
566
567
  _tag.add_tag_filtering_option_to_parser(parser, _('subnets'))
@@ -606,8 +607,8 @@ class ListSubnet(command.Lister):
606
607
  _tag.get_tag_filtering_args(parsed_args, filters)
607
608
  data = network_client.subnets(**filters)
608
609
 
609
- headers = ('ID', 'Name', 'Network', 'Subnet')
610
- columns = ('id', 'name', 'network_id', 'cidr')
610
+ headers: tuple[str, ...] = ('ID', 'Name', 'Network', 'Subnet')
611
+ columns: tuple[str, ...] = ('id', 'name', 'network_id', 'cidr')
611
612
  if parsed_args.long:
612
613
  headers += (
613
614
  'Project',
@@ -684,8 +685,8 @@ class SetSubnet(common.NeutronCommandWithExtraArgs):
684
685
  help=_(
685
686
  "Specify a gateway for the subnet. The options are: "
686
687
  "<ip-address>: Specific IP address to use as the gateway, "
687
- "'none': This subnet will not use a gateway, "
688
- "e.g.: --gateway 192.168.9.1, --gateway none."
688
+ "'none': This subnet will not use a gateway. "
689
+ "For example, --gateway 192.168.9.1 or --gateway none."
689
690
  ),
690
691
  )
691
692
  parser.add_argument(
@@ -694,7 +695,7 @@ class SetSubnet(common.NeutronCommandWithExtraArgs):
694
695
  help=_(
695
696
  "Network segment to associate with this subnet (name or "
696
697
  "ID). It is only allowed to set the segment if the current "
697
- "value is `None`, the network must also have only one "
698
+ "value is `None`. The network must also have only one "
698
699
  "segment and only one subnet can exist on the network."
699
700
  ),
700
701
  )
@@ -774,7 +775,7 @@ class UnsetSubnet(common.NeutronUnsetCommandWithExtraArgs):
774
775
  required_keys=['start', 'end'],
775
776
  help=_(
776
777
  'Allocation pool IP addresses to be removed from this '
777
- 'subnet e.g.: start=192.168.199.2,end=192.168.199.254 '
778
+ 'subnet, for example, start=192.168.199.2,end=192.168.199.254 '
778
779
  '(repeat option to unset multiple allocation pools)'
779
780
  ),
780
781
  )
@@ -800,10 +801,10 @@ class UnsetSubnet(common.NeutronUnsetCommandWithExtraArgs):
800
801
  action=parseractions.MultiKeyValueAction,
801
802
  required_keys=['destination', 'gateway'],
802
803
  help=_(
803
- 'Route to be removed from this subnet '
804
- 'e.g.: destination=10.10.0.0/16,gateway=192.168.71.254 '
804
+ 'Route to be removed from this subnet, '
805
+ 'for example, destination=10.10.0.0/16,gateway=192.168.71.254 '
805
806
  'destination: destination subnet (in CIDR notation) '
806
- 'gateway: nexthop IP address '
807
+ 'gateway: next-hop IP address '
807
808
  '(repeat option to unset multiple host routes)'
808
809
  ),
809
810
  )
@@ -813,8 +814,8 @@ class UnsetSubnet(common.NeutronUnsetCommandWithExtraArgs):
813
814
  action='append',
814
815
  dest='service_types',
815
816
  help=_(
816
- 'Service type to be removed from this subnet '
817
- 'e.g.: network:floatingip_agent_gateway. '
817
+ 'Service type to be removed from this subnet, '
818
+ 'for example, network:floatingip_agent_gateway. '
818
819
  'Must be a valid device owner value for a network port '
819
820
  '(repeat option to unset multiple service types)'
820
821
  ),
@@ -831,7 +832,7 @@ class UnsetSubnet(common.NeutronUnsetCommandWithExtraArgs):
831
832
  client = self.app.client_manager.network
832
833
  obj = client.find_subnet(parsed_args.subnet, ignore_missing=False)
833
834
 
834
- attrs = {}
835
+ attrs: dict[str, ty.Any] = {}
835
836
  if parsed_args.gateway:
836
837
  attrs['gateway_ip'] = None
837
838
  if parsed_args.dns_nameservers:
@@ -256,7 +256,7 @@ class DeleteSubnetPool(command.Command):
256
256
  if result > 0:
257
257
  total = len(parsed_args.subnet_pool)
258
258
  msg = _(
259
- "%(result)s of %(total)s subnet pools failed " "to delete."
259
+ "%(result)s of %(total)s subnet pools failed to delete."
260
260
  ) % {'result': result, 'total': total}
261
261
  raise exceptions.CommandError(msg)
262
262
 
@@ -290,7 +290,7 @@ class ListSubnetPool(command.Lister):
290
290
  '--default',
291
291
  action='store_true',
292
292
  help=_(
293
- "List subnet pools used as the default external " "subnet pool"
293
+ "List subnet pools used as the default external subnet pool"
294
294
  ),
295
295
  )
296
296
  default_group.add_argument(
@@ -356,8 +356,8 @@ class ListSubnetPool(command.Lister):
356
356
  _tag.get_tag_filtering_args(parsed_args, filters)
357
357
  data = network_client.subnet_pools(**filters)
358
358
 
359
- headers = ('ID', 'Name', 'Prefixes')
360
- columns = ('id', 'name', 'prefixes')
359
+ headers: tuple[str, ...] = ('ID', 'Name', 'Prefixes')
360
+ columns: tuple[str, ...] = ('id', 'name', 'prefixes')
361
361
  if parsed_args.long:
362
362
  headers += (
363
363
  'Default Prefix Length',
@@ -19,12 +19,11 @@ from osc_lib import utils
19
19
 
20
20
  from openstackclient.api import object_store_v1
21
21
 
22
+ # global variables used when building the shell
22
23
  DEFAULT_API_VERSION = '1'
23
24
  API_VERSION_OPTION = 'os_object_api_version'
24
25
  API_NAME = 'object_store'
25
- API_VERSIONS = {
26
- '1': 'openstackclient.object.client.ObjectClientv1',
27
- }
26
+ API_VERSIONS = ('1',)
28
27
 
29
28
 
30
29
  def make_client(instance):
@@ -148,10 +148,9 @@ class ListContainer(command.Lister):
148
148
  return parser
149
149
 
150
150
  def take_action(self, parsed_args):
151
+ columns: tuple[str, ...] = ('Name',)
151
152
  if parsed_args.long:
152
- columns = ('Name', 'Bytes', 'Count')
153
- else:
154
- columns = ('Name',)
153
+ columns += ('Bytes', 'Count')
155
154
 
156
155
  kwargs = {}
157
156
  if parsed_args.prefix:
@@ -162,16 +162,9 @@ class ListObject(command.Lister):
162
162
  return parser
163
163
 
164
164
  def take_action(self, parsed_args):
165
+ columns: tuple[str, ...] = ('Name',)
165
166
  if parsed_args.long:
166
- columns = (
167
- 'Name',
168
- 'Bytes',
169
- 'Hash',
170
- 'Content Type',
171
- 'Last Modified',
172
- )
173
- else:
174
- columns = ('Name',)
167
+ columns += ('Bytes', 'Hash', 'Content Type', 'Last Modified')
175
168
 
176
169
  kwargs = {}
177
170
  if parsed_args.prefix:
openstackclient/shell.py CHANGED
@@ -88,17 +88,34 @@ class OpenStackShell(shell.OpenStackShell):
88
88
  # this throws an exception if invalid
89
89
  skip_old_check = mod_check_api_version(version_opt)
90
90
 
91
+ # NOTE(stephenfin): API_VERSIONS has traditionally been a
92
+ # dictionary but the values are only used internally and are
93
+ # ignored for the modules using SDK. So we now support tuples
94
+ # instead.
91
95
  mod_versions = getattr(mod, 'API_VERSIONS', None)
92
- if not skip_old_check and mod_versions:
96
+ if mod_versions is not None and not isinstance(
97
+ mod_versions, dict | tuple
98
+ ):
99
+ raise TypeError(
100
+ f'Plugin {mod} has incompatible API_VERSIONS. '
101
+ f'Expected: tuple, dict. Got: {type(mod_versions)}. '
102
+ f'Please report this to your package maintainer.'
103
+ )
104
+
105
+ if mod_versions and not skip_old_check:
93
106
  if version_opt not in mod_versions:
94
107
  sorted_versions = sorted(
95
- mod.API_VERSIONS.keys(),
108
+ list(mod.API_VERSIONS),
96
109
  key=lambda s: list(map(int, s.split('.'))),
97
110
  )
98
111
  self.log.warning(
99
- "{} version {} is not in supported versions: {}".format(
100
- api, version_opt, ', '.join(sorted_versions)
101
- )
112
+ "%(name)s API version %(version)s is not in "
113
+ "supported versions: %(supported)s",
114
+ {
115
+ 'name': api,
116
+ 'version': version_opt,
117
+ 'supported': ', '.join(sorted_versions),
118
+ },
102
119
  )
103
120
 
104
121
  # Command groups deal only with major versions
@@ -36,8 +36,8 @@ def execute(cmd, *, fail_ok=False):
36
36
 
37
37
  proc = subprocess.Popen(cmdlist, stdout=stdout, stderr=stderr, env=env)
38
38
 
39
- result_out, result_err = proc.communicate()
40
- result_out = result_out.decode('utf-8')
39
+ result_out_b, result_err = proc.communicate()
40
+ result_out = result_out_b.decode('utf-8')
41
41
  LOG.debug('stdout: %s', result_out)
42
42
  LOG.debug('stderr: %s', result_err)
43
43
 
@@ -97,7 +97,11 @@ class TestCase(testtools.TestCase):
97
97
  )
98
98
 
99
99
  if parse_output:
100
- return json.loads(output)
100
+ try:
101
+ return json.loads(output)
102
+ except json.JSONDecodeError:
103
+ print(f'failed to decode: {output}')
104
+ raise
101
105
  else:
102
106
  return output
103
107
 
@@ -25,7 +25,7 @@ class QuotaTests(base.TestCase):
25
25
  test runs as these may run in parallel and otherwise step on each other.
26
26
  """
27
27
 
28
- PROJECT_NAME = None
28
+ PROJECT_NAME: str
29
29
 
30
30
  @classmethod
31
31
  def setUpClass(cls):
@@ -250,6 +250,8 @@ class QuotaTests(base.TestCase):
250
250
  row_headers = [str(r) for r in row.keys()]
251
251
  self.assertEqual(sorted(expected_headers), sorted(row_headers))
252
252
  resources.append(row['Resource'])
253
+ for header in expected_headers[1:]:
254
+ self.assertIsInstance(row[header], int)
253
255
  # Ensure that returned quota has network quota...
254
256
  self.assertIn("networks", resources)
255
257
  # ...and compute quota
@@ -22,9 +22,9 @@ from openstackclient.tests.functional import base
22
22
  class ComputeTestCase(base.TestCase):
23
23
  """Common functional test bits for Compute commands"""
24
24
 
25
- flavor_name = None
26
- image_name = None
27
- network_arg = None
25
+ flavor_name: str
26
+ image_name: str
27
+ network_arg: str
28
28
 
29
29
  def setUp(self):
30
30
  """Select common resources"""
@@ -34,7 +34,7 @@ class ComputeTestCase(base.TestCase):
34
34
  self.network_arg = self.get_network()
35
35
 
36
36
  @classmethod
37
- def get_flavor(cls):
37
+ def get_flavor(cls) -> str:
38
38
  # NOTE(rtheis): Get cirros256 or m1.tiny flavors since functional
39
39
  # tests may create other flavors.
40
40
  flavors = cls.openstack("flavor list", parse_output=True)
@@ -43,10 +43,13 @@ class ComputeTestCase(base.TestCase):
43
43
  if flavor['Name'] in ['m1.tiny', 'cirros256']:
44
44
  server_flavor = flavor['Name']
45
45
  break
46
+
47
+ assert server_flavor is not None
48
+
46
49
  return server_flavor
47
50
 
48
51
  @classmethod
49
- def get_image(cls):
52
+ def get_image(cls) -> str:
50
53
  # NOTE(rtheis): Get first Cirros image since functional tests may
51
54
  # create other images. Image may be named '-uec' or
52
55
  # '-disk'.
@@ -59,10 +62,13 @@ class ComputeTestCase(base.TestCase):
59
62
  ):
60
63
  server_image = image['Name']
61
64
  break
65
+
66
+ assert server_image is not None
67
+
62
68
  return server_image
63
69
 
64
70
  @classmethod
65
- def get_network(cls):
71
+ def get_network(cls) -> str:
66
72
  try:
67
73
  # NOTE(rtheis): Get private network since functional tests may
68
74
  # create other networks.
@@ -21,12 +21,18 @@ from openstackclient.tests.functional import base
21
21
  class KeypairBase(base.TestCase):
22
22
  """Methods for functional tests."""
23
23
 
24
- def keypair_create(self, name=data_utils.rand_uuid()):
24
+ def keypair_create(self, name=data_utils.rand_uuid(), user=None):
25
25
  """Create keypair and add cleanup."""
26
- raw_output = self.openstack('keypair create ' + name)
27
- self.addCleanup(self.keypair_delete, name, True)
26
+ cmd = 'keypair create ' + name
27
+ if user is not None:
28
+ cmd += ' --user ' + user
29
+ raw_output = self.openstack(cmd)
30
+ self.addCleanup(
31
+ self.keypair_delete, name, ignore_exceptions=True, user=user
32
+ )
28
33
  if not raw_output:
29
34
  self.fail('Keypair has not been created!')
35
+ return name
30
36
 
31
37
  def keypair_list(self, params=''):
32
38
  """Return dictionary with list of keypairs."""
@@ -34,10 +40,13 @@ class KeypairBase(base.TestCase):
34
40
  keypairs = self.parse_show_as_object(raw_output)
35
41
  return keypairs
36
42
 
37
- def keypair_delete(self, name, ignore_exceptions=False):
43
+ def keypair_delete(self, name, ignore_exceptions=False, user=None):
38
44
  """Try to delete keypair by name."""
39
45
  try:
40
- self.openstack('keypair delete ' + name)
46
+ cmd = 'keypair delete ' + name
47
+ if user is not None:
48
+ cmd += ' --user ' + user
49
+ self.openstack(cmd)
41
50
  except exceptions.CommandFailed:
42
51
  if not ignore_exceptions:
43
52
  raise
@@ -200,3 +209,30 @@ class KeypairTests(KeypairBase):
200
209
  items = self.parse_listing(raw_output)
201
210
  self.assert_table_structure(items, HEADERS)
202
211
  self.assertInOutput(self.KPName, raw_output)
212
+
213
+ def test_keypair_list_by_project(self):
214
+ """Test keypair list by project.
215
+
216
+ Test steps:
217
+ 1) Create keypair for admin project in setUp
218
+ 2) Create a new project
219
+ 3) Create a new user
220
+ 4) Associate the new user with the new project
221
+ 5) Create keypair for the new user
222
+ 6) List keypairs by the new project
223
+ 7) Check that only the keypair from step 5 is returned
224
+ """
225
+ project_name = data_utils.rand_name('TestProject')
226
+ self.openstack(f'project create {project_name}')
227
+ self.addCleanup(self.openstack, f'project delete {project_name}')
228
+ user_name = data_utils.rand_name('TestUser')
229
+ self.openstack(f'user create {user_name}')
230
+ self.addCleanup(self.openstack, f'user delete {user_name}')
231
+ self.openstack(
232
+ f'role add --user {user_name} --project {project_name} member'
233
+ )
234
+ keypair_name = self.keypair_create(user=user_name)
235
+ raw_output = self.openstack(f'keypair list --project {project_name}')
236
+ items = self.parse_listing(raw_output)
237
+ self.assertEqual(1, len(items))
238
+ self.assertEqual(keypair_name, items[0]['Name'])
@@ -156,7 +156,7 @@ class ServerTests(common.ComputeTestCase):
156
156
  server_name3 = cmd_output['name']
157
157
 
158
158
  cmd_output = self.openstack(
159
- 'server list ' '--changes-since ' + updated_at2,
159
+ 'server list --changes-since ' + updated_at2,
160
160
  parse_output=True,
161
161
  )
162
162
 
@@ -852,8 +852,7 @@ class ServerTests(common.ComputeTestCase):
852
852
  # it to the server at /dev/vdb and delete the volume when the
853
853
  # server is deleted.
854
854
  bdm_arg = (
855
- f'--block-device-mapping '
856
- f'vdb={self.image_name}:image:1:true '
855
+ f'--block-device-mapping vdb={self.image_name}:image:1:true '
857
856
  )
858
857
  else:
859
858
  # get image ID
@@ -93,7 +93,7 @@ class ServerEventTests(common.ComputeTestCase):
93
93
  # And verify we can get the event list after it's deleted
94
94
  # Test 'server event list' for deleting
95
95
  cmd_output = self.openstack(
96
- '--os-compute-api-version 2.21 ' 'server event list ' + server_id,
96
+ '--os-compute-api-version 2.21 server event list ' + server_id,
97
97
  parse_output=True,
98
98
  )
99
99
  request_id = None
@@ -37,7 +37,7 @@ class UserTests(common.IdentityTests):
37
37
  new_username = data_utils.rand_name('NewTestUser')
38
38
  new_email = data_utils.rand_name() + '@example.com'
39
39
  raw_output = self.openstack(
40
- 'user set ' '--email {email} ' '--name {new_name} ' '{id}'.format(
40
+ 'user set --email {email} --name {new_name} {id}'.format(
41
41
  email=new_email, new_name=new_username, id=user['id']
42
42
  )
43
43
  )
@@ -187,8 +187,7 @@ class IdentityTests(base.TestCase):
187
187
  f'domain set --disable {cls.domain_name}'
188
188
  )
189
189
  cls.openstack(
190
- '--os-identity-api-version 3 '
191
- f'domain delete {cls.domain_name}'
190
+ f'--os-identity-api-version 3 domain delete {cls.domain_name}'
192
191
  )
193
192
  finally:
194
193
  super().tearDownClass()
@@ -270,9 +269,7 @@ class IdentityTests(base.TestCase):
270
269
  if add_clean_up:
271
270
  self.addCleanup(
272
271
  self.openstack,
273
- 'group delete '
274
- f'--domain {self.domain_name} '
275
- f'{group_name}',
272
+ f'group delete --domain {self.domain_name} {group_name}',
276
273
  )
277
274
  items = self.parse_show(raw_output)
278
275
  self.assert_show_fields(items, self.GROUP_FIELDS)
@@ -305,9 +302,7 @@ class IdentityTests(base.TestCase):
305
302
  if add_clean_up:
306
303
  self.addCleanup(
307
304
  self.openstack,
308
- 'project delete '
309
- f'--domain {self.domain_name} '
310
- f'{project_name}',
305
+ f'project delete --domain {self.domain_name} {project_name}',
311
306
  )
312
307
  return project_name
313
308
 
@@ -50,35 +50,35 @@ class ApplicationCredentialTests(common.IdentityTests):
50
50
  def _create_role_assignments(self):
51
51
  try:
52
52
  user = self.openstack(
53
- 'configuration show -f value' ' -c auth.username'
53
+ 'configuration show -f value -c auth.username'
54
54
  )
55
55
  except Exception:
56
56
  user = self.openstack(
57
- 'configuration show -f value' ' -c auth.user_id'
57
+ 'configuration show -f value -c auth.user_id'
58
58
  )
59
59
  try:
60
60
  user_domain = self.openstack(
61
- 'configuration show -f value' ' -c auth.user_domain_name'
61
+ 'configuration show -f value -c auth.user_domain_name'
62
62
  )
63
63
  except Exception:
64
64
  user_domain = self.openstack(
65
- 'configuration show -f value' ' -c auth.user_domain_id'
65
+ 'configuration show -f value -c auth.user_domain_id'
66
66
  )
67
67
  try:
68
68
  project = self.openstack(
69
- 'configuration show -f value' ' -c auth.project_name'
69
+ 'configuration show -f value -c auth.project_name'
70
70
  )
71
71
  except Exception:
72
72
  project = self.openstack(
73
- 'configuration show -f value' ' -c auth.project_id'
73
+ 'configuration show -f value -c auth.project_id'
74
74
  )
75
75
  try:
76
76
  project_domain = self.openstack(
77
- 'configuration show -f value' ' -c auth.project_domain_name'
77
+ 'configuration show -f value -c auth.project_domain_name'
78
78
  )
79
79
  except Exception:
80
80
  project_domain = self.openstack(
81
- 'configuration show -f value' ' -c auth.project_domain_id'
81
+ 'configuration show -f value -c auth.project_domain_id'
82
82
  )
83
83
  role1 = self._create_dummy_role()
84
84
  role2 = self._create_dummy_role()
@@ -130,7 +130,7 @@ class ApplicationCredentialTests(common.IdentityTests):
130
130
  def test_application_credential_delete(self):
131
131
  name = data_utils.rand_name('name')
132
132
  self.openstack(f'application credential create {name}')
133
- raw_output = self.openstack('application credential delete ' f'{name}')
133
+ raw_output = self.openstack(f'application credential delete {name}')
134
134
  self.assertEqual(0, len(raw_output))
135
135
 
136
136
  def test_application_credential_list(self):
@@ -147,6 +147,6 @@ class ApplicationCredentialTests(common.IdentityTests):
147
147
  self.openstack,
148
148
  f'application credential delete {name}',
149
149
  )
150
- raw_output = self.openstack('application credential show ' f'{name}')
150
+ raw_output = self.openstack(f'application credential show {name}')
151
151
  items = self.parse_show(raw_output)
152
152
  self.assert_show_fields(items, self.APPLICATION_CREDENTIAL_FIELDS)
@@ -45,7 +45,7 @@ class EndpointTests(common.IdentityTests):
45
45
  endpoint_id = self._create_dummy_endpoint(add_clean_up=False)
46
46
  project_id = self._create_dummy_project(add_clean_up=False)
47
47
  raw_output = self.openstack(
48
- 'endpoint add project ' f'{endpoint_id} ' f'{project_id}'
48
+ f'endpoint add project {endpoint_id} {project_id}'
49
49
  )
50
50
  self.assertEqual(0, len(raw_output))
51
51
  raw_output = self.openstack(f'endpoint list --endpoint {endpoint_id}')
@@ -89,11 +89,11 @@ class EndpointTests(common.IdentityTests):
89
89
  endpoint_id = self._create_dummy_endpoint(add_clean_up=False)
90
90
  project_id = self._create_dummy_project(add_clean_up=False)
91
91
  raw_output = self.openstack(
92
- 'endpoint add project ' f'{endpoint_id} ' f'{project_id}'
92
+ f'endpoint add project {endpoint_id} {project_id}'
93
93
  )
94
94
  self.assertEqual(0, len(raw_output))
95
95
 
96
96
  raw_output = self.openstack(
97
- 'endpoint remove project ' f'{endpoint_id} ' f'{project_id}'
97
+ f'endpoint remove project {endpoint_id} {project_id}'
98
98
  )
99
99
  self.assertEqual(0, len(raw_output))
@@ -36,14 +36,14 @@ class GroupTests(common.IdentityTests):
36
36
  def test_group_delete(self):
37
37
  group_name = self._create_dummy_group(add_clean_up=False)
38
38
  raw_output = self.openstack(
39
- 'group delete ' f'--domain {self.domain_name} ' f'{group_name}'
39
+ f'group delete --domain {self.domain_name} {group_name}'
40
40
  )
41
41
  self.assertEqual(0, len(raw_output))
42
42
 
43
43
  def test_group_show(self):
44
44
  group_name = self._create_dummy_group()
45
45
  raw_output = self.openstack(
46
- 'group show ' f'--domain {self.domain_name} ' f'{group_name}'
46
+ f'group show --domain {self.domain_name} {group_name}'
47
47
  )
48
48
  items = self.parse_show(raw_output)
49
49
  self.assert_show_fields(items, self.GROUP_FIELDS)
@@ -59,7 +59,7 @@ class GroupTests(common.IdentityTests):
59
59
  )
60
60
  self.assertEqual(0, len(raw_output))
61
61
  raw_output = self.openstack(
62
- 'group show ' f'--domain {self.domain_name} ' f'{new_group_name}'
62
+ f'group show --domain {self.domain_name} {new_group_name}'
63
63
  )
64
64
  group = self.parse_show_as_object(raw_output)
65
65
  self.assertEqual(new_group_name, group['name'])