python-openstackclient 10.0.0__py3-none-any.whl → 10.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openstackclient/common/availability_zone.py +1 -1
- openstackclient/common/module.py +21 -27
- openstackclient/common/pagination.py +42 -4
- openstackclient/common/project_cleanup.py +1 -2
- openstackclient/common/quota.py +9 -5
- openstackclient/compute/v2/flavor.py +3 -1
- openstackclient/compute/v2/hypervisor.py +2 -0
- openstackclient/compute/v2/keypair.py +6 -2
- openstackclient/compute/v2/server.py +21 -12
- openstackclient/compute/v2/server_event.py +8 -1
- openstackclient/compute/v2/server_group.py +2 -0
- openstackclient/compute/v2/server_migration.py +3 -0
- openstackclient/compute/v2/server_volume.py +3 -1
- openstackclient/compute/v2/service.py +3 -1
- openstackclient/compute/v2/usage.py +2 -2
- openstackclient/identity/common.py +5 -1
- openstackclient/identity/v3/access_rule.py +6 -0
- openstackclient/identity/v3/application_credential.py +10 -3
- openstackclient/identity/v3/credential.py +4 -2
- openstackclient/identity/v3/domain.py +4 -2
- openstackclient/identity/v3/endpoint.py +57 -45
- openstackclient/identity/v3/federation_protocol.py +7 -5
- openstackclient/identity/v3/group.py +11 -10
- openstackclient/identity/v3/identity_provider.py +4 -1
- openstackclient/identity/v3/limit.py +5 -2
- openstackclient/identity/v3/mapping.py +36 -19
- openstackclient/identity/v3/project.py +18 -5
- openstackclient/identity/v3/region.py +4 -2
- openstackclient/identity/v3/registered_limit.py +3 -2
- openstackclient/identity/v3/role.py +2 -1
- openstackclient/identity/v3/role_assignment.py +3 -2
- openstackclient/identity/v3/service.py +4 -2
- openstackclient/identity/v3/service_provider.py +4 -2
- openstackclient/identity/v3/trust.py +8 -5
- openstackclient/identity/v3/user.py +38 -11
- openstackclient/image/v2/cache.py +2 -2
- openstackclient/image/v2/image.py +15 -9
- openstackclient/image/v2/metadef_namespaces.py +11 -10
- openstackclient/image/v2/metadef_objects.py +5 -5
- openstackclient/image/v2/metadef_properties.py +7 -4
- openstackclient/image/v2/task.py +11 -22
- openstackclient/network/utils.py +0 -41
- openstackclient/network/v2/address_group.py +13 -1
- openstackclient/network/v2/address_scope.py +13 -8
- openstackclient/network/v2/bgpvpn/bgpvpn.py +33 -19
- openstackclient/network/v2/bgpvpn/network_association.py +25 -13
- openstackclient/network/v2/bgpvpn/port_association.py +35 -21
- openstackclient/network/v2/bgpvpn/router_association.py +27 -14
- openstackclient/network/v2/default_security_group_rule.py +14 -6
- openstackclient/network/v2/floating_ip.py +12 -4
- openstackclient/network/v2/floating_ip_port_forwarding.py +12 -2
- openstackclient/network/v2/fwaas/group.py +34 -1
- openstackclient/network/v2/fwaas/rule.py +39 -3
- openstackclient/network/v2/ip_availability.py +13 -4
- openstackclient/network/v2/l3_conntrack_helper.py +14 -1
- openstackclient/network/v2/local_ip.py +4 -1
- openstackclient/network/v2/local_ip_association.py +4 -1
- openstackclient/network/v2/ndp_proxy.py +4 -1
- openstackclient/network/v2/network.py +87 -20
- openstackclient/network/v2/network_agent.py +32 -10
- openstackclient/network/v2/network_auto_allocated_topology.py +6 -5
- openstackclient/network/v2/network_flavor.py +19 -6
- openstackclient/network/v2/network_flavor_profile.py +20 -6
- openstackclient/network/v2/network_meter.py +19 -6
- openstackclient/network/v2/network_meter_rule.py +20 -2
- openstackclient/network/v2/network_qos_policy.py +15 -7
- openstackclient/network/v2/network_qos_rule.py +16 -1
- openstackclient/network/v2/network_qos_rule_type.py +16 -5
- openstackclient/network/v2/network_rbac.py +12 -5
- openstackclient/network/v2/network_segment.py +13 -1
- openstackclient/network/v2/network_segment_range.py +15 -3
- openstackclient/network/v2/network_trunk.py +4 -1
- openstackclient/network/v2/port.py +88 -12
- openstackclient/network/v2/router.py +27 -16
- openstackclient/network/v2/security_group.py +18 -49
- openstackclient/network/v2/security_group_rule.py +18 -5
- openstackclient/network/v2/subnet.py +15 -7
- openstackclient/network/v2/subnet_pool.py +13 -8
- openstackclient/network/v2/taas/tap_flow.py +13 -3
- openstackclient/network/v2/taas/tap_mirror.py +7 -4
- openstackclient/network/v2/taas/tap_service.py +4 -1
- openstackclient/object/v1/container.py +3 -1
- openstackclient/object/v1/object.py +3 -1
- openstackclient/tests/functional/identity/v3/common.py +34 -0
- openstackclient/tests/functional/identity/v3/test_application_credential.py +1 -1
- openstackclient/tests/functional/identity/v3/test_mapping.py +81 -0
- openstackclient/tests/functional/volume/v3/test_volume_group.py +163 -0
- openstackclient/tests/unit/common/test_limits.py +1 -1
- openstackclient/tests/unit/common/test_module.py +77 -44
- openstackclient/tests/unit/common/test_quota.py +9 -0
- openstackclient/tests/unit/compute/v2/fakes.py +1 -57
- openstackclient/tests/unit/compute/v2/test_agent.py +4 -4
- openstackclient/tests/unit/compute/v2/test_aggregate.py +1 -1
- openstackclient/tests/unit/compute/v2/test_console.py +2 -2
- openstackclient/tests/unit/compute/v2/test_console_connection.py +1 -1
- openstackclient/tests/unit/compute/v2/test_flavor.py +1 -1
- openstackclient/tests/unit/compute/v2/test_host.py +3 -3
- openstackclient/tests/unit/compute/v2/test_hypervisor.py +2 -2
- openstackclient/tests/unit/compute/v2/test_hypervisor_stats.py +1 -1
- openstackclient/tests/unit/compute/v2/test_keypair.py +1 -1
- openstackclient/tests/unit/compute/v2/test_server.py +15 -15
- openstackclient/tests/unit/compute/v2/test_server_backup.py +1 -1
- openstackclient/tests/unit/compute/v2/test_server_event.py +2 -2
- openstackclient/tests/unit/compute/v2/test_server_group.py +1 -1
- openstackclient/tests/unit/compute/v2/test_server_image.py +1 -1
- openstackclient/tests/unit/compute/v2/test_server_migration.py +4 -4
- openstackclient/tests/unit/compute/v2/test_server_share.py +4 -4
- openstackclient/tests/unit/compute/v2/test_server_volume.py +2 -2
- openstackclient/tests/unit/compute/v2/test_service.py +3 -3
- openstackclient/tests/unit/compute/v2/test_usage.py +1 -1
- openstackclient/tests/unit/identity/v2_0/fakes.py +3 -7
- openstackclient/tests/unit/identity/v2_0/test_endpoint.py +1 -1
- openstackclient/tests/unit/identity/v2_0/test_project.py +1 -1
- openstackclient/tests/unit/identity/v2_0/test_role.py +1 -1
- openstackclient/tests/unit/identity/v2_0/test_role_assignment.py +1 -1
- openstackclient/tests/unit/identity/v2_0/test_service.py +1 -1
- openstackclient/tests/unit/identity/v2_0/test_token.py +2 -2
- openstackclient/tests/unit/identity/v2_0/test_user.py +1 -1
- openstackclient/tests/unit/identity/v3/fakes.py +5 -38
- openstackclient/tests/unit/identity/v3/test_access_rule.py +3 -3
- openstackclient/tests/unit/identity/v3/test_application_credential.py +4 -4
- openstackclient/tests/unit/identity/v3/test_credential.py +5 -5
- openstackclient/tests/unit/identity/v3/test_domain.py +5 -5
- openstackclient/tests/unit/identity/v3/test_endpoint.py +6 -6
- openstackclient/tests/unit/identity/v3/test_endpoint_group.py +1 -1
- openstackclient/tests/unit/identity/v3/test_group.py +8 -8
- openstackclient/tests/unit/identity/v3/test_implied_role.py +1 -1
- openstackclient/tests/unit/identity/v3/test_limit.py +5 -5
- openstackclient/tests/unit/identity/v3/test_mappings.py +163 -79
- openstackclient/tests/unit/identity/v3/test_project.py +28 -5
- openstackclient/tests/unit/identity/v3/test_protocol.py +3 -3
- openstackclient/tests/unit/identity/v3/test_region.py +5 -5
- openstackclient/tests/unit/identity/v3/test_registered_limit.py +5 -5
- openstackclient/tests/unit/identity/v3/test_role.py +8 -8
- openstackclient/tests/unit/identity/v3/test_role_assignment.py +1 -1
- openstackclient/tests/unit/identity/v3/test_service.py +5 -5
- openstackclient/tests/unit/identity/v3/test_token.py +2 -2
- openstackclient/tests/unit/identity/v3/test_trust.py +4 -4
- openstackclient/tests/unit/identity/v3/test_user.py +73 -6
- openstackclient/tests/unit/network/v2/fakes.py +5 -77
- openstackclient/tests/unit/network/v2/fwaas/test_group.py +28 -2
- openstackclient/tests/unit/network/v2/fwaas/test_rule.py +28 -3
- openstackclient/tests/unit/network/v2/test_address_group.py +24 -0
- openstackclient/tests/unit/network/v2/test_address_scope.py +24 -0
- openstackclient/tests/unit/network/v2/test_floating_ip.py +24 -0
- openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py +24 -0
- openstackclient/tests/unit/network/v2/test_ip_availability.py +25 -0
- openstackclient/tests/unit/network/v2/test_l3_conntrack_helper.py +29 -3
- openstackclient/tests/unit/network/v2/test_network.py +74 -12
- openstackclient/tests/unit/network/v2/test_network_agent.py +50 -1
- openstackclient/tests/unit/network/v2/test_network_flavor.py +24 -0
- openstackclient/tests/unit/network/v2/test_network_flavor_profile.py +24 -0
- openstackclient/tests/unit/network/v2/test_network_meter.py +24 -0
- openstackclient/tests/unit/network/v2/test_network_qos_policy.py +24 -0
- openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py +24 -0
- openstackclient/tests/unit/network/v2/test_network_rbac.py +24 -0
- openstackclient/tests/unit/network/v2/test_network_segment.py +24 -0
- openstackclient/tests/unit/network/v2/test_network_segment_range.py +24 -0
- openstackclient/tests/unit/network/v2/test_port.py +166 -0
- openstackclient/tests/unit/network/v2/test_router.py +28 -7
- openstackclient/tests/unit/network/v2/test_security_group.py +22 -0
- openstackclient/tests/unit/network/v2/test_security_group_rule.py +25 -0
- openstackclient/tests/unit/network/v2/test_subnet.py +28 -4
- openstackclient/tests/unit/network/v2/test_subnet_pool.py +24 -0
- openstackclient/tests/unit/volume/v2/fakes.py +20 -140
- openstackclient/tests/unit/volume/v2/test_volume_backup.py +5 -9
- openstackclient/tests/unit/volume/v2/test_volume_snapshot.py +6 -0
- openstackclient/tests/unit/volume/v3/fakes.py +204 -100
- openstackclient/tests/unit/volume/v3/test_backup_record.py +114 -0
- openstackclient/tests/unit/volume/v3/test_consistency_group.py +720 -0
- openstackclient/tests/unit/volume/v3/test_consistency_group_snapshot.py +354 -0
- openstackclient/tests/unit/volume/v3/test_qos_specs.py +455 -0
- openstackclient/tests/unit/volume/v3/test_volume_attachment.py +2 -0
- openstackclient/tests/unit/volume/v3/test_volume_backend.py +158 -0
- openstackclient/tests/unit/volume/v3/test_volume_backup.py +5 -9
- openstackclient/tests/unit/volume/v3/test_volume_group_type.py +65 -0
- openstackclient/tests/unit/volume/v3/test_volume_host.py +115 -0
- openstackclient/tests/unit/volume/v3/test_volume_snapshot.py +6 -0
- openstackclient/volume/v2/volume.py +4 -2
- openstackclient/volume/v2/volume_backup.py +2 -3
- openstackclient/volume/v2/volume_snapshot.py +3 -4
- openstackclient/volume/v3/backup_record.py +94 -0
- openstackclient/volume/v3/consistency_group.py +400 -0
- openstackclient/volume/v3/consistency_group_snapshot.py +225 -0
- openstackclient/volume/v3/qos_specs.py +389 -0
- openstackclient/volume/v3/volume.py +4 -2
- openstackclient/volume/v3/volume_attachment.py +5 -1
- openstackclient/volume/v3/volume_backend.py +130 -0
- openstackclient/volume/v3/volume_backup.py +2 -3
- openstackclient/volume/v3/volume_group_snapshot.py +4 -6
- openstackclient/volume/v3/volume_group_type.py +1 -1
- openstackclient/volume/v3/volume_host.py +74 -0
- openstackclient/volume/v3/volume_message.py +3 -1
- openstackclient/volume/v3/volume_snapshot.py +2 -1
- {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/METADATA +3 -4
- {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/RECORD +202 -188
- {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/entry_points.txt +24 -24
- {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/licenses/AUTHORS +5 -0
- python_openstackclient-10.1.0.dist-info/pbr.json +1 -0
- python_openstackclient-10.0.0.dist-info/pbr.json +0 -1
- {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/WHEEL +0 -0
- {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/licenses/LICENSE +0 -0
- {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/top_level.txt +0 -0
|
@@ -22,19 +22,20 @@ import logging
|
|
|
22
22
|
from typing import Any
|
|
23
23
|
|
|
24
24
|
from openstack import exceptions as sdk_exc
|
|
25
|
+
from openstack.identity.v3 import user as _user
|
|
25
26
|
from openstack import utils as sdk_utils
|
|
26
27
|
from osc_lib import exceptions
|
|
27
28
|
from osc_lib import utils
|
|
28
29
|
|
|
29
30
|
from openstackclient import command
|
|
31
|
+
from openstackclient.common import pagination
|
|
30
32
|
from openstackclient.i18n import _
|
|
31
33
|
from openstackclient.identity import common
|
|
32
34
|
|
|
33
|
-
|
|
34
35
|
LOG = logging.getLogger(__name__)
|
|
35
36
|
|
|
36
37
|
|
|
37
|
-
def _format_user(user:
|
|
38
|
+
def _format_user(user: _user.User) -> tuple[tuple[str, ...], tuple[Any, ...]]:
|
|
38
39
|
columns = (
|
|
39
40
|
'default_project_id',
|
|
40
41
|
'domain_id',
|
|
@@ -448,11 +449,18 @@ class ListUser(command.Lister):
|
|
|
448
449
|
'--project and --group'
|
|
449
450
|
),
|
|
450
451
|
)
|
|
452
|
+
pagination.add_marker_pagination_option_to_parser(parser)
|
|
451
453
|
return parser
|
|
452
454
|
|
|
453
455
|
def take_action(
|
|
454
456
|
self, parsed_args: argparse.Namespace
|
|
455
457
|
) -> tuple[Sequence[str], Iterable[tuple[Any, ...]]]:
|
|
458
|
+
if parsed_args.project and (
|
|
459
|
+
parsed_args.limit is not None or parsed_args.marker is not None
|
|
460
|
+
):
|
|
461
|
+
msg = _('--limit and --marker are not supported with --project')
|
|
462
|
+
raise exceptions.CommandError(msg)
|
|
463
|
+
|
|
456
464
|
identity_client = sdk_utils.ensure_service_version(
|
|
457
465
|
self.app.client_manager.sdk_connection.identity, '3'
|
|
458
466
|
)
|
|
@@ -475,6 +483,15 @@ class ListUser(command.Lister):
|
|
|
475
483
|
if parsed_args.is_enabled is not None:
|
|
476
484
|
enabled = parsed_args.is_enabled
|
|
477
485
|
|
|
486
|
+
pagination_kwargs: dict[str, Any] = {}
|
|
487
|
+
if parsed_args.limit is not None:
|
|
488
|
+
pagination_kwargs['limit'] = parsed_args.limit
|
|
489
|
+
if parsed_args.max_items is not None:
|
|
490
|
+
pagination_kwargs['max_items'] = parsed_args.max_items
|
|
491
|
+
if parsed_args.marker is not None:
|
|
492
|
+
pagination_kwargs['marker'] = parsed_args.marker
|
|
493
|
+
|
|
494
|
+
data: list[_user.User]
|
|
478
495
|
if parsed_args.project:
|
|
479
496
|
if domain is not None:
|
|
480
497
|
project = identity_client.find_project(
|
|
@@ -504,21 +521,28 @@ class ListUser(command.Lister):
|
|
|
504
521
|
for user_id in user_ids:
|
|
505
522
|
user = identity_client.find_user(user_id, ignore_missing=False)
|
|
506
523
|
data.append(user)
|
|
507
|
-
|
|
508
524
|
elif parsed_args.group:
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
525
|
+
assert group is not None
|
|
526
|
+
data = list(
|
|
527
|
+
identity_client.group_users(
|
|
528
|
+
domain_id=domain, group=group, **pagination_kwargs
|
|
529
|
+
)
|
|
512
530
|
)
|
|
513
531
|
else:
|
|
514
532
|
if parsed_args.is_enabled is not None:
|
|
515
|
-
data =
|
|
516
|
-
|
|
517
|
-
|
|
533
|
+
data = list(
|
|
534
|
+
identity_client.users(
|
|
535
|
+
domain_id=domain,
|
|
536
|
+
is_enabled=enabled,
|
|
537
|
+
**pagination_kwargs,
|
|
538
|
+
)
|
|
518
539
|
)
|
|
519
540
|
else:
|
|
520
|
-
data =
|
|
521
|
-
|
|
541
|
+
data = list(
|
|
542
|
+
identity_client.users(
|
|
543
|
+
domain_id=domain,
|
|
544
|
+
**pagination_kwargs,
|
|
545
|
+
)
|
|
522
546
|
)
|
|
523
547
|
|
|
524
548
|
# Column handling
|
|
@@ -718,6 +742,9 @@ class SetPasswordUser(command.Command):
|
|
|
718
742
|
raise exceptions.CommandError('invalid authentication info')
|
|
719
743
|
|
|
720
744
|
user_id = auth.get_user_id(conn.session)
|
|
745
|
+
if user_id is None:
|
|
746
|
+
# this will never happen
|
|
747
|
+
raise exceptions.CommandError('invalid authentication info')
|
|
721
748
|
|
|
722
749
|
# FIXME(gyee): there are two scenarios:
|
|
723
750
|
#
|
|
@@ -41,14 +41,14 @@ def _format_image_cache(cached_images: dict[str, Any]) -> list[dict[str, Any]]:
|
|
|
41
41
|
image_obj['state'] = 'cached'
|
|
42
42
|
image_obj['last_accessed'] = (
|
|
43
43
|
datetime.datetime.fromtimestamp(
|
|
44
|
-
image['last_accessed'], tz=datetime.
|
|
44
|
+
image['last_accessed'], tz=datetime.UTC
|
|
45
45
|
)
|
|
46
46
|
.replace(tzinfo=None)
|
|
47
47
|
.isoformat()
|
|
48
48
|
)
|
|
49
49
|
image_obj['last_modified'] = (
|
|
50
50
|
datetime.datetime.fromtimestamp(
|
|
51
|
-
image['last_modified'], tz=datetime.
|
|
51
|
+
image['last_modified'], tz=datetime.UTC
|
|
52
52
|
)
|
|
53
53
|
.replace(tzinfo=None)
|
|
54
54
|
.isoformat()
|
|
@@ -27,6 +27,7 @@ import urllib.parse
|
|
|
27
27
|
|
|
28
28
|
from openstack import exceptions as sdk_exceptions
|
|
29
29
|
from openstack.image import image_signer
|
|
30
|
+
from openstack.image.v2 import image as _image
|
|
30
31
|
from openstack import utils as sdk_utils
|
|
31
32
|
from osc_lib.api import utils as api_utils
|
|
32
33
|
from osc_lib.cli import format_columns
|
|
@@ -74,11 +75,13 @@ MEMBER_STATUS_CHOICES = ["accepted", "pending", "rejected", "all"]
|
|
|
74
75
|
LOG = logging.getLogger(__name__)
|
|
75
76
|
|
|
76
77
|
|
|
77
|
-
def _format_image(
|
|
78
|
+
def _format_image(
|
|
79
|
+
image: _image.Image, human_readable: bool = False
|
|
80
|
+
) -> dict[str, object]:
|
|
78
81
|
"""Format an image to make it more consistent with OSC operations."""
|
|
79
82
|
|
|
80
83
|
info = {}
|
|
81
|
-
properties = {}
|
|
84
|
+
properties: dict[str, object] = {}
|
|
82
85
|
|
|
83
86
|
# the only fields we're not including is "links", "tags" and the properties
|
|
84
87
|
fields_to_show = [
|
|
@@ -106,25 +109,25 @@ def _format_image(image: Any, human_readable: bool = False) -> dict[str, Any]:
|
|
|
106
109
|
|
|
107
110
|
# TODO(gtema/anybody): actually it should be possible to drop this method,
|
|
108
111
|
# since SDK already delivers a proper object
|
|
109
|
-
|
|
112
|
+
data = image.to_dict(ignore_none=True, original_names=True)
|
|
110
113
|
|
|
111
114
|
# split out the usual key and the properties which are top-level
|
|
112
|
-
for key in
|
|
115
|
+
for key in data:
|
|
113
116
|
if key in fields_to_show:
|
|
114
|
-
info[key] =
|
|
117
|
+
info[key] = data[key]
|
|
115
118
|
elif key == 'tags':
|
|
116
119
|
continue # handle this later
|
|
117
120
|
elif key == 'properties':
|
|
118
121
|
# NOTE(gtema): flatten content of properties
|
|
119
|
-
properties.update(
|
|
122
|
+
properties.update(data[key])
|
|
120
123
|
elif key != 'location':
|
|
121
|
-
properties[key] =
|
|
124
|
+
properties[key] = data[key]
|
|
122
125
|
|
|
123
126
|
if human_readable:
|
|
124
|
-
info['size'] = utils.format_size(
|
|
127
|
+
info['size'] = utils.format_size(data['size'])
|
|
125
128
|
|
|
126
129
|
# format the tags if they are there
|
|
127
|
-
info['tags'] = format_columns.ListColumn(
|
|
130
|
+
info['tags'] = format_columns.ListColumn(data.get('tags') or [])
|
|
128
131
|
|
|
129
132
|
# add properties back into the dictionary as a top-level key
|
|
130
133
|
if properties:
|
|
@@ -884,6 +887,8 @@ class ListImage(command.Lister):
|
|
|
884
887
|
kwargs['visibility'] = parsed_args.visibility
|
|
885
888
|
if parsed_args.limit:
|
|
886
889
|
kwargs['limit'] = parsed_args.limit
|
|
890
|
+
if parsed_args.max_items is not None:
|
|
891
|
+
kwargs['max_items'] = parsed_args.max_items
|
|
887
892
|
if parsed_args.marker:
|
|
888
893
|
kwargs['marker'] = image_client.find_image(
|
|
889
894
|
parsed_args.marker,
|
|
@@ -1358,6 +1363,7 @@ class SetImage(command.Command):
|
|
|
1358
1363
|
# our own membership
|
|
1359
1364
|
if not project_id:
|
|
1360
1365
|
project_id = self.app.client_manager.auth_ref.project_id
|
|
1366
|
+
assert project_id is not None, 'this should not happen'
|
|
1361
1367
|
image_client.update_member(
|
|
1362
1368
|
image=image.id,
|
|
1363
1369
|
member=project_id,
|
|
@@ -20,6 +20,7 @@ from collections.abc import Iterable, Sequence
|
|
|
20
20
|
import logging
|
|
21
21
|
from typing import Any
|
|
22
22
|
|
|
23
|
+
from openstack.image.v2 import metadef_namespace as _metadef_namespace
|
|
23
24
|
from osc_lib.cli import format_columns
|
|
24
25
|
from osc_lib import exceptions
|
|
25
26
|
from osc_lib import utils
|
|
@@ -34,7 +35,9 @@ _formatters = {
|
|
|
34
35
|
LOG = logging.getLogger(__name__)
|
|
35
36
|
|
|
36
37
|
|
|
37
|
-
def _format_namespace(
|
|
38
|
+
def _format_namespace(
|
|
39
|
+
namespace: _metadef_namespace.MetadefNamespace,
|
|
40
|
+
) -> dict[str, Any]:
|
|
38
41
|
info = {}
|
|
39
42
|
|
|
40
43
|
fields_to_show = [
|
|
@@ -50,18 +53,16 @@ def _format_namespace(namespace: Any) -> dict[str, Any]:
|
|
|
50
53
|
'visibility',
|
|
51
54
|
]
|
|
52
55
|
|
|
53
|
-
|
|
56
|
+
data = namespace.to_dict(ignore_none=True, original_names=True)
|
|
54
57
|
|
|
55
58
|
# split out the usual key and the properties which are top-level
|
|
56
|
-
for key in
|
|
59
|
+
for key in data:
|
|
57
60
|
if key in fields_to_show:
|
|
58
|
-
info[key] =
|
|
61
|
+
info[key] = data.get(key)
|
|
59
62
|
elif key == "resource_type_associations":
|
|
60
|
-
info[key] = [
|
|
61
|
-
resource_type['name'] for resource_type in namespace.get(key)
|
|
62
|
-
]
|
|
63
|
+
info[key] = [resource_type['name'] for resource_type in data[key]]
|
|
63
64
|
elif key == 'properties':
|
|
64
|
-
info['properties'] = list(
|
|
65
|
+
info['properties'] = list(data[key].keys())
|
|
65
66
|
|
|
66
67
|
return info
|
|
67
68
|
|
|
@@ -358,7 +359,7 @@ class ShowMetadefNamespace(command.ShowOne):
|
|
|
358
359
|
class UnsetMetadefNamespace(command.Command):
|
|
359
360
|
_description = _("Unset metadef namespace tags")
|
|
360
361
|
|
|
361
|
-
def get_parser(self, prog_name):
|
|
362
|
+
def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
|
|
362
363
|
parser = super().get_parser(prog_name)
|
|
363
364
|
parser.add_argument(
|
|
364
365
|
"namespace",
|
|
@@ -385,7 +386,7 @@ class UnsetMetadefNamespace(command.Command):
|
|
|
385
386
|
)
|
|
386
387
|
return parser
|
|
387
388
|
|
|
388
|
-
def take_action(self, parsed_args):
|
|
389
|
+
def take_action(self, parsed_args: argparse.Namespace) -> None:
|
|
389
390
|
image_client = self.app.client_manager.image
|
|
390
391
|
|
|
391
392
|
namespace = image_client.get_metadef_namespace(parsed_args.namespace)
|
|
@@ -20,6 +20,7 @@ from collections.abc import Iterable, Sequence
|
|
|
20
20
|
import logging
|
|
21
21
|
from typing import Any
|
|
22
22
|
|
|
23
|
+
from openstack.image.v2 import metadef_object as _metadef_object
|
|
23
24
|
from osc_lib import exceptions
|
|
24
25
|
from osc_lib import utils
|
|
25
26
|
|
|
@@ -30,7 +31,9 @@ from openstackclient.i18n import _
|
|
|
30
31
|
LOG = logging.getLogger(__name__)
|
|
31
32
|
|
|
32
33
|
|
|
33
|
-
def _format_object(
|
|
34
|
+
def _format_object(
|
|
35
|
+
md_object: _metadef_object.MetadefObject,
|
|
36
|
+
) -> tuple[tuple[str, ...], Iterable[Any]]:
|
|
34
37
|
fields_to_show = (
|
|
35
38
|
'created_at',
|
|
36
39
|
'description',
|
|
@@ -43,10 +46,7 @@ def _format_object(md_object: Any) -> tuple[tuple[str, ...], Any]:
|
|
|
43
46
|
|
|
44
47
|
return (
|
|
45
48
|
fields_to_show,
|
|
46
|
-
utils.get_item_properties(
|
|
47
|
-
md_object,
|
|
48
|
-
fields_to_show,
|
|
49
|
-
),
|
|
49
|
+
utils.get_item_properties(md_object, fields_to_show),
|
|
50
50
|
)
|
|
51
51
|
|
|
52
52
|
|
|
@@ -18,6 +18,7 @@ import json
|
|
|
18
18
|
import logging
|
|
19
19
|
from typing import Any
|
|
20
20
|
|
|
21
|
+
from openstack.image.v2 import metadef_property as _metadef_property
|
|
21
22
|
from osc_lib import exceptions
|
|
22
23
|
from osc_lib import utils
|
|
23
24
|
|
|
@@ -28,10 +29,12 @@ from openstackclient.i18n import _
|
|
|
28
29
|
LOG = logging.getLogger(__name__)
|
|
29
30
|
|
|
30
31
|
|
|
31
|
-
def _format_property(
|
|
32
|
-
prop
|
|
32
|
+
def _format_property(
|
|
33
|
+
prop: _metadef_property.MetadefProperty,
|
|
34
|
+
) -> dict[str, Any]:
|
|
35
|
+
data = prop.to_dict(ignore_none=True, original_names=True)
|
|
33
36
|
return {
|
|
34
|
-
key:
|
|
37
|
+
key: data[key]
|
|
35
38
|
for key in [
|
|
36
39
|
'namespace_name',
|
|
37
40
|
'name',
|
|
@@ -53,7 +56,7 @@ def _format_property(prop: Any) -> dict[str, Any]:
|
|
|
53
56
|
'max_items',
|
|
54
57
|
'allow_additional_items',
|
|
55
58
|
]
|
|
56
|
-
if key in
|
|
59
|
+
if key in data
|
|
57
60
|
}
|
|
58
61
|
|
|
59
62
|
|
openstackclient/image/v2/task.py
CHANGED
|
@@ -14,18 +14,16 @@ import argparse
|
|
|
14
14
|
from collections.abc import Iterable, Sequence
|
|
15
15
|
from typing import Any
|
|
16
16
|
|
|
17
|
+
from openstack.image.v2 import task as _task
|
|
17
18
|
from osc_lib.cli import format_columns
|
|
18
19
|
from osc_lib import utils
|
|
19
20
|
|
|
20
21
|
from openstackclient import command
|
|
22
|
+
from openstackclient.common import pagination
|
|
21
23
|
from openstackclient.i18n import _
|
|
22
24
|
|
|
23
|
-
_formatters = {
|
|
24
|
-
'tags': format_columns.ListColumn,
|
|
25
|
-
}
|
|
26
25
|
|
|
27
|
-
|
|
28
|
-
def _format_task(task: Any) -> dict[str, Any]:
|
|
26
|
+
def _format_task(task: _task.Task) -> dict[str, Any]:
|
|
29
27
|
"""Format an task to make it more consistent with OSC operations."""
|
|
30
28
|
|
|
31
29
|
info = {}
|
|
@@ -117,22 +115,7 @@ class ListTask(command.Lister):
|
|
|
117
115
|
'by comma)'
|
|
118
116
|
),
|
|
119
117
|
)
|
|
120
|
-
|
|
121
|
-
'--limit',
|
|
122
|
-
metavar='<num-tasks>',
|
|
123
|
-
type=int,
|
|
124
|
-
help=_('Maximum number of tasks to display.'),
|
|
125
|
-
)
|
|
126
|
-
parser.add_argument(
|
|
127
|
-
'--marker',
|
|
128
|
-
metavar='<task>',
|
|
129
|
-
help=_(
|
|
130
|
-
'The last task of the previous page. '
|
|
131
|
-
'Display list of tasks after marker. '
|
|
132
|
-
'Display all tasks if not specified. '
|
|
133
|
-
'(name or ID)'
|
|
134
|
-
),
|
|
135
|
-
)
|
|
118
|
+
pagination.add_marker_pagination_option_to_parser(parser)
|
|
136
119
|
parser.add_argument(
|
|
137
120
|
'--type',
|
|
138
121
|
metavar='<type>',
|
|
@@ -182,7 +165,13 @@ class ListTask(command.Lister):
|
|
|
182
165
|
return (
|
|
183
166
|
column_headers,
|
|
184
167
|
(
|
|
185
|
-
utils.get_item_properties(
|
|
168
|
+
utils.get_item_properties(
|
|
169
|
+
s,
|
|
170
|
+
columns,
|
|
171
|
+
formatters={
|
|
172
|
+
'tags': format_columns.ListColumn,
|
|
173
|
+
},
|
|
174
|
+
)
|
|
186
175
|
for s in data
|
|
187
176
|
),
|
|
188
177
|
)
|
openstackclient/network/utils.py
CHANGED
|
@@ -9,9 +9,7 @@
|
|
|
9
9
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
10
10
|
# License for the specific language governing permissions and limitations
|
|
11
11
|
# under the License.
|
|
12
|
-
#
|
|
13
12
|
|
|
14
|
-
from collections.abc import Iterable, Sequence
|
|
15
13
|
from typing import Any, cast
|
|
16
14
|
|
|
17
15
|
from osc_lib import exceptions
|
|
@@ -19,37 +17,6 @@ from osc_lib import exceptions
|
|
|
19
17
|
from openstackclient.i18n import _
|
|
20
18
|
|
|
21
19
|
|
|
22
|
-
# Transform compute security group rule for display.
|
|
23
|
-
def transform_compute_security_group_rule(
|
|
24
|
-
sg_rule: dict[str, Any],
|
|
25
|
-
) -> dict[str, Any]:
|
|
26
|
-
info = {}
|
|
27
|
-
info.update(sg_rule)
|
|
28
|
-
from_port = info.pop('from_port')
|
|
29
|
-
to_port = info.pop('to_port')
|
|
30
|
-
if isinstance(from_port, int) and isinstance(to_port, int):
|
|
31
|
-
port_range = {'port_range': f"{from_port}:{to_port}"}
|
|
32
|
-
elif from_port is None and to_port is None:
|
|
33
|
-
port_range = {'port_range': ""}
|
|
34
|
-
else:
|
|
35
|
-
port_range = {'port_range': f"{from_port}:{to_port}"}
|
|
36
|
-
info.update(port_range)
|
|
37
|
-
if 'cidr' in info['ip_range']:
|
|
38
|
-
info['ip_range'] = info['ip_range']['cidr']
|
|
39
|
-
else:
|
|
40
|
-
info['ip_range'] = ''
|
|
41
|
-
if info['ip_protocol'] is None:
|
|
42
|
-
info['ip_protocol'] = ''
|
|
43
|
-
elif info['ip_protocol'].lower() == 'icmp':
|
|
44
|
-
info['port_range'] = ''
|
|
45
|
-
group = info.pop('group')
|
|
46
|
-
if 'name' in group:
|
|
47
|
-
info['remote_security_group'] = group['name']
|
|
48
|
-
else:
|
|
49
|
-
info['remote_security_group'] = ''
|
|
50
|
-
return info
|
|
51
|
-
|
|
52
|
-
|
|
53
20
|
def str2bool(strbool: str | None) -> bool | None:
|
|
54
21
|
if strbool is None:
|
|
55
22
|
return None
|
|
@@ -88,14 +55,6 @@ def str2dict(strdict: str) -> dict[str, str]:
|
|
|
88
55
|
return result
|
|
89
56
|
|
|
90
57
|
|
|
91
|
-
def format_security_group_rule_show(
|
|
92
|
-
obj: dict[str, Any],
|
|
93
|
-
) -> tuple[Sequence[str], Iterable[Any]]:
|
|
94
|
-
data = transform_compute_security_group_rule(obj)
|
|
95
|
-
col_headers, col_data = zip(*sorted(data.items()))
|
|
96
|
-
return col_headers, col_data
|
|
97
|
-
|
|
98
|
-
|
|
99
58
|
def format_network_port_range(rule: dict[str, Any]) -> str:
|
|
100
59
|
# Display port range or ICMP type and code. For example:
|
|
101
60
|
# - ICMP type: 'type=3'
|
|
@@ -19,10 +19,12 @@ from collections.abc import Iterable, Sequence
|
|
|
19
19
|
from typing import Any
|
|
20
20
|
|
|
21
21
|
import netaddr
|
|
22
|
+
from openstack.network.v2 import address_group as _address_group
|
|
22
23
|
from osc_lib import exceptions
|
|
23
24
|
from osc_lib import utils
|
|
24
25
|
|
|
25
26
|
from openstackclient import command
|
|
27
|
+
from openstackclient.common import pagination
|
|
26
28
|
from openstackclient.i18n import _
|
|
27
29
|
from openstackclient.identity import common as identity_common
|
|
28
30
|
from openstackclient.network import common
|
|
@@ -30,7 +32,9 @@ from openstackclient.network import common
|
|
|
30
32
|
LOG = logging.getLogger(__name__)
|
|
31
33
|
|
|
32
34
|
|
|
33
|
-
def _get_columns(
|
|
35
|
+
def _get_columns(
|
|
36
|
+
item: _address_group.AddressGroup,
|
|
37
|
+
) -> tuple[tuple[str, ...], tuple[str, ...]]:
|
|
34
38
|
hidden_columns = ['location', 'tenant_id']
|
|
35
39
|
return utils.get_osc_show_columns_for_sdk_resource(
|
|
36
40
|
item, {}, hidden_columns
|
|
@@ -169,6 +173,7 @@ class ListAddressGroup(command.Lister):
|
|
|
169
173
|
),
|
|
170
174
|
)
|
|
171
175
|
identity_common.add_project_domain_option_to_parser(parser)
|
|
176
|
+
pagination.add_marker_pagination_option_to_parser(parser)
|
|
172
177
|
|
|
173
178
|
return parser
|
|
174
179
|
|
|
@@ -201,6 +206,13 @@ class ListAddressGroup(command.Lister):
|
|
|
201
206
|
parsed_args.project_domain,
|
|
202
207
|
).id
|
|
203
208
|
attrs['project_id'] = project_id
|
|
209
|
+
if parsed_args.marker is not None:
|
|
210
|
+
attrs['marker'] = parsed_args.marker
|
|
211
|
+
if parsed_args.limit is not None:
|
|
212
|
+
attrs['limit'] = parsed_args.limit
|
|
213
|
+
if parsed_args.max_items is not None:
|
|
214
|
+
attrs['max_items'] = parsed_args.max_items
|
|
215
|
+
|
|
204
216
|
data = client.address_groups(**attrs)
|
|
205
217
|
|
|
206
218
|
return (
|
|
@@ -18,10 +18,12 @@ import logging
|
|
|
18
18
|
from collections.abc import Iterable, Sequence
|
|
19
19
|
from typing import Any
|
|
20
20
|
|
|
21
|
+
from openstack.network.v2 import address_scope as _address_scope
|
|
21
22
|
from osc_lib import exceptions
|
|
22
23
|
from osc_lib import utils
|
|
23
24
|
|
|
24
25
|
from openstackclient import command
|
|
26
|
+
from openstackclient.common import pagination
|
|
25
27
|
from openstackclient.i18n import _
|
|
26
28
|
from openstackclient.identity import common as identity_common
|
|
27
29
|
from openstackclient.network import common
|
|
@@ -29,7 +31,9 @@ from openstackclient.network import common
|
|
|
29
31
|
LOG = logging.getLogger(__name__)
|
|
30
32
|
|
|
31
33
|
|
|
32
|
-
def _get_columns(
|
|
34
|
+
def _get_columns(
|
|
35
|
+
item: _address_scope.AddressScope,
|
|
36
|
+
) -> tuple[tuple[str, ...], tuple[str, ...]]:
|
|
33
37
|
column_map = {
|
|
34
38
|
'is_shared': 'shared',
|
|
35
39
|
}
|
|
@@ -61,8 +65,6 @@ def _get_attrs(
|
|
|
61
65
|
return attrs
|
|
62
66
|
|
|
63
67
|
|
|
64
|
-
# TODO(rtheis): Use the SDK resource mapped attribute names once the
|
|
65
|
-
# OSC minimum requirements include SDK 1.0.
|
|
66
68
|
class CreateAddressScope(command.ShowOne, common.NeutronCommandWithExtraArgs):
|
|
67
69
|
_description = _("Create a new Address Scope")
|
|
68
70
|
|
|
@@ -156,8 +158,6 @@ class DeleteAddressScope(command.Command):
|
|
|
156
158
|
raise exceptions.CommandError(msg)
|
|
157
159
|
|
|
158
160
|
|
|
159
|
-
# TODO(yanxing'an): Use the SDK resource mapped attribute names once the
|
|
160
|
-
# OSC minimum requirements include SDK 1.0.
|
|
161
161
|
class ListAddressScope(command.Lister):
|
|
162
162
|
_description = _("List address scopes")
|
|
163
163
|
|
|
@@ -189,7 +189,7 @@ class ListAddressScope(command.Lister):
|
|
|
189
189
|
),
|
|
190
190
|
)
|
|
191
191
|
identity_common.add_project_domain_option_to_parser(parser)
|
|
192
|
-
|
|
192
|
+
pagination.add_marker_pagination_option_to_parser(parser)
|
|
193
193
|
shared_group = parser.add_mutually_exclusive_group()
|
|
194
194
|
shared_group.add_argument(
|
|
195
195
|
'--share',
|
|
@@ -201,6 +201,7 @@ class ListAddressScope(command.Lister):
|
|
|
201
201
|
action='store_true',
|
|
202
202
|
help=_("List only address scopes not shared between projects"),
|
|
203
203
|
)
|
|
204
|
+
|
|
204
205
|
return parser
|
|
205
206
|
|
|
206
207
|
def take_action(
|
|
@@ -238,6 +239,12 @@ class ListAddressScope(command.Lister):
|
|
|
238
239
|
parsed_args.project_domain,
|
|
239
240
|
).id
|
|
240
241
|
attrs['project_id'] = project_id
|
|
242
|
+
if parsed_args.marker is not None:
|
|
243
|
+
attrs['marker'] = parsed_args.marker
|
|
244
|
+
if parsed_args.limit is not None:
|
|
245
|
+
attrs['limit'] = parsed_args.limit
|
|
246
|
+
if parsed_args.max_items is not None:
|
|
247
|
+
attrs['max_items'] = parsed_args.max_items
|
|
241
248
|
data = client.address_scopes(**attrs)
|
|
242
249
|
|
|
243
250
|
return (
|
|
@@ -253,8 +260,6 @@ class ListAddressScope(command.Lister):
|
|
|
253
260
|
)
|
|
254
261
|
|
|
255
262
|
|
|
256
|
-
# TODO(rtheis): Use the SDK resource mapped attribute names once the
|
|
257
|
-
# OSC minimum requirements include SDK 1.0.
|
|
258
263
|
class SetAddressScope(common.NeutronCommandWithExtraArgs):
|
|
259
264
|
_description = _("Set address scope properties")
|
|
260
265
|
|