python-openstackclient 8.2.0__py3-none-any.whl → 9.0.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/object_store_v1.py +4 -1
- 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 +5 -3
- openstackclient/common/project_cleanup.py +10 -8
- openstackclient/common/quota.py +54 -23
- 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 +1 -1
- 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 +78 -29
- 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 +33 -1
- 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 +4 -2
- 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 +30 -10
- 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 +10 -4
- 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 +40 -41
- 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 +86 -85
- openstackclient/identity/v3/mapping.py +1 -1
- openstackclient/identity/v3/policy.py +1 -1
- openstackclient/identity/v3/project.py +191 -115
- openstackclient/identity/v3/region.py +1 -1
- openstackclient/identity/v3/registered_limit.py +97 -109
- openstackclient/identity/v3/role.py +20 -39
- 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 +1 -11
- 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 +19 -16
- openstackclient/image/v2/cache.py +1 -1
- openstackclient/image/v2/image.py +16 -12
- openstackclient/image/v2/info.py +1 -1
- openstackclient/image/v2/metadef_namespaces.py +1 -1
- openstackclient/image/v2/metadef_objects.py +1 -1
- openstackclient/image/v2/metadef_properties.py +3 -2
- 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 +22 -20
- openstackclient/network/v2/router.py +19 -8
- openstackclient/network/v2/security_group.py +10 -6
- openstackclient/network/v2/security_group_rule.py +11 -5
- 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_catalog.py +42 -23
- openstackclient/tests/functional/identity/v3/test_limit.py +47 -0
- 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_metadef_objects.py +69 -0
- openstackclient/tests/functional/image/v2/test_metadef_resource_type.py +55 -0
- openstackclient/tests/functional/volume/v3/test_volume_snapshot.py +46 -132
- 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 +79 -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 +1 -3
- openstackclient/tests/unit/compute/v2/test_hypervisor_stats.py +1 -9
- openstackclient/tests/unit/compute/v2/test_server.py +370 -38
- 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 +3 -3
- openstackclient/tests/unit/identity/v3/test_domain.py +1 -1
- 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_limit.py +197 -145
- openstackclient/tests/unit/identity/v3/test_oauth.py +1 -1
- openstackclient/tests/unit/identity/v3/test_project.py +832 -513
- openstackclient/tests/unit/identity/v3/test_protocol.py +97 -88
- openstackclient/tests/unit/identity/v3/test_registered_limit.py +356 -221
- openstackclient/tests/unit/identity/v3/test_role.py +1 -82
- openstackclient/tests/unit/identity/v3/test_user.py +7 -51
- openstackclient/tests/unit/image/v2/test_image.py +116 -5
- openstackclient/tests/unit/network/test_common.py +9 -13
- 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 +11 -21
- 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 +75 -86
- openstackclient/tests/unit/network/v2/test_router.py +104 -126
- openstackclient/tests/unit/network/v2/test_security_group_network.py +19 -26
- openstackclient/tests/unit/network/v2/test_security_group_rule_network.py +17 -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_consistency_group.py +8 -2
- openstackclient/tests/unit/volume/v2/test_volume.py +7 -6
- openstackclient/tests/unit/volume/v2/test_volume_backup.py +3 -1
- openstackclient/tests/unit/volume/v3/test_volume.py +38 -12
- 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 +9 -9
- openstackclient/volume/v2/consistency_group_snapshot.py +3 -3
- openstackclient/volume/v2/qos_specs.py +3 -3
- openstackclient/volume/v2/service.py +1 -1
- openstackclient/volume/v2/volume.py +14 -7
- openstackclient/volume/v2/volume_backend.py +1 -1
- openstackclient/volume/v2/volume_backup.py +7 -5
- openstackclient/volume/v2/volume_host.py +1 -2
- openstackclient/volume/v2/volume_snapshot.py +4 -4
- openstackclient/volume/v2/volume_transfer_request.py +3 -3
- openstackclient/volume/v2/volume_type.py +16 -11
- 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 +1 -1
- openstackclient/volume/v3/volume.py +16 -9
- openstackclient/volume/v3/volume_attachment.py +6 -5
- openstackclient/volume/v3/volume_backup.py +20 -5
- openstackclient/volume/v3/volume_group.py +1 -1
- 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 +4 -4
- openstackclient/volume/v3/volume_transfer_request.py +3 -3
- openstackclient/volume/v3/volume_type.py +20 -14
- {python_openstackclient-8.2.0.dist-info → python_openstackclient-9.0.0.dist-info}/METADATA +15 -13
- {python_openstackclient-8.2.0.dist-info → python_openstackclient-9.0.0.dist-info}/RECORD +231 -219
- {python_openstackclient-8.2.0.dist-info → python_openstackclient-9.0.0.dist-info}/WHEEL +1 -1
- {python_openstackclient-8.2.0.dist-info → python_openstackclient-9.0.0.dist-info}/entry_points.txt +15 -0
- {python_openstackclient-8.2.0.dist-info → python_openstackclient-9.0.0.dist-info/licenses}/AUTHORS +15 -0
- python_openstackclient-9.0.0.dist-info/pbr.json +1 -0
- openstackclient/tests/unit/common/test_logs.py +0 -221
- python_openstackclient-8.2.0.dist-info/pbr.json +0 -1
- {python_openstackclient-8.2.0.dist-info → python_openstackclient-9.0.0.dist-info/licenses}/LICENSE +0 -0
- {python_openstackclient-8.2.0.dist-info → python_openstackclient-9.0.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
2
|
+
# not use this file except in compliance with the License. You may obtain
|
|
3
|
+
# a copy of the License at
|
|
4
|
+
#
|
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
#
|
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
9
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
10
|
+
# License for the specific language governing permissions and limitations
|
|
11
|
+
# under the License.
|
|
12
|
+
|
|
13
|
+
import logging
|
|
14
|
+
|
|
15
|
+
from osc_lib.cli import identity as identity_utils
|
|
16
|
+
from osc_lib import exceptions
|
|
17
|
+
from osc_lib import utils as osc_utils
|
|
18
|
+
from osc_lib.utils import columns as column_util
|
|
19
|
+
|
|
20
|
+
from openstackclient import command
|
|
21
|
+
from openstackclient.i18n import _
|
|
22
|
+
from openstackclient.identity import common
|
|
23
|
+
from openstackclient.network.v2 import port as osc_port
|
|
24
|
+
from openstackclient.network.v2.taas import tap_service
|
|
25
|
+
|
|
26
|
+
LOG = logging.getLogger(__name__)
|
|
27
|
+
|
|
28
|
+
TAP_MIRROR = 'tap_mirror'
|
|
29
|
+
TAP_MIRRORS = f'{TAP_MIRROR}s'
|
|
30
|
+
|
|
31
|
+
_attr_map = [
|
|
32
|
+
('id', 'ID', column_util.LIST_BOTH),
|
|
33
|
+
('tenant_id', 'Tenant', column_util.LIST_LONG_ONLY),
|
|
34
|
+
('name', 'Name', column_util.LIST_BOTH),
|
|
35
|
+
('port_id', 'Port', column_util.LIST_BOTH),
|
|
36
|
+
('directions', 'Directions', column_util.LIST_LONG_ONLY),
|
|
37
|
+
('remote_ip', 'Remote IP', column_util.LIST_BOTH),
|
|
38
|
+
('mirror_type', 'Mirror Type', column_util.LIST_LONG_ONLY),
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _get_columns(item):
|
|
43
|
+
column_map: dict[str, str] = {}
|
|
44
|
+
hidden_columns = ['location', 'tenant_id']
|
|
45
|
+
return osc_utils.get_osc_show_columns_for_sdk_resource(
|
|
46
|
+
item, column_map, hidden_columns
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class CreateTapMirror(command.ShowOne):
|
|
51
|
+
_description = _("Create a new tap mirror.")
|
|
52
|
+
|
|
53
|
+
def get_parser(self, prog_name):
|
|
54
|
+
parser = super().get_parser(prog_name)
|
|
55
|
+
identity_utils.add_project_owner_option_to_parser(parser)
|
|
56
|
+
tap_service._add_updatable_args(parser)
|
|
57
|
+
parser.add_argument(
|
|
58
|
+
'--port',
|
|
59
|
+
dest='port_id',
|
|
60
|
+
required=True,
|
|
61
|
+
metavar="PORT",
|
|
62
|
+
help=_('Port (name or ID) to which the Tap Mirror is connected.'),
|
|
63
|
+
)
|
|
64
|
+
parser.add_argument(
|
|
65
|
+
'--directions',
|
|
66
|
+
dest='directions',
|
|
67
|
+
action=osc_port.JSONKeyValueAction,
|
|
68
|
+
required=True,
|
|
69
|
+
help=_(
|
|
70
|
+
'Dictionary of direction and tunnel_id. Valid directions are: '
|
|
71
|
+
'IN and OUT.'
|
|
72
|
+
),
|
|
73
|
+
)
|
|
74
|
+
parser.add_argument(
|
|
75
|
+
'--remote-ip',
|
|
76
|
+
dest='remote_ip',
|
|
77
|
+
required=True,
|
|
78
|
+
help=_(
|
|
79
|
+
'Remote IP address for the tap mirror (remote end of the '
|
|
80
|
+
'GRE or ERSPAN v1 tunnel).'
|
|
81
|
+
),
|
|
82
|
+
)
|
|
83
|
+
parser.add_argument(
|
|
84
|
+
'--mirror-type',
|
|
85
|
+
dest='mirror_type',
|
|
86
|
+
required=True,
|
|
87
|
+
help=_('Mirror type. Valid values are: gre and erspanv1.'),
|
|
88
|
+
)
|
|
89
|
+
return parser
|
|
90
|
+
|
|
91
|
+
def take_action(self, parsed_args):
|
|
92
|
+
client = self.app.client_manager.network
|
|
93
|
+
attrs = {}
|
|
94
|
+
if parsed_args.name is not None:
|
|
95
|
+
attrs['name'] = parsed_args.name
|
|
96
|
+
if parsed_args.description is not None:
|
|
97
|
+
attrs['description'] = parsed_args.description
|
|
98
|
+
if parsed_args.port_id is not None:
|
|
99
|
+
port_id = client.find_port(
|
|
100
|
+
parsed_args.port_id, ignore_missing=False
|
|
101
|
+
).id
|
|
102
|
+
attrs['port_id'] = port_id
|
|
103
|
+
if parsed_args.directions is not None:
|
|
104
|
+
attrs['directions'] = parsed_args.directions
|
|
105
|
+
if parsed_args.remote_ip is not None:
|
|
106
|
+
attrs['remote_ip'] = parsed_args.remote_ip
|
|
107
|
+
if parsed_args.mirror_type is not None:
|
|
108
|
+
attrs['mirror_type'] = parsed_args.mirror_type
|
|
109
|
+
if 'project' in parsed_args and parsed_args.project is not None:
|
|
110
|
+
attrs['project_id'] = common.find_project(
|
|
111
|
+
self.app.client_manager.identity,
|
|
112
|
+
parsed_args.project,
|
|
113
|
+
parsed_args.project_domain,
|
|
114
|
+
).id
|
|
115
|
+
obj = client.create_tap_mirror(**attrs)
|
|
116
|
+
display_columns, columns = tap_service._get_columns(obj)
|
|
117
|
+
data = osc_utils.get_dict_properties(obj, columns)
|
|
118
|
+
return display_columns, data
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class ListTapMirror(command.Lister):
|
|
122
|
+
_description = _("List tap mirrors.")
|
|
123
|
+
|
|
124
|
+
def get_parser(self, prog_name):
|
|
125
|
+
parser = super().get_parser(prog_name)
|
|
126
|
+
identity_utils.add_project_owner_option_to_parser(parser)
|
|
127
|
+
|
|
128
|
+
return parser
|
|
129
|
+
|
|
130
|
+
def take_action(self, parsed_args):
|
|
131
|
+
client = self.app.client_manager.network
|
|
132
|
+
params = {}
|
|
133
|
+
if parsed_args.project is not None:
|
|
134
|
+
params['project_id'] = common.find_project(
|
|
135
|
+
self.app.client_manager.identity,
|
|
136
|
+
parsed_args.project,
|
|
137
|
+
parsed_args.project_domain,
|
|
138
|
+
).id
|
|
139
|
+
objs = client.tap_mirrors(retrieve_all=True, params=params)
|
|
140
|
+
headers, columns = column_util.get_column_definitions(
|
|
141
|
+
_attr_map, long_listing=True
|
|
142
|
+
)
|
|
143
|
+
return (
|
|
144
|
+
headers,
|
|
145
|
+
(osc_utils.get_dict_properties(s, columns) for s in objs),
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class ShowTapMirror(command.ShowOne):
|
|
150
|
+
_description = _("Show tap mirror details.")
|
|
151
|
+
|
|
152
|
+
def get_parser(self, prog_name):
|
|
153
|
+
parser = super().get_parser(prog_name)
|
|
154
|
+
parser.add_argument(
|
|
155
|
+
TAP_MIRROR,
|
|
156
|
+
metavar=f"<{TAP_MIRROR}>",
|
|
157
|
+
help=_("Tap mirror to display (name or ID)."),
|
|
158
|
+
)
|
|
159
|
+
return parser
|
|
160
|
+
|
|
161
|
+
def take_action(self, parsed_args):
|
|
162
|
+
client = self.app.client_manager.network
|
|
163
|
+
id = client.find_tap_mirror(
|
|
164
|
+
parsed_args.tap_mirror, ignore_missing=False
|
|
165
|
+
).id
|
|
166
|
+
obj = client.get_tap_mirror(id)
|
|
167
|
+
display_columns, columns = tap_service._get_columns(obj)
|
|
168
|
+
data = osc_utils.get_dict_properties(obj, columns)
|
|
169
|
+
return display_columns, data
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class DeleteTapMirror(command.Command):
|
|
173
|
+
_description = _("Delete a tap mirror.")
|
|
174
|
+
|
|
175
|
+
def get_parser(self, prog_name):
|
|
176
|
+
parser = super().get_parser(prog_name)
|
|
177
|
+
parser.add_argument(
|
|
178
|
+
TAP_MIRROR,
|
|
179
|
+
metavar=f"<{TAP_MIRROR}>",
|
|
180
|
+
nargs="+",
|
|
181
|
+
help=_("Tap mirror to delete (name or ID)."),
|
|
182
|
+
)
|
|
183
|
+
return parser
|
|
184
|
+
|
|
185
|
+
def take_action(self, parsed_args):
|
|
186
|
+
client = self.app.client_manager.network
|
|
187
|
+
fails = 0
|
|
188
|
+
for id_or_name in parsed_args.tap_mirror:
|
|
189
|
+
try:
|
|
190
|
+
id = client.find_tap_mirror(
|
|
191
|
+
id_or_name, ignore_missing=False
|
|
192
|
+
).id
|
|
193
|
+
|
|
194
|
+
client.delete_tap_mirror(id)
|
|
195
|
+
LOG.warning("Tap Mirror %(id)s deleted", {'id': id})
|
|
196
|
+
except Exception as e:
|
|
197
|
+
fails += 1
|
|
198
|
+
LOG.error(
|
|
199
|
+
"Failed to delete Tap Mirror with name or ID "
|
|
200
|
+
"'%(id_or_name)s': %(e)s",
|
|
201
|
+
{'id_or_name': id_or_name, 'e': e},
|
|
202
|
+
)
|
|
203
|
+
if fails > 0:
|
|
204
|
+
msg = _("Failed to delete %(fails)s of %(total)s Tap Mirror.") % {
|
|
205
|
+
'fails': fails,
|
|
206
|
+
'total': len(parsed_args.tap_mirror),
|
|
207
|
+
}
|
|
208
|
+
raise exceptions.CommandError(msg)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
class UpdateTapMirror(command.ShowOne):
|
|
212
|
+
_description = _("Update a tap mirror.")
|
|
213
|
+
|
|
214
|
+
def get_parser(self, prog_name):
|
|
215
|
+
parser = super().get_parser(prog_name)
|
|
216
|
+
parser.add_argument(
|
|
217
|
+
TAP_MIRROR,
|
|
218
|
+
metavar=f"<{TAP_MIRROR}>",
|
|
219
|
+
help=_("Tap mirror to modify (name or ID)."),
|
|
220
|
+
)
|
|
221
|
+
tap_service._add_updatable_args(parser)
|
|
222
|
+
return parser
|
|
223
|
+
|
|
224
|
+
def take_action(self, parsed_args):
|
|
225
|
+
client = self.app.client_manager.network
|
|
226
|
+
original_t_s = client.find_tap_mirror(
|
|
227
|
+
parsed_args.tap_mirror, ignore_missing=False
|
|
228
|
+
).id
|
|
229
|
+
attrs = {}
|
|
230
|
+
if parsed_args.name is not None:
|
|
231
|
+
attrs['name'] = parsed_args.name
|
|
232
|
+
if parsed_args.description is not None:
|
|
233
|
+
attrs['description'] = parsed_args.description
|
|
234
|
+
obj = client.update_tap_mirror(original_t_s, **attrs)
|
|
235
|
+
display_columns, columns = tap_service._get_columns(obj)
|
|
236
|
+
data = osc_utils.get_dict_properties(obj, columns)
|
|
237
|
+
return display_columns, data
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# All Rights Reserved 2020
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
4
|
+
# not use this file except in compliance with the License. You may obtain
|
|
5
|
+
# a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
11
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
12
|
+
# License for the specific language governing permissions and limitations
|
|
13
|
+
# under the License.
|
|
14
|
+
|
|
15
|
+
import logging
|
|
16
|
+
|
|
17
|
+
from osc_lib.cli import identity as identity_utils
|
|
18
|
+
from osc_lib import exceptions
|
|
19
|
+
from osc_lib import utils as osc_utils
|
|
20
|
+
from osc_lib.utils import columns as column_util
|
|
21
|
+
|
|
22
|
+
from openstackclient import command
|
|
23
|
+
from openstackclient.i18n import _
|
|
24
|
+
from openstackclient.identity import common
|
|
25
|
+
|
|
26
|
+
LOG = logging.getLogger(__name__)
|
|
27
|
+
|
|
28
|
+
TAP_SERVICE = 'tap_service'
|
|
29
|
+
TAP_SERVICES = f'{TAP_SERVICE}s'
|
|
30
|
+
|
|
31
|
+
_attr_map = [
|
|
32
|
+
('id', 'ID', column_util.LIST_BOTH),
|
|
33
|
+
('tenant_id', 'Tenant', column_util.LIST_LONG_ONLY),
|
|
34
|
+
('name', 'Name', column_util.LIST_BOTH),
|
|
35
|
+
('port_id', 'Port', column_util.LIST_BOTH),
|
|
36
|
+
('status', 'Status', column_util.LIST_BOTH),
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _add_updatable_args(parser):
|
|
41
|
+
parser.add_argument('--name', help=_('Name of the tap service.'))
|
|
42
|
+
parser.add_argument(
|
|
43
|
+
'--description', help=_('Description of the tap service.')
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _get_columns(item):
|
|
48
|
+
column_map: dict[str, str] = {}
|
|
49
|
+
hidden_columns = ['location', 'tenant_id']
|
|
50
|
+
return osc_utils.get_osc_show_columns_for_sdk_resource(
|
|
51
|
+
item, column_map, hidden_columns
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class CreateTapService(command.ShowOne):
|
|
56
|
+
_description = _("Create a new tap service.")
|
|
57
|
+
|
|
58
|
+
def get_parser(self, prog_name):
|
|
59
|
+
parser = super().get_parser(prog_name)
|
|
60
|
+
identity_utils.add_project_owner_option_to_parser(parser)
|
|
61
|
+
_add_updatable_args(parser)
|
|
62
|
+
parser.add_argument(
|
|
63
|
+
'--port',
|
|
64
|
+
dest='port_id',
|
|
65
|
+
required=True,
|
|
66
|
+
metavar="PORT",
|
|
67
|
+
help=_('Port (name or ID) to connect to the tap service.'),
|
|
68
|
+
)
|
|
69
|
+
return parser
|
|
70
|
+
|
|
71
|
+
def take_action(self, parsed_args):
|
|
72
|
+
client = self.app.client_manager.network
|
|
73
|
+
attrs = {}
|
|
74
|
+
if parsed_args.name is not None:
|
|
75
|
+
attrs['name'] = parsed_args.name
|
|
76
|
+
if parsed_args.description is not None:
|
|
77
|
+
attrs['description'] = parsed_args.description
|
|
78
|
+
if parsed_args.port_id is not None:
|
|
79
|
+
port_id = client.find_port(
|
|
80
|
+
parsed_args.port_id, ignore_missing=False
|
|
81
|
+
).id
|
|
82
|
+
attrs['port_id'] = port_id
|
|
83
|
+
if 'project' in parsed_args and parsed_args.project is not None:
|
|
84
|
+
attrs['project_id'] = common.find_project(
|
|
85
|
+
self.app.client_manager.identity,
|
|
86
|
+
parsed_args.project,
|
|
87
|
+
parsed_args.project_domain,
|
|
88
|
+
).id
|
|
89
|
+
obj = client.create_tap_service(**attrs)
|
|
90
|
+
display_columns, columns = _get_columns(obj)
|
|
91
|
+
data = osc_utils.get_dict_properties(obj, columns)
|
|
92
|
+
return display_columns, data
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class ListTapService(command.Lister):
|
|
96
|
+
_description = _("List tap services.")
|
|
97
|
+
|
|
98
|
+
def get_parser(self, prog_name):
|
|
99
|
+
parser = super().get_parser(prog_name)
|
|
100
|
+
identity_utils.add_project_owner_option_to_parser(parser)
|
|
101
|
+
|
|
102
|
+
return parser
|
|
103
|
+
|
|
104
|
+
def take_action(self, parsed_args):
|
|
105
|
+
client = self.app.client_manager.network
|
|
106
|
+
params = {}
|
|
107
|
+
if parsed_args.project is not None:
|
|
108
|
+
params['project_id'] = common.find_project(
|
|
109
|
+
self.app.client_manager.identity,
|
|
110
|
+
parsed_args.project,
|
|
111
|
+
parsed_args.project_domain,
|
|
112
|
+
).id
|
|
113
|
+
objs = client.tap_services(retrieve_all=True, params=params)
|
|
114
|
+
headers, columns = column_util.get_column_definitions(
|
|
115
|
+
_attr_map, long_listing=True
|
|
116
|
+
)
|
|
117
|
+
return (
|
|
118
|
+
headers,
|
|
119
|
+
(osc_utils.get_dict_properties(s, columns) for s in objs),
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class ShowTapService(command.ShowOne):
|
|
124
|
+
_description = _("Show tap service details.")
|
|
125
|
+
|
|
126
|
+
def get_parser(self, prog_name):
|
|
127
|
+
parser = super().get_parser(prog_name)
|
|
128
|
+
parser.add_argument(
|
|
129
|
+
TAP_SERVICE,
|
|
130
|
+
metavar=f"<{TAP_SERVICE}>",
|
|
131
|
+
help=_("Tap service to display (name or ID)."),
|
|
132
|
+
)
|
|
133
|
+
return parser
|
|
134
|
+
|
|
135
|
+
def take_action(self, parsed_args):
|
|
136
|
+
client = self.app.client_manager.network
|
|
137
|
+
id = client.find_tap_service(
|
|
138
|
+
parsed_args.tap_service, ignore_missing=False
|
|
139
|
+
).id
|
|
140
|
+
obj = client.get_tap_service(id)
|
|
141
|
+
display_columns, columns = _get_columns(obj)
|
|
142
|
+
data = osc_utils.get_dict_properties(obj, columns)
|
|
143
|
+
return display_columns, data
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class DeleteTapService(command.Command):
|
|
147
|
+
_description = _("Delete a tap service.")
|
|
148
|
+
|
|
149
|
+
def get_parser(self, prog_name):
|
|
150
|
+
parser = super().get_parser(prog_name)
|
|
151
|
+
parser.add_argument(
|
|
152
|
+
TAP_SERVICE,
|
|
153
|
+
metavar=f"<{TAP_SERVICE}>",
|
|
154
|
+
nargs="+",
|
|
155
|
+
help=_("Tap service to delete (name or ID)."),
|
|
156
|
+
)
|
|
157
|
+
return parser
|
|
158
|
+
|
|
159
|
+
def take_action(self, parsed_args):
|
|
160
|
+
client = self.app.client_manager.network
|
|
161
|
+
fails = 0
|
|
162
|
+
for id_or_name in parsed_args.tap_service:
|
|
163
|
+
try:
|
|
164
|
+
id = client.find_tap_service(
|
|
165
|
+
id_or_name, ignore_missing=False
|
|
166
|
+
).id
|
|
167
|
+
|
|
168
|
+
client.delete_tap_service(id)
|
|
169
|
+
LOG.warning("Tap service %(id)s deleted", {'id': id})
|
|
170
|
+
except Exception as e:
|
|
171
|
+
fails += 1
|
|
172
|
+
LOG.error(
|
|
173
|
+
"Failed to delete tap service with name or ID "
|
|
174
|
+
"'%(id_or_name)s': %(e)s",
|
|
175
|
+
{'id_or_name': id_or_name, 'e': e},
|
|
176
|
+
)
|
|
177
|
+
if fails > 0:
|
|
178
|
+
msg = _("Failed to delete %(fails)s of %(total)s tap service.") % {
|
|
179
|
+
'fails': fails,
|
|
180
|
+
'total': len(parsed_args.tap_service),
|
|
181
|
+
}
|
|
182
|
+
raise exceptions.CommandError(msg)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
class UpdateTapService(command.ShowOne):
|
|
186
|
+
_description = _("Update a tap service.")
|
|
187
|
+
|
|
188
|
+
def get_parser(self, prog_name):
|
|
189
|
+
parser = super().get_parser(prog_name)
|
|
190
|
+
parser.add_argument(
|
|
191
|
+
TAP_SERVICE,
|
|
192
|
+
metavar=f"<{TAP_SERVICE}>",
|
|
193
|
+
help=_("Tap service to modify (name or ID)."),
|
|
194
|
+
)
|
|
195
|
+
_add_updatable_args(parser)
|
|
196
|
+
return parser
|
|
197
|
+
|
|
198
|
+
def take_action(self, parsed_args):
|
|
199
|
+
client = self.app.client_manager.network
|
|
200
|
+
original_t_s = client.find_tap_service(
|
|
201
|
+
parsed_args.tap_service, ignore_missing=False
|
|
202
|
+
).id
|
|
203
|
+
attrs = {}
|
|
204
|
+
if parsed_args.name is not None:
|
|
205
|
+
attrs['name'] = parsed_args.name
|
|
206
|
+
if parsed_args.description is not None:
|
|
207
|
+
attrs['description'] = parsed_args.description
|
|
208
|
+
obj = client.update_tap_service(original_t_s, **attrs)
|
|
209
|
+
display_columns, columns = _get_columns(obj)
|
|
210
|
+
data = osc_utils.get_dict_properties(obj, columns)
|
|
211
|
+
return display_columns, data
|
|
@@ -19,9 +19,9 @@ import logging
|
|
|
19
19
|
|
|
20
20
|
from osc_lib.cli import format_columns
|
|
21
21
|
from osc_lib.cli import parseractions
|
|
22
|
-
from osc_lib.command import command
|
|
23
22
|
from osc_lib import utils
|
|
24
23
|
|
|
24
|
+
from openstackclient import command
|
|
25
25
|
from openstackclient.common import pagination
|
|
26
26
|
from openstackclient.i18n import _
|
|
27
27
|
|
|
@@ -19,10 +19,10 @@ import logging
|
|
|
19
19
|
|
|
20
20
|
from osc_lib.cli import format_columns
|
|
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.common import pagination
|
|
27
27
|
from openstackclient.i18n import _
|
|
28
28
|
|
openstackclient/shell.py
CHANGED
|
@@ -26,16 +26,27 @@ from osc_lib import shell
|
|
|
26
26
|
import openstackclient
|
|
27
27
|
from openstackclient.common import clientmanager
|
|
28
28
|
|
|
29
|
-
|
|
30
29
|
DEFAULT_DOMAIN = 'default'
|
|
30
|
+
# list of modules that were originally out-of-tree and are now in
|
|
31
|
+
# core OSC
|
|
32
|
+
IGNORED_MODULES = (
|
|
33
|
+
'neutron_taas.taas_client.osc',
|
|
34
|
+
'neutronclient.osc.v2.taas',
|
|
35
|
+
)
|
|
31
36
|
|
|
32
37
|
|
|
33
38
|
class OpenStackShell(shell.OpenStackShell):
|
|
39
|
+
client_manager: clientmanager.ClientManager
|
|
40
|
+
|
|
34
41
|
def __init__(self):
|
|
42
|
+
command_manager = commandmanager.CommandManager(
|
|
43
|
+
'openstack.cli', ignored_modules=IGNORED_MODULES
|
|
44
|
+
)
|
|
45
|
+
|
|
35
46
|
super().__init__(
|
|
36
47
|
description=__doc__.strip(),
|
|
37
48
|
version=openstackclient.__version__,
|
|
38
|
-
command_manager=
|
|
49
|
+
command_manager=command_manager,
|
|
39
50
|
deferred_help=True,
|
|
40
51
|
)
|
|
41
52
|
|
|
@@ -48,8 +59,10 @@ class OpenStackShell(shell.OpenStackShell):
|
|
|
48
59
|
# about them
|
|
49
60
|
warnings.filterwarnings('ignore', module='openstack')
|
|
50
61
|
|
|
51
|
-
def build_option_parser(self, description, version):
|
|
52
|
-
parser = super().build_option_parser(
|
|
62
|
+
def build_option_parser(self, description, version, argparse_kwargs=None):
|
|
63
|
+
parser = super().build_option_parser(
|
|
64
|
+
description, version, argparse_kwargs
|
|
65
|
+
)
|
|
53
66
|
parser = clientmanager.build_plugin_option_parser(parser)
|
|
54
67
|
parser = auth.build_auth_plugins_option_parser(parser)
|
|
55
68
|
return parser
|
|
@@ -65,10 +78,7 @@ class OpenStackShell(shell.OpenStackShell):
|
|
|
65
78
|
self._auth_type = 'password'
|
|
66
79
|
|
|
67
80
|
def _load_plugins(self):
|
|
68
|
-
"""Load plugins via stevedore
|
|
69
|
-
|
|
70
|
-
osc-lib has no opinion on what plugins should be loaded
|
|
71
|
-
"""
|
|
81
|
+
"""Load plugins via stevedore."""
|
|
72
82
|
# Loop through extensions to get API versions
|
|
73
83
|
for mod in clientmanager.PLUGIN_MODULES:
|
|
74
84
|
default_version = getattr(mod, 'DEFAULT_API_VERSION', None)
|
|
@@ -10,35 +10,54 @@
|
|
|
10
10
|
# License for the specific language governing permissions and limitations
|
|
11
11
|
# under the License.
|
|
12
12
|
|
|
13
|
+
|
|
13
14
|
from openstackclient.tests.functional.identity.v3 import common
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
class CatalogTests(common.IdentityTests):
|
|
17
|
-
|
|
18
|
+
"""Functional tests for catalog commands"""
|
|
19
|
+
|
|
20
|
+
def test_catalog(self):
|
|
21
|
+
"""Test catalog list and show functionality"""
|
|
22
|
+
# Create a test service for isolated testing
|
|
23
|
+
_dummy_service_name = self._create_dummy_service(add_clean_up=True)
|
|
24
|
+
|
|
25
|
+
# list catalogs
|
|
18
26
|
raw_output = self.openstack('catalog list')
|
|
19
27
|
items = self.parse_listing(raw_output)
|
|
20
28
|
self.assert_table_structure(items, ['Name', 'Type', 'Endpoints'])
|
|
21
29
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
| | admin: http://localhost:35357/v2.0 |
|
|
35
|
-
| | |
|
|
36
|
-
| id | e1e68b5ba21a43a39ff1cf58e736c3aa |
|
|
37
|
-
| name | keystone |
|
|
38
|
-
| type | identity |
|
|
39
|
-
+-----------+----------------------------------------+
|
|
40
|
-
"""
|
|
41
|
-
raw_output = self.openstack('catalog show {}'.format('identity'))
|
|
30
|
+
# Verify created service appears in catalog
|
|
31
|
+
service_names = [
|
|
32
|
+
item.get('Name') for item in items if item.get('Name')
|
|
33
|
+
]
|
|
34
|
+
self.assertIn(
|
|
35
|
+
_dummy_service_name,
|
|
36
|
+
service_names,
|
|
37
|
+
"Created dummy service should be present in catalog",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
# show service (by name)
|
|
41
|
+
raw_output = self.openstack(f'catalog show {_dummy_service_name}')
|
|
42
42
|
items = self.parse_show(raw_output)
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
self.assert_show_fields(items, ['endpoints', 'name', 'type', 'id'])
|
|
44
|
+
|
|
45
|
+
# Extract the type from the dummy service
|
|
46
|
+
_dummy_service_type = next(
|
|
47
|
+
(item['type'] for item in items if 'type' in item), None
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# show service (by type)
|
|
51
|
+
raw_output = self.openstack(f'catalog show {_dummy_service_type}')
|
|
52
|
+
items = self.parse_show(raw_output)
|
|
53
|
+
self.assert_show_fields(items, ['endpoints', 'name', 'type', 'id'])
|
|
54
|
+
|
|
55
|
+
# show service (non-existent)
|
|
56
|
+
result = self.openstack(
|
|
57
|
+
'catalog show nonexistent-service-xyz', fail_ok=True
|
|
58
|
+
)
|
|
59
|
+
self.assertEqual(
|
|
60
|
+
'',
|
|
61
|
+
result.strip(),
|
|
62
|
+
"Non-existent service should return empty result",
|
|
63
|
+
)
|
|
@@ -100,6 +100,53 @@ class LimitTestCase(common.IdentityTests):
|
|
|
100
100
|
self.assert_show_fields(items, self.LIMIT_FIELDS)
|
|
101
101
|
registered_limit_id = self._create_dummy_registered_limit()
|
|
102
102
|
|
|
103
|
+
def test_limit_create_with_project_domain(self):
|
|
104
|
+
registered_limit_id = self._create_dummy_registered_limit()
|
|
105
|
+
raw_output = self.openstack(
|
|
106
|
+
f'registered limit show {registered_limit_id}',
|
|
107
|
+
cloud=SYSTEM_CLOUD,
|
|
108
|
+
)
|
|
109
|
+
items = self.parse_show(raw_output)
|
|
110
|
+
service_id = self._extract_value_from_items('service_id', items)
|
|
111
|
+
resource_name = self._extract_value_from_items('resource_name', items)
|
|
112
|
+
|
|
113
|
+
raw_output = self.openstack(f'service show {service_id}')
|
|
114
|
+
items = self.parse_show(raw_output)
|
|
115
|
+
service_name = self._extract_value_from_items('name', items)
|
|
116
|
+
|
|
117
|
+
project_name = self._create_dummy_project()
|
|
118
|
+
raw_output = self.openstack(
|
|
119
|
+
f'project show {project_name}',
|
|
120
|
+
cloud=SYSTEM_CLOUD,
|
|
121
|
+
)
|
|
122
|
+
items = self.parse_show(raw_output)
|
|
123
|
+
domain_id = self._extract_value_from_items('domain_id', items)
|
|
124
|
+
|
|
125
|
+
params = {
|
|
126
|
+
'project_name': project_name,
|
|
127
|
+
'project_domain': domain_id,
|
|
128
|
+
'service_name': service_name,
|
|
129
|
+
'resource_name': resource_name,
|
|
130
|
+
'resource_limit': 15,
|
|
131
|
+
}
|
|
132
|
+
raw_output = self.openstack(
|
|
133
|
+
'limit create'
|
|
134
|
+
' --project {project_name}'
|
|
135
|
+
' --project-domain {project_domain}'
|
|
136
|
+
' --service {service_name}'
|
|
137
|
+
' --resource-limit {resource_limit}'
|
|
138
|
+
' {resource_name}'.format(**params),
|
|
139
|
+
cloud=SYSTEM_CLOUD,
|
|
140
|
+
)
|
|
141
|
+
items = self.parse_show(raw_output)
|
|
142
|
+
limit_id = self._extract_value_from_items('id', items)
|
|
143
|
+
self.addCleanup(
|
|
144
|
+
self.openstack, f'limit delete {limit_id}', cloud=SYSTEM_CLOUD
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
self.assert_show_fields(items, self.LIMIT_FIELDS)
|
|
148
|
+
registered_limit_id = self._create_dummy_registered_limit()
|
|
149
|
+
|
|
103
150
|
def test_limit_create_with_service_id(self):
|
|
104
151
|
self._create_dummy_limit()
|
|
105
152
|
|