python-openstackclient 8.1.0__py3-none-any.whl → 8.3.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.
- openstackclient/api/compute_v2.py +2 -2
- openstackclient/api/object_store_v1.py +4 -1
- openstackclient/api/volume_v2.py +60 -0
- openstackclient/api/volume_v3.py +60 -0
- openstackclient/command.py +27 -0
- openstackclient/common/availability_zone.py +1 -1
- openstackclient/common/clientmanager.py +59 -21
- openstackclient/common/configuration.py +1 -1
- openstackclient/common/extension.py +1 -1
- openstackclient/common/limits.py +1 -1
- openstackclient/common/module.py +4 -2
- openstackclient/common/project_cleanup.py +10 -8
- openstackclient/common/quota.py +23 -6
- openstackclient/common/versions.py +1 -2
- openstackclient/compute/v2/agent.py +1 -1
- openstackclient/compute/v2/aggregate.py +6 -5
- openstackclient/compute/v2/console.py +5 -3
- openstackclient/compute/v2/console_connection.py +1 -1
- openstackclient/compute/v2/flavor.py +15 -2
- openstackclient/compute/v2/host.py +1 -1
- openstackclient/compute/v2/hypervisor.py +1 -1
- openstackclient/compute/v2/hypervisor_stats.py +1 -1
- openstackclient/compute/v2/keypair.py +1 -1
- openstackclient/compute/v2/server.py +77 -30
- openstackclient/compute/v2/server_backup.py +1 -1
- openstackclient/compute/v2/server_event.py +1 -1
- openstackclient/compute/v2/server_group.py +4 -2
- openstackclient/compute/v2/server_image.py +1 -1
- openstackclient/compute/v2/server_migration.py +1 -1
- openstackclient/compute/v2/server_volume.py +1 -1
- openstackclient/compute/v2/service.py +1 -1
- openstackclient/compute/v2/usage.py +6 -4
- openstackclient/identity/common.py +10 -14
- openstackclient/identity/v2_0/catalog.py +3 -2
- openstackclient/identity/v2_0/ec2creds.py +1 -1
- openstackclient/identity/v2_0/endpoint.py +1 -1
- openstackclient/identity/v2_0/project.py +17 -7
- openstackclient/identity/v2_0/role.py +1 -1
- openstackclient/identity/v2_0/role_assignment.py +3 -3
- openstackclient/identity/v2_0/service.py +1 -1
- openstackclient/identity/v2_0/token.py +1 -1
- openstackclient/identity/v2_0/user.py +2 -2
- openstackclient/identity/v3/access_rule.py +16 -4
- openstackclient/identity/v3/application_credential.py +116 -95
- openstackclient/identity/v3/catalog.py +3 -3
- openstackclient/identity/v3/consumer.py +1 -1
- openstackclient/identity/v3/credential.py +1 -1
- openstackclient/identity/v3/domain.py +15 -10
- openstackclient/identity/v3/ec2creds.py +1 -1
- openstackclient/identity/v3/endpoint.py +33 -12
- openstackclient/identity/v3/endpoint_group.py +1 -1
- openstackclient/identity/v3/federation_protocol.py +1 -1
- openstackclient/identity/v3/group.py +11 -5
- openstackclient/identity/v3/identity_provider.py +12 -10
- openstackclient/identity/v3/implied_role.py +1 -1
- openstackclient/identity/v3/limit.py +1 -1
- openstackclient/identity/v3/mapping.py +1 -1
- openstackclient/identity/v3/policy.py +1 -1
- openstackclient/identity/v3/project.py +34 -22
- openstackclient/identity/v3/region.py +1 -1
- openstackclient/identity/v3/registered_limit.py +16 -11
- openstackclient/identity/v3/role.py +27 -41
- openstackclient/identity/v3/role_assignment.py +12 -23
- openstackclient/identity/v3/service.py +1 -1
- openstackclient/identity/v3/service_provider.py +1 -1
- openstackclient/identity/v3/tag.py +3 -2
- openstackclient/identity/v3/token.py +3 -2
- openstackclient/identity/v3/trust.py +4 -2
- openstackclient/identity/v3/unscoped_saml.py +1 -1
- openstackclient/identity/v3/user.py +22 -13
- openstackclient/image/v1/image.py +35 -17
- openstackclient/image/v2/cache.py +11 -7
- openstackclient/image/v2/image.py +62 -12
- openstackclient/image/v2/info.py +1 -1
- openstackclient/image/v2/metadef_namespaces.py +1 -1
- openstackclient/image/v2/metadef_objects.py +9 -3
- openstackclient/image/v2/metadef_properties.py +11 -3
- openstackclient/image/v2/metadef_resource_type_association.py +1 -1
- openstackclient/image/v2/metadef_resource_types.py +1 -1
- openstackclient/image/v2/task.py +1 -1
- openstackclient/network/common.py +10 -9
- openstackclient/network/v2/address_group.py +4 -3
- openstackclient/network/v2/address_scope.py +8 -6
- openstackclient/network/v2/default_security_group_rule.py +9 -8
- openstackclient/network/v2/floating_ip.py +16 -9
- openstackclient/network/v2/floating_ip_port_forwarding.py +9 -6
- openstackclient/network/v2/ip_availability.py +7 -4
- openstackclient/network/v2/l3_conntrack_helper.py +11 -4
- openstackclient/network/v2/local_ip.py +13 -7
- openstackclient/network/v2/local_ip_association.py +7 -4
- openstackclient/network/v2/ndp_proxy.py +13 -6
- openstackclient/network/v2/network.py +33 -16
- openstackclient/network/v2/network_agent.py +5 -5
- openstackclient/network/v2/network_auto_allocated_topology.py +1 -1
- openstackclient/network/v2/network_flavor.py +1 -1
- openstackclient/network/v2/network_flavor_profile.py +1 -1
- openstackclient/network/v2/network_meter.py +1 -1
- openstackclient/network/v2/network_meter_rule.py +1 -1
- openstackclient/network/v2/network_qos_policy.py +7 -5
- openstackclient/network/v2/network_qos_rule.py +1 -1
- openstackclient/network/v2/network_qos_rule_type.py +1 -1
- openstackclient/network/v2/network_rbac.py +8 -5
- openstackclient/network/v2/network_segment.py +2 -2
- openstackclient/network/v2/network_segment_range.py +13 -6
- openstackclient/network/v2/network_service_provider.py +1 -1
- openstackclient/network/v2/network_trunk.py +65 -42
- openstackclient/network/v2/port.py +38 -20
- openstackclient/network/v2/router.py +19 -8
- openstackclient/network/v2/security_group.py +52 -7
- openstackclient/network/v2/security_group_rule.py +27 -4
- openstackclient/network/v2/subnet.py +17 -18
- openstackclient/network/v2/subnet_pool.py +11 -9
- openstackclient/network/v2/taas/__init__.py +0 -0
- openstackclient/network/v2/taas/tap_flow.py +245 -0
- openstackclient/network/v2/taas/tap_mirror.py +237 -0
- openstackclient/network/v2/taas/tap_service.py +211 -0
- openstackclient/object/v1/account.py +1 -1
- openstackclient/object/v1/container.py +1 -1
- openstackclient/object/v1/object.py +1 -1
- openstackclient/shell.py +18 -8
- openstackclient/tests/functional/identity/v3/test_access_rule.py +1 -1
- openstackclient/tests/functional/identity/v3/test_application_credential.py +7 -7
- openstackclient/tests/functional/identity/v3/test_catalog.py +42 -23
- openstackclient/tests/functional/identity/v3/test_role_assignment.py +174 -0
- openstackclient/tests/functional/image/v2/test_cache.py +54 -0
- openstackclient/tests/functional/image/v2/test_image.py +36 -14
- openstackclient/tests/functional/image/v2/test_metadef_resource_type.py +55 -0
- openstackclient/tests/functional/volume/v2/test_volume.py +1 -1
- openstackclient/tests/functional/volume/v3/test_volume.py +2 -2
- openstackclient/tests/unit/api/test_volume_v2.py +124 -0
- openstackclient/tests/unit/api/test_volume_v3.py +124 -0
- openstackclient/tests/unit/common/test_command.py +1 -1
- openstackclient/tests/unit/common/test_extension.py +2 -3
- openstackclient/tests/unit/common/test_module.py +14 -7
- openstackclient/tests/unit/common/test_quota.py +20 -0
- openstackclient/tests/unit/compute/v2/test_aggregate.py +5 -3
- openstackclient/tests/unit/compute/v2/test_console.py +1 -4
- openstackclient/tests/unit/compute/v2/test_flavor.py +160 -177
- openstackclient/tests/unit/compute/v2/test_hypervisor_stats.py +1 -9
- openstackclient/tests/unit/compute/v2/test_server.py +406 -81
- openstackclient/tests/unit/compute/v2/test_server_backup.py +1 -3
- openstackclient/tests/unit/compute/v2/test_service.py +1 -3
- openstackclient/tests/unit/fakes.py +35 -134
- openstackclient/tests/unit/identity/test_common.py +100 -0
- openstackclient/tests/unit/identity/v2_0/test_project.py +4 -4
- openstackclient/tests/unit/identity/v3/fakes.py +10 -2
- openstackclient/tests/unit/identity/v3/test_application_credential.py +50 -44
- openstackclient/tests/unit/identity/v3/test_domain.py +3 -3
- openstackclient/tests/unit/identity/v3/test_endpoint.py +1 -1
- openstackclient/tests/unit/identity/v3/test_group.py +4 -2
- openstackclient/tests/unit/identity/v3/test_identity_provider.py +10 -10
- openstackclient/tests/unit/identity/v3/test_oauth.py +1 -1
- openstackclient/tests/unit/identity/v3/test_project.py +31 -54
- openstackclient/tests/unit/identity/v3/test_registered_limit.py +2 -2
- openstackclient/tests/unit/identity/v3/test_role.py +3 -90
- openstackclient/tests/unit/identity/v3/test_user.py +7 -51
- openstackclient/tests/unit/image/v1/test_image.py +47 -0
- openstackclient/tests/unit/image/v2/test_image.py +190 -9
- openstackclient/tests/unit/image/v2/test_metadef_objects.py +22 -0
- openstackclient/tests/unit/image/v2/test_metadef_properties.py +24 -10
- openstackclient/tests/unit/network/test_common.py +9 -13
- openstackclient/tests/unit/network/v2/fakes.py +1 -0
- openstackclient/tests/unit/network/v2/taas/__init__.py +0 -0
- openstackclient/tests/unit/network/v2/taas/test_osc_tap_flow.py +276 -0
- openstackclient/tests/unit/network/v2/taas/test_osc_tap_mirror.py +288 -0
- openstackclient/tests/unit/network/v2/taas/test_osc_tap_service.py +271 -0
- openstackclient/tests/unit/network/v2/test_address_group.py +19 -22
- openstackclient/tests/unit/network/v2/test_address_scope.py +10 -15
- openstackclient/tests/unit/network/v2/test_default_security_group_rule.py +38 -49
- openstackclient/tests/unit/network/v2/test_floating_ip_network.py +21 -27
- openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py +21 -18
- openstackclient/tests/unit/network/v2/test_ip_availability.py +6 -8
- openstackclient/tests/unit/network/v2/test_l3_conntrack_helper.py +6 -15
- openstackclient/tests/unit/network/v2/test_local_ip.py +12 -23
- openstackclient/tests/unit/network/v2/test_local_ip_association.py +13 -18
- openstackclient/tests/unit/network/v2/test_ndp_proxy.py +13 -23
- openstackclient/tests/unit/network/v2/test_network.py +41 -37
- openstackclient/tests/unit/network/v2/test_network_agent.py +13 -20
- openstackclient/tests/unit/network/v2/test_network_auto_allocated_topology.py +5 -8
- openstackclient/tests/unit/network/v2/test_network_flavor.py +14 -26
- openstackclient/tests/unit/network/v2/test_network_flavor_profile.py +14 -17
- openstackclient/tests/unit/network/v2/test_network_meter.py +7 -17
- openstackclient/tests/unit/network/v2/test_network_meter_rule.py +10 -20
- openstackclient/tests/unit/network/v2/test_network_qos_policy.py +7 -13
- openstackclient/tests/unit/network/v2/test_network_qos_rule.py +44 -54
- openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py +2 -7
- openstackclient/tests/unit/network/v2/test_network_rbac.py +21 -36
- openstackclient/tests/unit/network/v2/test_network_segment.py +13 -29
- openstackclient/tests/unit/network/v2/test_network_segment_range.py +20 -19
- openstackclient/tests/unit/network/v2/test_network_service_provider.py +1 -4
- openstackclient/tests/unit/network/v2/test_network_trunk.py +52 -47
- openstackclient/tests/unit/network/v2/test_port.py +113 -84
- openstackclient/tests/unit/network/v2/test_router.py +104 -126
- openstackclient/tests/unit/network/v2/test_security_group_network.py +25 -26
- openstackclient/tests/unit/network/v2/test_security_group_rule_network.py +66 -18
- openstackclient/tests/unit/network/v2/test_subnet.py +35 -46
- openstackclient/tests/unit/network/v2/test_subnet_pool.py +21 -33
- openstackclient/tests/unit/volume/test_find_resource.py +4 -13
- openstackclient/tests/unit/volume/v2/test_volume.py +358 -305
- openstackclient/tests/unit/volume/v2/test_volume_backup.py +3 -1
- openstackclient/tests/unit/volume/v3/test_volume.py +443 -415
- openstackclient/tests/unit/volume/v3/test_volume_backup.py +9 -0
- openstackclient/volume/client.py +7 -17
- openstackclient/volume/v2/backup_record.py +1 -1
- openstackclient/volume/v2/consistency_group.py +1 -1
- openstackclient/volume/v2/consistency_group_snapshot.py +1 -1
- openstackclient/volume/v2/qos_specs.py +1 -1
- openstackclient/volume/v2/service.py +2 -2
- openstackclient/volume/v2/volume.py +80 -54
- openstackclient/volume/v2/volume_backend.py +1 -1
- openstackclient/volume/v2/volume_backup.py +5 -3
- openstackclient/volume/v2/volume_host.py +1 -2
- openstackclient/volume/v2/volume_snapshot.py +2 -2
- openstackclient/volume/v2/volume_transfer_request.py +1 -1
- openstackclient/volume/v2/volume_type.py +11 -6
- openstackclient/volume/v3/block_storage_cleanup.py +1 -1
- openstackclient/volume/v3/block_storage_cluster.py +1 -1
- openstackclient/volume/v3/block_storage_log_level.py +1 -1
- openstackclient/volume/v3/block_storage_manage.py +1 -1
- openstackclient/volume/v3/block_storage_resource_filter.py +1 -1
- openstackclient/volume/v3/service.py +2 -2
- openstackclient/volume/v3/volume.py +104 -77
- openstackclient/volume/v3/volume_attachment.py +6 -5
- openstackclient/volume/v3/volume_backup.py +18 -3
- openstackclient/volume/v3/volume_group.py +2 -2
- openstackclient/volume/v3/volume_group_snapshot.py +1 -1
- openstackclient/volume/v3/volume_group_type.py +1 -1
- openstackclient/volume/v3/volume_message.py +1 -1
- openstackclient/volume/v3/volume_snapshot.py +2 -2
- openstackclient/volume/v3/volume_transfer_request.py +1 -1
- openstackclient/volume/v3/volume_type.py +15 -9
- {python_openstackclient-8.1.0.dist-info → python_openstackclient-8.3.0.dist-info}/METADATA +19 -17
- {python_openstackclient-8.1.0.dist-info → python_openstackclient-8.3.0.dist-info}/RECORD +239 -224
- {python_openstackclient-8.1.0.dist-info → python_openstackclient-8.3.0.dist-info}/WHEEL +1 -1
- {python_openstackclient-8.1.0.dist-info → python_openstackclient-8.3.0.dist-info}/entry_points.txt +15 -0
- {python_openstackclient-8.1.0.dist-info → python_openstackclient-8.3.0.dist-info/licenses}/AUTHORS +15 -0
- python_openstackclient-8.3.0.dist-info/pbr.json +1 -0
- openstackclient/tests/unit/common/test_logs.py +0 -221
- python_openstackclient-8.1.0.dist-info/pbr.json +0 -1
- {python_openstackclient-8.1.0.dist-info → python_openstackclient-8.3.0.dist-info/licenses}/LICENSE +0 -0
- {python_openstackclient-8.1.0.dist-info → python_openstackclient-8.3.0.dist-info}/top_level.txt +0 -0
|
@@ -16,10 +16,10 @@
|
|
|
16
16
|
import logging
|
|
17
17
|
|
|
18
18
|
from osc_lib.cli import format_columns
|
|
19
|
-
from osc_lib.command import command
|
|
20
19
|
from osc_lib import exceptions
|
|
21
20
|
from osc_lib import utils
|
|
22
21
|
|
|
22
|
+
from openstackclient import command
|
|
23
23
|
from openstackclient.i18n import _
|
|
24
24
|
from openstackclient.identity import common
|
|
25
25
|
|
|
@@ -41,6 +41,7 @@ class CreateIdentityProvider(command.ShowOne):
|
|
|
41
41
|
identity_remote_id_provider.add_argument(
|
|
42
42
|
'--remote-id',
|
|
43
43
|
metavar='<remote-id>',
|
|
44
|
+
dest='remote_ids',
|
|
44
45
|
action='append',
|
|
45
46
|
help=_(
|
|
46
47
|
'Remote IDs to associate with the Identity Provider '
|
|
@@ -99,16 +100,15 @@ class CreateIdentityProvider(command.ShowOne):
|
|
|
99
100
|
|
|
100
101
|
def take_action(self, parsed_args):
|
|
101
102
|
identity_client = self.app.client_manager.identity
|
|
103
|
+
remote_ids: list[str] | None = None
|
|
102
104
|
if parsed_args.remote_id_file:
|
|
103
105
|
file_content = utils.read_blob_file_contents(
|
|
104
106
|
parsed_args.remote_id_file
|
|
105
107
|
)
|
|
106
108
|
remote_ids = file_content.splitlines()
|
|
107
109
|
remote_ids = list(map(str.strip, remote_ids))
|
|
108
|
-
|
|
109
|
-
remote_ids =
|
|
110
|
-
parsed_args.remote_id if parsed_args.remote_id else None
|
|
111
|
-
)
|
|
110
|
+
elif parsed_args.remote_ids:
|
|
111
|
+
remote_ids = parsed_args.remote_ids
|
|
112
112
|
|
|
113
113
|
domain_id = None
|
|
114
114
|
if parsed_args.domain:
|
|
@@ -137,8 +137,9 @@ class CreateIdentityProvider(command.ShowOne):
|
|
|
137
137
|
)
|
|
138
138
|
|
|
139
139
|
idp._info.pop('links', None)
|
|
140
|
-
remote_ids = format_columns.ListColumn(
|
|
141
|
-
|
|
140
|
+
idp._info['remote_ids'] = format_columns.ListColumn(
|
|
141
|
+
idp._info.pop('remote_ids', [])
|
|
142
|
+
)
|
|
142
143
|
return zip(*sorted(idp._info.items()))
|
|
143
144
|
|
|
144
145
|
|
|
@@ -240,6 +241,7 @@ class SetIdentityProvider(command.Command):
|
|
|
240
241
|
identity_remote_id_provider.add_argument(
|
|
241
242
|
'--remote-id',
|
|
242
243
|
metavar='<remote-id>',
|
|
244
|
+
dest='remote_ids',
|
|
243
245
|
action='append',
|
|
244
246
|
help=_(
|
|
245
247
|
'Remote IDs to associate with the Identity Provider '
|
|
@@ -287,8 +289,8 @@ class SetIdentityProvider(command.Command):
|
|
|
287
289
|
)
|
|
288
290
|
remote_ids = file_content.splitlines()
|
|
289
291
|
remote_ids = list(map(str.strip, remote_ids))
|
|
290
|
-
elif parsed_args.
|
|
291
|
-
remote_ids = parsed_args.
|
|
292
|
+
elif parsed_args.remote_ids:
|
|
293
|
+
remote_ids = parsed_args.remote_ids
|
|
292
294
|
|
|
293
295
|
# Setup keyword args for the client
|
|
294
296
|
kwargs = {}
|
|
@@ -298,7 +300,7 @@ class SetIdentityProvider(command.Command):
|
|
|
298
300
|
kwargs['enabled'] = True
|
|
299
301
|
if parsed_args.disable:
|
|
300
302
|
kwargs['enabled'] = False
|
|
301
|
-
if parsed_args.remote_id_file or parsed_args.
|
|
303
|
+
if parsed_args.remote_id_file or parsed_args.remote_ids:
|
|
302
304
|
kwargs['remote_ids'] = remote_ids
|
|
303
305
|
|
|
304
306
|
# TODO(pas-ha) actually check for 3.14 microversion
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
|
|
16
16
|
import logging
|
|
17
17
|
|
|
18
|
-
from osc_lib.command import command
|
|
19
18
|
from osc_lib import exceptions
|
|
20
19
|
from osc_lib import utils
|
|
21
20
|
|
|
21
|
+
from openstackclient import command
|
|
22
22
|
from openstackclient.i18n import _
|
|
23
23
|
from openstackclient.identity import common as common_utils
|
|
24
24
|
|
|
@@ -19,10 +19,10 @@ import logging
|
|
|
19
19
|
|
|
20
20
|
from keystoneauth1 import exceptions as ks_exc
|
|
21
21
|
from osc_lib.cli import parseractions
|
|
22
|
-
from osc_lib.command import command
|
|
23
22
|
from osc_lib import exceptions
|
|
24
23
|
from osc_lib import utils
|
|
25
24
|
|
|
25
|
+
from openstackclient import command
|
|
26
26
|
from openstackclient.i18n import _
|
|
27
27
|
from openstackclient.identity import common
|
|
28
28
|
from openstackclient.identity.v3 import tag
|
|
@@ -59,16 +59,21 @@ class CreateProject(command.ShowOne):
|
|
|
59
59
|
enable_group.add_argument(
|
|
60
60
|
'--enable',
|
|
61
61
|
action='store_true',
|
|
62
|
+
dest='enabled',
|
|
63
|
+
default=True,
|
|
62
64
|
help=_('Enable project'),
|
|
63
65
|
)
|
|
64
66
|
enable_group.add_argument(
|
|
65
67
|
'--disable',
|
|
66
|
-
action='
|
|
68
|
+
action='store_false',
|
|
69
|
+
dest='enabled',
|
|
70
|
+
default=True,
|
|
67
71
|
help=_('Disable project'),
|
|
68
72
|
)
|
|
69
73
|
parser.add_argument(
|
|
70
74
|
'--property',
|
|
71
75
|
metavar='<key=value>',
|
|
76
|
+
dest='properties',
|
|
72
77
|
action=parseractions.KeyValueAction,
|
|
73
78
|
help=_(
|
|
74
79
|
'Add a property to <name> '
|
|
@@ -98,15 +103,9 @@ class CreateProject(command.ShowOne):
|
|
|
98
103
|
parsed_args.parent,
|
|
99
104
|
).id
|
|
100
105
|
|
|
101
|
-
enabled = True
|
|
102
|
-
if parsed_args.disable:
|
|
103
|
-
enabled = False
|
|
104
|
-
|
|
105
|
-
options = common.get_immutable_options(parsed_args)
|
|
106
|
-
|
|
107
106
|
kwargs = {}
|
|
108
|
-
if parsed_args.
|
|
109
|
-
kwargs = parsed_args.
|
|
107
|
+
if parsed_args.properties:
|
|
108
|
+
kwargs = parsed_args.properties.copy()
|
|
110
109
|
if 'is_domain' in kwargs.keys():
|
|
111
110
|
if kwargs['is_domain'].lower() == "true":
|
|
112
111
|
kwargs['is_domain'] = True
|
|
@@ -117,13 +116,17 @@ class CreateProject(command.ShowOne):
|
|
|
117
116
|
|
|
118
117
|
kwargs['tags'] = list(set(parsed_args.tags))
|
|
119
118
|
|
|
119
|
+
options = {}
|
|
120
|
+
if parsed_args.immutable is not None:
|
|
121
|
+
options['immutable'] = parsed_args.immutable
|
|
122
|
+
|
|
120
123
|
try:
|
|
121
124
|
project = identity_client.projects.create(
|
|
122
125
|
name=parsed_args.name,
|
|
123
126
|
domain=domain,
|
|
124
127
|
parent=parent,
|
|
125
128
|
description=parsed_args.description,
|
|
126
|
-
enabled=enabled,
|
|
129
|
+
enabled=parsed_args.enabled,
|
|
127
130
|
options=options,
|
|
128
131
|
**kwargs,
|
|
129
132
|
)
|
|
@@ -143,7 +146,14 @@ class CreateProject(command.ShowOne):
|
|
|
143
146
|
|
|
144
147
|
|
|
145
148
|
class DeleteProject(command.Command):
|
|
146
|
-
_description = _(
|
|
149
|
+
_description = _(
|
|
150
|
+
"Delete project(s). This command will remove specified "
|
|
151
|
+
"existing project(s) if an active user is authorized to do "
|
|
152
|
+
"this. If there are resources managed by other services "
|
|
153
|
+
"(for example, Nova, Neutron, Cinder) associated with "
|
|
154
|
+
"specified project(s), delete operation will proceed "
|
|
155
|
+
"regardless."
|
|
156
|
+
)
|
|
147
157
|
|
|
148
158
|
def get_parser(self, prog_name):
|
|
149
159
|
parser = super().get_parser(prog_name)
|
|
@@ -356,16 +366,21 @@ class SetProject(command.Command):
|
|
|
356
366
|
enable_group.add_argument(
|
|
357
367
|
'--enable',
|
|
358
368
|
action='store_true',
|
|
369
|
+
dest='enabled',
|
|
370
|
+
default=None,
|
|
359
371
|
help=_('Enable project'),
|
|
360
372
|
)
|
|
361
373
|
enable_group.add_argument(
|
|
362
374
|
'--disable',
|
|
363
|
-
action='
|
|
375
|
+
action='store_false',
|
|
376
|
+
dest='enabled',
|
|
377
|
+
default=None,
|
|
364
378
|
help=_('Disable project'),
|
|
365
379
|
)
|
|
366
380
|
parser.add_argument(
|
|
367
381
|
'--property',
|
|
368
382
|
metavar='<key=value>',
|
|
383
|
+
dest='properties',
|
|
369
384
|
action=parseractions.KeyValueAction,
|
|
370
385
|
help=_(
|
|
371
386
|
'Set a property on <project> '
|
|
@@ -388,15 +403,12 @@ class SetProject(command.Command):
|
|
|
388
403
|
kwargs['name'] = parsed_args.name
|
|
389
404
|
if parsed_args.description:
|
|
390
405
|
kwargs['description'] = parsed_args.description
|
|
391
|
-
if parsed_args.
|
|
392
|
-
kwargs['enabled'] =
|
|
393
|
-
if parsed_args.
|
|
394
|
-
kwargs['
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
kwargs['options'] = options
|
|
398
|
-
if parsed_args.property:
|
|
399
|
-
kwargs.update(parsed_args.property)
|
|
406
|
+
if parsed_args.enabled is not None:
|
|
407
|
+
kwargs['enabled'] = parsed_args.enabled
|
|
408
|
+
if parsed_args.immutable is not None:
|
|
409
|
+
kwargs['options'] = {'immutable': parsed_args.immutable}
|
|
410
|
+
if parsed_args.properties:
|
|
411
|
+
kwargs.update(parsed_args.properties)
|
|
400
412
|
tag.update_tags_in_args(parsed_args, project, kwargs)
|
|
401
413
|
|
|
402
414
|
identity_client.projects.update(project.id, **kwargs)
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
|
|
16
16
|
import logging
|
|
17
17
|
|
|
18
|
-
from osc_lib.command import command
|
|
19
18
|
from osc_lib import exceptions
|
|
20
19
|
from osc_lib import utils
|
|
21
20
|
|
|
21
|
+
from openstackclient import command
|
|
22
22
|
from openstackclient.i18n import _
|
|
23
23
|
from openstackclient.identity import common as common_utils
|
|
24
24
|
|
|
@@ -44,7 +44,10 @@ class CreateRegisteredLimit(command.ShowOne):
|
|
|
44
44
|
'--service',
|
|
45
45
|
metavar='<service>',
|
|
46
46
|
required=True,
|
|
47
|
-
help=_(
|
|
47
|
+
help=_(
|
|
48
|
+
'Service responsible for the resource to limit (required) '
|
|
49
|
+
'(name or ID)'
|
|
50
|
+
),
|
|
48
51
|
)
|
|
49
52
|
parser.add_argument(
|
|
50
53
|
'--default-limit',
|
|
@@ -106,10 +109,10 @@ class DeleteRegisteredLimit(command.Command):
|
|
|
106
109
|
def get_parser(self, prog_name):
|
|
107
110
|
parser = super().get_parser(prog_name)
|
|
108
111
|
parser.add_argument(
|
|
109
|
-
'
|
|
110
|
-
metavar='<registered-
|
|
112
|
+
'registered_limits',
|
|
113
|
+
metavar='<registered-limits>',
|
|
111
114
|
nargs="+",
|
|
112
|
-
help=_('Registered limit to delete (ID)'),
|
|
115
|
+
help=_('Registered limit(s) to delete (ID)'),
|
|
113
116
|
)
|
|
114
117
|
return parser
|
|
115
118
|
|
|
@@ -117,7 +120,7 @@ class DeleteRegisteredLimit(command.Command):
|
|
|
117
120
|
identity_client = self.app.client_manager.identity
|
|
118
121
|
|
|
119
122
|
errors = 0
|
|
120
|
-
for registered_limit_id in parsed_args.
|
|
123
|
+
for registered_limit_id in parsed_args.registered_limits:
|
|
121
124
|
try:
|
|
122
125
|
identity_client.registered_limits.delete(registered_limit_id)
|
|
123
126
|
except Exception as e:
|
|
@@ -134,7 +137,7 @@ class DeleteRegisteredLimit(command.Command):
|
|
|
134
137
|
)
|
|
135
138
|
|
|
136
139
|
if errors > 0:
|
|
137
|
-
total = len(parsed_args.
|
|
140
|
+
total = len(parsed_args.registered_limits)
|
|
138
141
|
msg = _(
|
|
139
142
|
"%(errors)s of %(total)s registered limits failed to delete."
|
|
140
143
|
) % {'errors': errors, 'total': total}
|
|
@@ -149,7 +152,9 @@ class ListRegisteredLimit(command.Lister):
|
|
|
149
152
|
parser.add_argument(
|
|
150
153
|
'--service',
|
|
151
154
|
metavar='<service>',
|
|
152
|
-
help=_(
|
|
155
|
+
help=_(
|
|
156
|
+
'Service responsible for the resource to limit (name or ID)'
|
|
157
|
+
),
|
|
153
158
|
)
|
|
154
159
|
parser.add_argument(
|
|
155
160
|
'--resource-name',
|
|
@@ -228,9 +233,9 @@ class SetRegisteredLimit(command.ShowOne):
|
|
|
228
233
|
'--service',
|
|
229
234
|
metavar='<service>',
|
|
230
235
|
help=_(
|
|
231
|
-
'Service to be updated responsible for the resource to '
|
|
232
|
-
'
|
|
233
|
-
'be different than existing value otherwise it will be '
|
|
236
|
+
'Service to be updated responsible for the resource to limit '
|
|
237
|
+
'(name or ID). Either --service, --resource-name or --region '
|
|
238
|
+
'must be different than existing value otherwise it will be '
|
|
234
239
|
'duplicate entry'
|
|
235
240
|
),
|
|
236
241
|
)
|
|
@@ -18,10 +18,10 @@
|
|
|
18
18
|
import logging
|
|
19
19
|
|
|
20
20
|
from openstack import exceptions as sdk_exc
|
|
21
|
-
from osc_lib.command import command
|
|
22
21
|
from osc_lib import exceptions
|
|
23
22
|
from osc_lib import utils
|
|
24
23
|
|
|
24
|
+
from openstackclient import command
|
|
25
25
|
from openstackclient.i18n import _
|
|
26
26
|
from openstackclient.identity import common
|
|
27
27
|
|
|
@@ -82,32 +82,12 @@ def _add_identity_and_resource_options_to_parser(parser):
|
|
|
82
82
|
common.add_inherited_option_to_parser(parser)
|
|
83
83
|
|
|
84
84
|
|
|
85
|
-
def _find_sdk_id(
|
|
86
|
-
find_command, name_or_id, validate_actor_existence=True, **kwargs
|
|
87
|
-
):
|
|
88
|
-
try:
|
|
89
|
-
resource = find_command(
|
|
90
|
-
name_or_id=name_or_id, ignore_missing=False, **kwargs
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
# Mimic the behavior of
|
|
94
|
-
# openstackclient.identity.common._find_identity_resource()
|
|
95
|
-
# and ignore if we don't have permission to find a resource.
|
|
96
|
-
except sdk_exc.ForbiddenException:
|
|
97
|
-
return name_or_id
|
|
98
|
-
except sdk_exc.ResourceNotFound as exc:
|
|
99
|
-
if not validate_actor_existence:
|
|
100
|
-
return name_or_id
|
|
101
|
-
raise exceptions.CommandError from exc
|
|
102
|
-
return resource.id
|
|
103
|
-
|
|
104
|
-
|
|
105
85
|
def _process_identity_and_resource_options(
|
|
106
86
|
parsed_args, identity_client, validate_actor_existence=True
|
|
107
87
|
):
|
|
108
88
|
def _find_user():
|
|
109
89
|
domain_id = (
|
|
110
|
-
_find_sdk_id(
|
|
90
|
+
common._find_sdk_id(
|
|
111
91
|
identity_client.find_domain,
|
|
112
92
|
name_or_id=parsed_args.user_domain,
|
|
113
93
|
validate_actor_existence=validate_actor_existence,
|
|
@@ -115,7 +95,7 @@ def _process_identity_and_resource_options(
|
|
|
115
95
|
if parsed_args.user_domain
|
|
116
96
|
else None
|
|
117
97
|
)
|
|
118
|
-
return _find_sdk_id(
|
|
98
|
+
return common._find_sdk_id(
|
|
119
99
|
identity_client.find_user,
|
|
120
100
|
name_or_id=parsed_args.user,
|
|
121
101
|
validate_actor_existence=validate_actor_existence,
|
|
@@ -124,7 +104,7 @@ def _process_identity_and_resource_options(
|
|
|
124
104
|
|
|
125
105
|
def _find_group():
|
|
126
106
|
domain_id = (
|
|
127
|
-
_find_sdk_id(
|
|
107
|
+
common._find_sdk_id(
|
|
128
108
|
identity_client.find_domain,
|
|
129
109
|
name_or_id=parsed_args.group_domain,
|
|
130
110
|
validate_actor_existence=validate_actor_existence,
|
|
@@ -132,7 +112,7 @@ def _process_identity_and_resource_options(
|
|
|
132
112
|
if parsed_args.group_domain
|
|
133
113
|
else None
|
|
134
114
|
)
|
|
135
|
-
return _find_sdk_id(
|
|
115
|
+
return common._find_sdk_id(
|
|
136
116
|
identity_client.find_group,
|
|
137
117
|
name_or_id=parsed_args.group,
|
|
138
118
|
validate_actor_existence=validate_actor_existence,
|
|
@@ -141,7 +121,7 @@ def _process_identity_and_resource_options(
|
|
|
141
121
|
|
|
142
122
|
def _find_project():
|
|
143
123
|
domain_id = (
|
|
144
|
-
_find_sdk_id(
|
|
124
|
+
common._find_sdk_id(
|
|
145
125
|
identity_client.find_domain,
|
|
146
126
|
name_or_id=parsed_args.project_domain,
|
|
147
127
|
validate_actor_existence=validate_actor_existence,
|
|
@@ -149,7 +129,7 @@ def _process_identity_and_resource_options(
|
|
|
149
129
|
if parsed_args.project_domain
|
|
150
130
|
else None
|
|
151
131
|
)
|
|
152
|
-
return _find_sdk_id(
|
|
132
|
+
return common._find_sdk_id(
|
|
153
133
|
identity_client.find_project,
|
|
154
134
|
name_or_id=parsed_args.project,
|
|
155
135
|
validate_actor_existence=validate_actor_existence,
|
|
@@ -162,7 +142,7 @@ def _process_identity_and_resource_options(
|
|
|
162
142
|
kwargs['system'] = parsed_args.system
|
|
163
143
|
elif parsed_args.user and parsed_args.domain:
|
|
164
144
|
kwargs['user'] = _find_user()
|
|
165
|
-
kwargs['domain'] = _find_sdk_id(
|
|
145
|
+
kwargs['domain'] = common._find_sdk_id(
|
|
166
146
|
identity_client.find_domain,
|
|
167
147
|
name_or_id=parsed_args.domain,
|
|
168
148
|
validate_actor_existence=validate_actor_existence,
|
|
@@ -175,7 +155,7 @@ def _process_identity_and_resource_options(
|
|
|
175
155
|
kwargs['system'] = parsed_args.system
|
|
176
156
|
elif parsed_args.group and parsed_args.domain:
|
|
177
157
|
kwargs['group'] = _find_group()
|
|
178
|
-
kwargs['domain'] = _find_sdk_id(
|
|
158
|
+
kwargs['domain'] = common._find_sdk_id(
|
|
179
159
|
identity_client.find_domain,
|
|
180
160
|
name_or_id=parsed_args.domain,
|
|
181
161
|
validate_actor_existence=validate_actor_existence,
|
|
@@ -228,10 +208,10 @@ class AddRole(command.Command):
|
|
|
228
208
|
|
|
229
209
|
domain_id = None
|
|
230
210
|
if parsed_args.role_domain:
|
|
231
|
-
domain_id = _find_sdk_id(
|
|
211
|
+
domain_id = common._find_sdk_id(
|
|
232
212
|
identity_client.find_domain, name_or_id=parsed_args.role_domain
|
|
233
213
|
)
|
|
234
|
-
role = _find_sdk_id(
|
|
214
|
+
role = common._find_sdk_id(
|
|
235
215
|
identity_client.find_role,
|
|
236
216
|
name_or_id=parsed_args.role,
|
|
237
217
|
domain_id=domain_id,
|
|
@@ -328,15 +308,18 @@ class CreateRole(command.ShowOne):
|
|
|
328
308
|
|
|
329
309
|
create_kwargs = {}
|
|
330
310
|
if parsed_args.domain:
|
|
331
|
-
create_kwargs['domain_id'] = _find_sdk_id(
|
|
311
|
+
create_kwargs['domain_id'] = common._find_sdk_id(
|
|
332
312
|
identity_client.find_domain, name_or_id=parsed_args.domain
|
|
333
313
|
)
|
|
334
314
|
|
|
335
315
|
if parsed_args.name:
|
|
336
316
|
create_kwargs['name'] = parsed_args.name
|
|
317
|
+
|
|
337
318
|
if parsed_args.description:
|
|
338
319
|
create_kwargs['description'] = parsed_args.description
|
|
339
|
-
|
|
320
|
+
|
|
321
|
+
if parsed_args.immutable is not None:
|
|
322
|
+
create_kwargs['options'] = {"immutable": parsed_args.immutable}
|
|
340
323
|
|
|
341
324
|
try:
|
|
342
325
|
role = identity_client.create_role(**create_kwargs)
|
|
@@ -378,13 +361,13 @@ class DeleteRole(command.Command):
|
|
|
378
361
|
|
|
379
362
|
domain_id = None
|
|
380
363
|
if parsed_args.domain:
|
|
381
|
-
domain_id = _find_sdk_id(
|
|
364
|
+
domain_id = common._find_sdk_id(
|
|
382
365
|
identity_client.find_domain, parsed_args.domain
|
|
383
366
|
)
|
|
384
367
|
errors = 0
|
|
385
368
|
for role in parsed_args.roles:
|
|
386
369
|
try:
|
|
387
|
-
role_id = _find_sdk_id(
|
|
370
|
+
role_id = common._find_sdk_id(
|
|
388
371
|
identity_client.find_role,
|
|
389
372
|
name_or_id=role,
|
|
390
373
|
domain_id=domain_id,
|
|
@@ -427,6 +410,7 @@ class ListRole(command.Lister):
|
|
|
427
410
|
if parsed_args.domain:
|
|
428
411
|
domain = identity_client.find_domain(
|
|
429
412
|
name_or_id=parsed_args.domain,
|
|
413
|
+
ignore_missing=False,
|
|
430
414
|
)
|
|
431
415
|
data = identity_client.roles(domain_id=domain.id)
|
|
432
416
|
return (
|
|
@@ -479,11 +463,11 @@ class RemoveRole(command.Command):
|
|
|
479
463
|
|
|
480
464
|
domain_id = None
|
|
481
465
|
if parsed_args.role_domain:
|
|
482
|
-
domain_id = _find_sdk_id(
|
|
466
|
+
domain_id = common._find_sdk_id(
|
|
483
467
|
identity_client.find_domain,
|
|
484
468
|
name_or_id=parsed_args.role_domain,
|
|
485
469
|
)
|
|
486
|
-
role = _find_sdk_id(
|
|
470
|
+
role = common._find_sdk_id(
|
|
487
471
|
identity_client.find_role,
|
|
488
472
|
name_or_id=parsed_args.role,
|
|
489
473
|
domain_id=domain_id,
|
|
@@ -579,14 +563,16 @@ class SetRole(command.Command):
|
|
|
579
563
|
|
|
580
564
|
domain_id = None
|
|
581
565
|
if parsed_args.domain:
|
|
582
|
-
domain_id = _find_sdk_id(
|
|
566
|
+
domain_id = common._find_sdk_id(
|
|
583
567
|
identity_client.find_domain,
|
|
584
568
|
name_or_id=parsed_args.domain,
|
|
585
569
|
)
|
|
586
570
|
update_kwargs["domain_id"] = domain_id
|
|
587
571
|
|
|
588
|
-
|
|
589
|
-
|
|
572
|
+
if parsed_args.immutable is not None:
|
|
573
|
+
update_kwargs["options"] = {"immutable": parsed_args.immutable}
|
|
574
|
+
|
|
575
|
+
role = common._find_sdk_id(
|
|
590
576
|
identity_client.find_role,
|
|
591
577
|
name_or_id=parsed_args.role,
|
|
592
578
|
domain_id=domain_id,
|
|
@@ -618,7 +604,7 @@ class ShowRole(command.ShowOne):
|
|
|
618
604
|
|
|
619
605
|
domain_id = None
|
|
620
606
|
if parsed_args.domain:
|
|
621
|
-
domain_id = _find_sdk_id(
|
|
607
|
+
domain_id = common._find_sdk_id(
|
|
622
608
|
identity_client.find_domain,
|
|
623
609
|
name_or_id=parsed_args.domain,
|
|
624
610
|
)
|
|
@@ -13,9 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
"""Identity v3 Assignment action implementations"""
|
|
15
15
|
|
|
16
|
-
from
|
|
17
|
-
from osc_lib.command import command
|
|
18
|
-
|
|
16
|
+
from openstackclient import command
|
|
19
17
|
from openstackclient.i18n import _
|
|
20
18
|
from openstackclient.identity import common
|
|
21
19
|
|
|
@@ -51,15 +49,6 @@ def _format_role_assignment_(assignment, include_names):
|
|
|
51
49
|
)
|
|
52
50
|
|
|
53
51
|
|
|
54
|
-
def _find_sdk_id(find_command, name_or_id, **kwargs):
|
|
55
|
-
try:
|
|
56
|
-
return find_command(
|
|
57
|
-
name_or_id=name_or_id, ignore_missing=False, **kwargs
|
|
58
|
-
).id
|
|
59
|
-
except sdk_exceptions.ForbiddenException:
|
|
60
|
-
return name_or_id
|
|
61
|
-
|
|
62
|
-
|
|
63
52
|
class ListRoleAssignment(command.Lister):
|
|
64
53
|
_description = _("List role assignments")
|
|
65
54
|
|
|
@@ -135,12 +124,12 @@ class ListRoleAssignment(command.Lister):
|
|
|
135
124
|
role_id = None
|
|
136
125
|
role_domain_id = None
|
|
137
126
|
if parsed_args.role_domain:
|
|
138
|
-
role_domain_id = _find_sdk_id(
|
|
127
|
+
role_domain_id = common._find_sdk_id(
|
|
139
128
|
identity_client.find_domain,
|
|
140
129
|
name_or_id=parsed_args.role_domain,
|
|
141
130
|
)
|
|
142
131
|
if parsed_args.role:
|
|
143
|
-
role_id = _find_sdk_id(
|
|
132
|
+
role_id = common._find_sdk_id(
|
|
144
133
|
identity_client.find_role,
|
|
145
134
|
name_or_id=parsed_args.role,
|
|
146
135
|
domain_id=role_domain_id,
|
|
@@ -148,21 +137,21 @@ class ListRoleAssignment(command.Lister):
|
|
|
148
137
|
|
|
149
138
|
user_domain_id = None
|
|
150
139
|
if parsed_args.user_domain:
|
|
151
|
-
user_domain_id = _find_sdk_id(
|
|
140
|
+
user_domain_id = common._find_sdk_id(
|
|
152
141
|
identity_client.find_domain,
|
|
153
142
|
name_or_id=parsed_args.user_domain,
|
|
154
143
|
)
|
|
155
144
|
|
|
156
145
|
user_id = None
|
|
157
146
|
if parsed_args.user:
|
|
158
|
-
user_id = _find_sdk_id(
|
|
147
|
+
user_id = common._find_sdk_id(
|
|
159
148
|
identity_client.find_user,
|
|
160
149
|
name_or_id=parsed_args.user,
|
|
161
150
|
domain_id=user_domain_id,
|
|
162
151
|
)
|
|
163
152
|
elif parsed_args.authuser:
|
|
164
153
|
if auth_ref:
|
|
165
|
-
user_id = _find_sdk_id(
|
|
154
|
+
user_id = common._find_sdk_id(
|
|
166
155
|
identity_client.find_user,
|
|
167
156
|
name_or_id=auth_ref.user_id,
|
|
168
157
|
)
|
|
@@ -173,21 +162,21 @@ class ListRoleAssignment(command.Lister):
|
|
|
173
162
|
|
|
174
163
|
domain_id = None
|
|
175
164
|
if parsed_args.domain:
|
|
176
|
-
domain_id = _find_sdk_id(
|
|
165
|
+
domain_id = common._find_sdk_id(
|
|
177
166
|
identity_client.find_domain,
|
|
178
167
|
name_or_id=parsed_args.domain,
|
|
179
168
|
)
|
|
180
169
|
|
|
181
170
|
project_domain_id = None
|
|
182
171
|
if parsed_args.project_domain:
|
|
183
|
-
project_domain_id = _find_sdk_id(
|
|
172
|
+
project_domain_id = common._find_sdk_id(
|
|
184
173
|
identity_client.find_domain,
|
|
185
174
|
name_or_id=parsed_args.project_domain,
|
|
186
175
|
)
|
|
187
176
|
|
|
188
177
|
project_id = None
|
|
189
178
|
if parsed_args.project:
|
|
190
|
-
project_id = _find_sdk_id(
|
|
179
|
+
project_id = common._find_sdk_id(
|
|
191
180
|
identity_client.find_project,
|
|
192
181
|
name_or_id=common._get_token_resource(
|
|
193
182
|
identity_client, 'project', parsed_args.project
|
|
@@ -196,21 +185,21 @@ class ListRoleAssignment(command.Lister):
|
|
|
196
185
|
)
|
|
197
186
|
elif parsed_args.authproject:
|
|
198
187
|
if auth_ref:
|
|
199
|
-
project_id = _find_sdk_id(
|
|
188
|
+
project_id = common._find_sdk_id(
|
|
200
189
|
identity_client.find_project,
|
|
201
190
|
name_or_id=auth_ref.project_id,
|
|
202
191
|
)
|
|
203
192
|
|
|
204
193
|
group_domain_id = None
|
|
205
194
|
if parsed_args.group_domain:
|
|
206
|
-
group_domain_id = _find_sdk_id(
|
|
195
|
+
group_domain_id = common._find_sdk_id(
|
|
207
196
|
identity_client.find_domain,
|
|
208
197
|
name_or_id=parsed_args.group_domain,
|
|
209
198
|
)
|
|
210
199
|
|
|
211
200
|
group_id = None
|
|
212
201
|
if parsed_args.group:
|
|
213
|
-
group_id = _find_sdk_id(
|
|
202
|
+
group_id = common._find_sdk_id(
|
|
214
203
|
identity_client.find_group,
|
|
215
204
|
name_or_id=parsed_args.group,
|
|
216
205
|
domain_id=group_domain_id,
|
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
|
|
18
18
|
import logging
|
|
19
19
|
|
|
20
|
-
from osc_lib.command import command
|
|
21
20
|
from osc_lib import exceptions
|
|
22
21
|
from osc_lib import utils
|
|
23
22
|
|
|
23
|
+
from openstackclient import command
|
|
24
24
|
from openstackclient.i18n import _
|
|
25
25
|
from openstackclient.identity import common
|
|
26
26
|
|