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
|
@@ -114,6 +114,7 @@ def add_tag_option_to_parser_for_set(parser, resource_name):
|
|
|
114
114
|
parser.add_argument(
|
|
115
115
|
'--remove-tag',
|
|
116
116
|
action='append',
|
|
117
|
+
dest='remove_tags',
|
|
117
118
|
metavar='<tag>',
|
|
118
119
|
default=[],
|
|
119
120
|
help=_(
|
|
@@ -128,8 +129,8 @@ def update_tags_in_args(parsed_args, obj, args):
|
|
|
128
129
|
if parsed_args.clear_tags:
|
|
129
130
|
args['tags'] = []
|
|
130
131
|
obj.tags = []
|
|
131
|
-
if parsed_args.
|
|
132
|
-
args['tags'] = sorted(set(obj.tags) - set(parsed_args.
|
|
132
|
+
if parsed_args.remove_tags:
|
|
133
|
+
args['tags'] = sorted(set(obj.tags) - set(parsed_args.remove_tags))
|
|
133
134
|
return
|
|
134
135
|
if parsed_args.tags:
|
|
135
136
|
args['tags'] = sorted(set(obj.tags).union(set(parsed_args.tags)))
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
|
|
16
16
|
"""Identity v3 Token action implementations"""
|
|
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
|
|
24
24
|
|
|
@@ -37,6 +37,7 @@ class AuthorizeRequestToken(command.ShowOne):
|
|
|
37
37
|
parser.add_argument(
|
|
38
38
|
'--role',
|
|
39
39
|
metavar='<role>',
|
|
40
|
+
dest='roles',
|
|
40
41
|
action='append',
|
|
41
42
|
default=[],
|
|
42
43
|
required=True,
|
|
@@ -52,7 +53,7 @@ class AuthorizeRequestToken(command.ShowOne):
|
|
|
52
53
|
|
|
53
54
|
# NOTE(stevemar): We want a list of role ids
|
|
54
55
|
roles = []
|
|
55
|
-
for role in parsed_args.
|
|
56
|
+
for role in parsed_args.roles:
|
|
56
57
|
role_id = utils.find_resource(
|
|
57
58
|
identity_client.roles,
|
|
58
59
|
role,
|
|
@@ -18,10 +18,10 @@ import itertools
|
|
|
18
18
|
import logging
|
|
19
19
|
|
|
20
20
|
from openstack import exceptions as sdk_exceptions
|
|
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
|
|
|
@@ -179,7 +179,9 @@ class CreateTrust(command.ShowOne):
|
|
|
179
179
|
roles = []
|
|
180
180
|
for role in parsed_args.roles:
|
|
181
181
|
try:
|
|
182
|
-
role_id = identity_client.find_role(
|
|
182
|
+
role_id = identity_client.find_role(
|
|
183
|
+
role, ignore_missing=False
|
|
184
|
+
).id
|
|
183
185
|
except sdk_exceptions.ForbiddenException:
|
|
184
186
|
role_id = role
|
|
185
187
|
roles.append({"id": role_id})
|
|
@@ -17,9 +17,9 @@ The first step of federated auth is to fetch an unscoped token. From there,
|
|
|
17
17
|
the user can list domains and projects they are allowed to access, and request
|
|
18
18
|
a scoped token."""
|
|
19
19
|
|
|
20
|
-
from osc_lib.command import command
|
|
21
20
|
from osc_lib import utils
|
|
22
21
|
|
|
22
|
+
from openstackclient import command
|
|
23
23
|
from openstackclient.i18n import _
|
|
24
24
|
|
|
25
25
|
|
|
@@ -20,10 +20,10 @@ import logging
|
|
|
20
20
|
import typing as ty
|
|
21
21
|
|
|
22
22
|
from openstack import exceptions as sdk_exc
|
|
23
|
-
from osc_lib.command import command
|
|
24
23
|
from osc_lib import exceptions
|
|
25
24
|
from osc_lib import utils
|
|
26
25
|
|
|
26
|
+
from openstackclient import command
|
|
27
27
|
from openstackclient.i18n import _
|
|
28
28
|
from openstackclient.identity import common
|
|
29
29
|
|
|
@@ -82,9 +82,9 @@ def _get_options_for_user(identity_client, parsed_args):
|
|
|
82
82
|
options['multi_factor_auth_enabled'] = True
|
|
83
83
|
if parsed_args.disable_multi_factor_auth:
|
|
84
84
|
options['multi_factor_auth_enabled'] = False
|
|
85
|
-
if parsed_args.
|
|
85
|
+
if parsed_args.multi_factor_auth_rules:
|
|
86
86
|
auth_rules = [
|
|
87
|
-
rule.split(",") for rule in parsed_args.
|
|
87
|
+
rule.split(",") for rule in parsed_args.multi_factor_auth_rules
|
|
88
88
|
]
|
|
89
89
|
if auth_rules:
|
|
90
90
|
options['multi_factor_auth_rules'] = auth_rules
|
|
@@ -175,7 +175,8 @@ def _add_user_options(parser):
|
|
|
175
175
|
parser.add_argument(
|
|
176
176
|
'--multi-factor-auth-rule',
|
|
177
177
|
metavar='<rule>',
|
|
178
|
-
|
|
178
|
+
dest='multi_factor_auth_rules',
|
|
179
|
+
action='append',
|
|
179
180
|
default=[],
|
|
180
181
|
help=_(
|
|
181
182
|
'Set multi-factor auth rules. For example, to set a rule '
|
|
@@ -298,6 +299,9 @@ class CreateUser(command.ShowOne):
|
|
|
298
299
|
"when a user does not have a password."
|
|
299
300
|
)
|
|
300
301
|
)
|
|
302
|
+
else:
|
|
303
|
+
kwargs['password'] = password
|
|
304
|
+
|
|
301
305
|
options = _get_options_for_user(identity_client, parsed_args)
|
|
302
306
|
if options:
|
|
303
307
|
kwargs['options'] = options
|
|
@@ -306,7 +310,6 @@ class CreateUser(command.ShowOne):
|
|
|
306
310
|
user = identity_client.create_user(
|
|
307
311
|
is_enabled=is_enabled,
|
|
308
312
|
name=parsed_args.name,
|
|
309
|
-
password=password,
|
|
310
313
|
**kwargs,
|
|
311
314
|
)
|
|
312
315
|
except sdk_exc.ConflictException:
|
|
@@ -420,7 +423,8 @@ class ListUser(command.Lister):
|
|
|
420
423
|
dest='is_enabled',
|
|
421
424
|
default=None,
|
|
422
425
|
help=_(
|
|
423
|
-
'List only enabled users, does nothing with
|
|
426
|
+
'List only enabled users, does nothing with '
|
|
427
|
+
'--project and --group'
|
|
424
428
|
),
|
|
425
429
|
)
|
|
426
430
|
parser.add_argument(
|
|
@@ -429,7 +433,8 @@ class ListUser(command.Lister):
|
|
|
429
433
|
dest='is_enabled',
|
|
430
434
|
default=None,
|
|
431
435
|
help=_(
|
|
432
|
-
'List only disabled users, does nothing with
|
|
436
|
+
'List only disabled users, does nothing with '
|
|
437
|
+
'--project and --group'
|
|
433
438
|
),
|
|
434
439
|
)
|
|
435
440
|
return parser
|
|
@@ -441,6 +446,7 @@ class ListUser(command.Lister):
|
|
|
441
446
|
if parsed_args.domain:
|
|
442
447
|
domain = identity_client.find_domain(
|
|
443
448
|
name_or_id=parsed_args.domain,
|
|
449
|
+
ignore_missing=False,
|
|
444
450
|
).id
|
|
445
451
|
|
|
446
452
|
group = None
|
|
@@ -467,15 +473,13 @@ class ListUser(command.Lister):
|
|
|
467
473
|
ignore_missing=False,
|
|
468
474
|
).id
|
|
469
475
|
|
|
470
|
-
assignments = identity_client.role_assignments_filter(
|
|
471
|
-
project=project
|
|
472
|
-
)
|
|
473
|
-
|
|
474
476
|
# NOTE(stevemar): If a user has more than one role on a project
|
|
475
477
|
# then they will have two entries in the returned data. Since we
|
|
476
478
|
# are looking for any role, let's just track unique user IDs.
|
|
477
479
|
user_ids = set()
|
|
478
|
-
for assignment in
|
|
480
|
+
for assignment in identity_client.role_assignments(
|
|
481
|
+
scope_project_id=project
|
|
482
|
+
):
|
|
479
483
|
if assignment.user:
|
|
480
484
|
user_ids.add(assignment.user['id'])
|
|
481
485
|
|
|
@@ -689,7 +693,12 @@ class SetPasswordUser(command.Command):
|
|
|
689
693
|
def take_action(self, parsed_args):
|
|
690
694
|
identity_client = self.app.client_manager.sdk_connection.identity
|
|
691
695
|
conn = self.app.client_manager.sdk_connection
|
|
692
|
-
|
|
696
|
+
auth = conn.config.get_auth()
|
|
697
|
+
if auth is None:
|
|
698
|
+
# this will never happen
|
|
699
|
+
raise exceptions.CommandError('invalid authentication info')
|
|
700
|
+
|
|
701
|
+
user_id = auth.get_user_id(conn.identity)
|
|
693
702
|
|
|
694
703
|
# FIXME(gyee): there are two scenarios:
|
|
695
704
|
#
|
|
@@ -19,15 +19,16 @@ import argparse
|
|
|
19
19
|
import logging
|
|
20
20
|
import os
|
|
21
21
|
import sys
|
|
22
|
+
import typing as ty
|
|
22
23
|
|
|
23
24
|
from cliff import columns as cliff_columns
|
|
24
25
|
from osc_lib.api import utils as api_utils
|
|
25
26
|
from osc_lib.cli import format_columns
|
|
26
27
|
from osc_lib.cli import parseractions
|
|
27
|
-
from osc_lib.command import command
|
|
28
28
|
from osc_lib import exceptions
|
|
29
29
|
from osc_lib import utils
|
|
30
30
|
|
|
31
|
+
from openstackclient import command
|
|
31
32
|
from openstackclient.i18n import _
|
|
32
33
|
|
|
33
34
|
CONTAINER_CHOICES = ["ami", "ari", "aki", "bare", "docker", "ova", "ovf"]
|
|
@@ -67,10 +68,7 @@ def _get_columns(item):
|
|
|
67
68
|
)
|
|
68
69
|
|
|
69
70
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
class HumanReadableSizeColumn(cliff_columns.FormattableColumn):
|
|
71
|
+
class HumanReadableSizeColumn(cliff_columns.FormattableColumn[int]):
|
|
74
72
|
def human_readable(self):
|
|
75
73
|
"""Return a formatted visibility string
|
|
76
74
|
|
|
@@ -84,7 +82,7 @@ class HumanReadableSizeColumn(cliff_columns.FormattableColumn):
|
|
|
84
82
|
return ''
|
|
85
83
|
|
|
86
84
|
|
|
87
|
-
class VisibilityColumn(cliff_columns.FormattableColumn):
|
|
85
|
+
class VisibilityColumn(cliff_columns.FormattableColumn[bool]):
|
|
88
86
|
def human_readable(self):
|
|
89
87
|
"""Return a formatted visibility string
|
|
90
88
|
|
|
@@ -340,9 +338,12 @@ class CreateImage(command.ShowOne):
|
|
|
340
338
|
|
|
341
339
|
if image:
|
|
342
340
|
display_columns, columns = _get_columns(image)
|
|
343
|
-
_formatters['properties'] = format_columns.DictColumn
|
|
344
341
|
data = utils.get_item_properties(
|
|
345
|
-
image,
|
|
342
|
+
image,
|
|
343
|
+
columns,
|
|
344
|
+
formatters={
|
|
345
|
+
'properties': format_columns.DictColumn,
|
|
346
|
+
},
|
|
346
347
|
)
|
|
347
348
|
return (display_columns, data)
|
|
348
349
|
elif info:
|
|
@@ -493,19 +494,19 @@ class ListImage(command.Lister):
|
|
|
493
494
|
column_headers = columns
|
|
494
495
|
|
|
495
496
|
# List of image data received
|
|
496
|
-
|
|
497
|
+
images = list(image_client.images(**kwargs))
|
|
497
498
|
|
|
498
499
|
if parsed_args.property:
|
|
499
500
|
# NOTE(dtroyer): coerce to a list to subscript it in py3
|
|
500
501
|
attr, value = list(parsed_args.property.items())[0]
|
|
501
502
|
api_utils.simple_filter(
|
|
502
|
-
|
|
503
|
+
images,
|
|
503
504
|
attr=attr,
|
|
504
505
|
value=value,
|
|
505
506
|
property_field='properties',
|
|
506
507
|
)
|
|
507
508
|
|
|
508
|
-
data = utils.sort_items(
|
|
509
|
+
data = utils.sort_items(images, parsed_args.sort)
|
|
509
510
|
|
|
510
511
|
return (
|
|
511
512
|
column_headers,
|
|
@@ -528,6 +529,16 @@ class SaveImage(command.Command):
|
|
|
528
529
|
|
|
529
530
|
def get_parser(self, prog_name):
|
|
530
531
|
parser = super().get_parser(prog_name)
|
|
532
|
+
parser.add_argument(
|
|
533
|
+
"--chunk-size",
|
|
534
|
+
type=int,
|
|
535
|
+
default=1024,
|
|
536
|
+
metavar="<chunk-size>",
|
|
537
|
+
help=_(
|
|
538
|
+
"Size in bytes to read from the wire and buffer at one "
|
|
539
|
+
"time (default: 1024)"
|
|
540
|
+
),
|
|
541
|
+
)
|
|
531
542
|
parser.add_argument(
|
|
532
543
|
"--file",
|
|
533
544
|
metavar="<filename>",
|
|
@@ -550,7 +561,12 @@ class SaveImage(command.Command):
|
|
|
550
561
|
if output_file is None:
|
|
551
562
|
output_file = getattr(sys.stdout, "buffer", sys.stdout)
|
|
552
563
|
|
|
553
|
-
image_client.download_image(
|
|
564
|
+
image_client.download_image(
|
|
565
|
+
image.id,
|
|
566
|
+
stream=True,
|
|
567
|
+
output=output_file,
|
|
568
|
+
chunk_size=parsed_args.chunk_size,
|
|
569
|
+
)
|
|
554
570
|
|
|
555
571
|
|
|
556
572
|
class SetImage(command.Command):
|
|
@@ -824,11 +840,13 @@ class ShowImage(command.ShowOne):
|
|
|
824
840
|
parsed_args.image, ignore_missing=False
|
|
825
841
|
)
|
|
826
842
|
|
|
843
|
+
formatters: dict[
|
|
844
|
+
str, type[cliff_columns.FormattableColumn[ty.Any]]
|
|
845
|
+
] = {
|
|
846
|
+
'properties': format_columns.DictColumn,
|
|
847
|
+
}
|
|
827
848
|
if parsed_args.human_readable:
|
|
828
|
-
|
|
849
|
+
formatters['size'] = HumanReadableSizeColumn
|
|
829
850
|
display_columns, columns = _get_columns(image)
|
|
830
|
-
|
|
831
|
-
data = utils.get_item_properties(
|
|
832
|
-
image, columns, formatters=_formatters
|
|
833
|
-
)
|
|
851
|
+
data = utils.get_item_properties(image, columns, formatters=formatters)
|
|
834
852
|
return (display_columns, data)
|
|
@@ -17,10 +17,10 @@ import copy
|
|
|
17
17
|
import datetime
|
|
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
|
|
|
26
26
|
|
|
@@ -37,14 +37,18 @@ def _format_image_cache(cached_images):
|
|
|
37
37
|
image_obj = copy.deepcopy(image)
|
|
38
38
|
image_obj['state'] = 'cached'
|
|
39
39
|
image_obj['last_accessed'] = (
|
|
40
|
-
datetime.datetime.
|
|
41
|
-
image['last_accessed']
|
|
42
|
-
)
|
|
40
|
+
datetime.datetime.fromtimestamp(
|
|
41
|
+
image['last_accessed'], tz=datetime.timezone.utc
|
|
42
|
+
)
|
|
43
|
+
.replace(tzinfo=None)
|
|
44
|
+
.isoformat()
|
|
43
45
|
)
|
|
44
46
|
image_obj['last_modified'] = (
|
|
45
|
-
datetime.datetime.
|
|
46
|
-
image['last_modified']
|
|
47
|
-
)
|
|
47
|
+
datetime.datetime.fromtimestamp(
|
|
48
|
+
image['last_modified'], tz=datetime.timezone.utc
|
|
49
|
+
)
|
|
50
|
+
.replace(tzinfo=None)
|
|
51
|
+
.isoformat()
|
|
48
52
|
)
|
|
49
53
|
image_list.append(image_obj)
|
|
50
54
|
elif item == "queued_images":
|
|
@@ -22,6 +22,7 @@ import logging
|
|
|
22
22
|
import os
|
|
23
23
|
import sys
|
|
24
24
|
import typing as ty
|
|
25
|
+
import urllib.parse
|
|
25
26
|
|
|
26
27
|
from openstack import exceptions as sdk_exceptions
|
|
27
28
|
from openstack.image import image_signer
|
|
@@ -29,10 +30,10 @@ from openstack import utils as sdk_utils
|
|
|
29
30
|
from osc_lib.api import utils as api_utils
|
|
30
31
|
from osc_lib.cli import format_columns
|
|
31
32
|
from osc_lib.cli import parseractions
|
|
32
|
-
from osc_lib.command import command
|
|
33
33
|
from osc_lib import exceptions
|
|
34
34
|
from osc_lib import utils
|
|
35
35
|
|
|
36
|
+
from openstackclient import command
|
|
36
37
|
from openstackclient.common import pagination
|
|
37
38
|
from openstackclient.common import progressbar
|
|
38
39
|
from openstackclient.i18n import _
|
|
@@ -54,6 +55,19 @@ DISK_CHOICES = [
|
|
|
54
55
|
"iso",
|
|
55
56
|
"ploop",
|
|
56
57
|
]
|
|
58
|
+
# A list of openstacksdk Image object attributes (values) that named
|
|
59
|
+
# differently from actual properties stored by Glance (keys).
|
|
60
|
+
IMAGE_ATTRIBUTES_CUSTOM_NAMES = {
|
|
61
|
+
'os_hidden': 'is_hidden',
|
|
62
|
+
'protected': 'is_protected',
|
|
63
|
+
'os_hash_algo': 'hash_algo',
|
|
64
|
+
'os_hash_value': 'hash_value',
|
|
65
|
+
'img_config_drive': 'needs_config_drive',
|
|
66
|
+
'os_secure_boot': 'needs_secure_boot',
|
|
67
|
+
'hw_vif_multiqueue_enabled': 'is_hw_vif_multiqueue_enabled',
|
|
68
|
+
'hw_boot_menu': 'is_hw_boot_menu_enabled',
|
|
69
|
+
'auto_disk_config': 'has_auto_disk_config',
|
|
70
|
+
}
|
|
57
71
|
MEMBER_STATUS_CHOICES = ["accepted", "pending", "rejected", "all"]
|
|
58
72
|
|
|
59
73
|
LOG = logging.getLogger(__name__)
|
|
@@ -84,6 +98,9 @@ def _format_image(image, human_readable=False):
|
|
|
84
98
|
'virtual_size',
|
|
85
99
|
'min_ram',
|
|
86
100
|
'schema',
|
|
101
|
+
'is_hidden',
|
|
102
|
+
'hash_algo',
|
|
103
|
+
'hash_value',
|
|
87
104
|
]
|
|
88
105
|
|
|
89
106
|
# TODO(gtema/anybody): actually it should be possible to drop this method,
|
|
@@ -534,7 +551,7 @@ class CreateImage(command.ShowOne):
|
|
|
534
551
|
sign_cert_id = parsed_args.sign_cert_id
|
|
535
552
|
signer = image_signer.ImageSigner()
|
|
536
553
|
try:
|
|
537
|
-
pw = utils.get_password(
|
|
554
|
+
pw: str | None = utils.get_password(
|
|
538
555
|
self.app.stdin,
|
|
539
556
|
prompt=(
|
|
540
557
|
"Please enter private key password, leave "
|
|
@@ -545,12 +562,11 @@ class CreateImage(command.ShowOne):
|
|
|
545
562
|
|
|
546
563
|
if not pw or len(pw) < 1:
|
|
547
564
|
pw = None
|
|
548
|
-
else:
|
|
549
|
-
# load_private_key() requires the password to be
|
|
550
|
-
# passed as bytes
|
|
551
|
-
pw = pw.encode()
|
|
552
565
|
|
|
553
|
-
signer.load_private_key(
|
|
566
|
+
signer.load_private_key(
|
|
567
|
+
sign_key_path,
|
|
568
|
+
password=pw.encode() if pw else None,
|
|
569
|
+
)
|
|
554
570
|
except Exception:
|
|
555
571
|
msg = _(
|
|
556
572
|
"Error during sign operation: private key "
|
|
@@ -889,6 +905,8 @@ class ListImage(command.Lister):
|
|
|
889
905
|
'visibility',
|
|
890
906
|
'is_protected',
|
|
891
907
|
'owner_id',
|
|
908
|
+
'hash_algo',
|
|
909
|
+
'hash_value',
|
|
892
910
|
'tags',
|
|
893
911
|
)
|
|
894
912
|
column_headers: tuple[str, ...] = (
|
|
@@ -902,6 +920,8 @@ class ListImage(command.Lister):
|
|
|
902
920
|
'Visibility',
|
|
903
921
|
'Protected',
|
|
904
922
|
'Project',
|
|
923
|
+
'Hash Algorithm',
|
|
924
|
+
'Hash Value',
|
|
905
925
|
'Tags',
|
|
906
926
|
)
|
|
907
927
|
else:
|
|
@@ -912,18 +932,19 @@ class ListImage(command.Lister):
|
|
|
912
932
|
if 'limit' in kwargs:
|
|
913
933
|
# Disable automatic pagination in SDK
|
|
914
934
|
kwargs['paginated'] = False
|
|
915
|
-
|
|
935
|
+
|
|
936
|
+
images = list(image_client.images(**kwargs))
|
|
916
937
|
|
|
917
938
|
if parsed_args.property:
|
|
918
939
|
for attr, value in parsed_args.property.items():
|
|
919
940
|
api_utils.simple_filter(
|
|
920
|
-
|
|
941
|
+
images,
|
|
921
942
|
attr=attr,
|
|
922
943
|
value=value,
|
|
923
944
|
property_field='properties',
|
|
924
945
|
)
|
|
925
946
|
|
|
926
|
-
data = utils.sort_items(
|
|
947
|
+
data = utils.sort_items(images, parsed_args.sort, str)
|
|
927
948
|
|
|
928
949
|
return (
|
|
929
950
|
column_headers,
|
|
@@ -1052,6 +1073,16 @@ class SaveImage(command.Command):
|
|
|
1052
1073
|
|
|
1053
1074
|
def get_parser(self, prog_name):
|
|
1054
1075
|
parser = super().get_parser(prog_name)
|
|
1076
|
+
parser.add_argument(
|
|
1077
|
+
"--chunk-size",
|
|
1078
|
+
type=int,
|
|
1079
|
+
default=1024,
|
|
1080
|
+
metavar="<chunk-size>",
|
|
1081
|
+
help=_(
|
|
1082
|
+
"Size in bytes to read from the wire and buffer at one "
|
|
1083
|
+
"time (default: 1024)"
|
|
1084
|
+
),
|
|
1085
|
+
)
|
|
1055
1086
|
parser.add_argument(
|
|
1056
1087
|
"--file",
|
|
1057
1088
|
metavar="<filename>",
|
|
@@ -1076,7 +1107,12 @@ class SaveImage(command.Command):
|
|
|
1076
1107
|
if output_file is None:
|
|
1077
1108
|
output_file = getattr(sys.stdout, "buffer", sys.stdout)
|
|
1078
1109
|
|
|
1079
|
-
image_client.download_image(
|
|
1110
|
+
image_client.download_image(
|
|
1111
|
+
image.id,
|
|
1112
|
+
stream=True,
|
|
1113
|
+
output=output_file,
|
|
1114
|
+
chunk_size=parsed_args.chunk_size,
|
|
1115
|
+
)
|
|
1080
1116
|
|
|
1081
1117
|
|
|
1082
1118
|
class SetImage(command.Command):
|
|
@@ -1357,7 +1393,10 @@ class SetImage(command.Command):
|
|
|
1357
1393
|
if parsed_args.visibility is not None:
|
|
1358
1394
|
kwargs['visibility'] = parsed_args.visibility
|
|
1359
1395
|
|
|
1360
|
-
if
|
|
1396
|
+
# Only set owner_id if --project is used WITHOUT membership flags
|
|
1397
|
+
# When --project is used with --accept/--reject/--pending, it should
|
|
1398
|
+
# only identify which member's status to update, not change ownership
|
|
1399
|
+
if parsed_args.project and not parsed_args.membership:
|
|
1361
1400
|
# We already did the project lookup above
|
|
1362
1401
|
kwargs['owner_id'] = project_id
|
|
1363
1402
|
|
|
@@ -1477,6 +1516,11 @@ class UnsetImage(command.Command):
|
|
|
1477
1516
|
)
|
|
1478
1517
|
new_props.pop(k, None)
|
|
1479
1518
|
kwargs['properties'] = new_props
|
|
1519
|
+
elif (
|
|
1520
|
+
k in IMAGE_ATTRIBUTES_CUSTOM_NAMES
|
|
1521
|
+
and IMAGE_ATTRIBUTES_CUSTOM_NAMES[k] in image
|
|
1522
|
+
):
|
|
1523
|
+
delattr(image, IMAGE_ATTRIBUTES_CUSTOM_NAMES[k])
|
|
1480
1524
|
else:
|
|
1481
1525
|
LOG.error(
|
|
1482
1526
|
_(
|
|
@@ -1744,6 +1788,12 @@ class ImportImage(command.ShowOne):
|
|
|
1744
1788
|
"'--method=web-download'"
|
|
1745
1789
|
)
|
|
1746
1790
|
raise exceptions.CommandError(msg)
|
|
1791
|
+
_parsed = urllib.parse.urlparse(parsed_args.uri)
|
|
1792
|
+
if not all({_parsed.scheme, _parsed.netloc}):
|
|
1793
|
+
msg = _("'%(uri)s' is not a valid url")
|
|
1794
|
+
raise exceptions.CommandError(
|
|
1795
|
+
msg % {'uri': parsed_args.uri},
|
|
1796
|
+
)
|
|
1747
1797
|
else:
|
|
1748
1798
|
if parsed_args.uri:
|
|
1749
1799
|
msg = _(
|
openstackclient/image/v2/info.py
CHANGED
|
@@ -18,10 +18,10 @@
|
|
|
18
18
|
import logging
|
|
19
19
|
|
|
20
20
|
from osc_lib.cli import format_columns
|
|
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
|
|
|
27
27
|
_formatters = {
|
|
@@ -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
|
|
|
26
26
|
|
|
@@ -123,8 +123,11 @@ class DeleteMetadefObject(command.Command):
|
|
|
123
123
|
parser.add_argument(
|
|
124
124
|
"objects",
|
|
125
125
|
metavar="<object>",
|
|
126
|
-
nargs="
|
|
127
|
-
help=_(
|
|
126
|
+
nargs="*",
|
|
127
|
+
help=_(
|
|
128
|
+
"Metadef object(s) to delete (name) "
|
|
129
|
+
"(omit this argument to delete all objects in the namespace)"
|
|
130
|
+
),
|
|
128
131
|
)
|
|
129
132
|
return parser
|
|
130
133
|
|
|
@@ -133,6 +136,9 @@ class DeleteMetadefObject(command.Command):
|
|
|
133
136
|
|
|
134
137
|
namespace = parsed_args.namespace
|
|
135
138
|
|
|
139
|
+
if not parsed_args.objects:
|
|
140
|
+
return image_client.delete_all_metadef_objects(namespace)
|
|
141
|
+
|
|
136
142
|
result = 0
|
|
137
143
|
for obj in parsed_args.objects:
|
|
138
144
|
try:
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
import json
|
|
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
|
|
|
24
24
|
|
|
@@ -124,14 +124,22 @@ class DeleteMetadefProperty(command.Command):
|
|
|
124
124
|
parser.add_argument(
|
|
125
125
|
"properties",
|
|
126
126
|
metavar="<property>",
|
|
127
|
-
nargs="
|
|
128
|
-
help=_(
|
|
127
|
+
nargs="*",
|
|
128
|
+
help=_(
|
|
129
|
+
"Metadef properties to delete (name) "
|
|
130
|
+
"(omit this argument to delete all properties "
|
|
131
|
+
"in the namespace)"
|
|
132
|
+
),
|
|
129
133
|
)
|
|
130
134
|
return parser
|
|
131
135
|
|
|
132
136
|
def take_action(self, parsed_args):
|
|
133
137
|
image_client = self.app.client_manager.image
|
|
134
138
|
|
|
139
|
+
if not parsed_args.properties:
|
|
140
|
+
image_client.delete_all_metadef_properties(parsed_args.namespace)
|
|
141
|
+
return
|
|
142
|
+
|
|
135
143
|
result = 0
|
|
136
144
|
for prop in parsed_args.properties:
|
|
137
145
|
try:
|
openstackclient/image/v2/task.py
CHANGED