summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.pre-commit-config.yaml23
-rw-r--r--.zuul.yaml2
-rw-r--r--bindep.txt2
-rw-r--r--debian/changelog10
-rw-r--r--debian/control4
-rw-r--r--debian/patches/Fix_openstack_quota_show_without_cinder.patch106
-rw-r--r--debian/patches/add-missing-backup_id-field.patch42
-rw-r--r--debian/patches/series2
-rw-r--r--doc/requirements.txt2
-rwxr-xr-xexamples/common.py2
-rw-r--r--hacking/checks.py179
-rw-r--r--openstackclient/api/object_store_v1.py5
-rw-r--r--openstackclient/command.py27
-rw-r--r--openstackclient/common/availability_zone.py2
-rw-r--r--openstackclient/common/clientmanager.py80
-rw-r--r--openstackclient/common/configuration.py2
-rw-r--r--openstackclient/common/extension.py2
-rw-r--r--openstackclient/common/limits.py2
-rw-r--r--openstackclient/common/module.py8
-rw-r--r--openstackclient/common/project_cleanup.py18
-rw-r--r--openstackclient/common/quota.py77
-rw-r--r--openstackclient/common/versions.py3
-rw-r--r--openstackclient/compute/v2/agent.py2
-rw-r--r--openstackclient/compute/v2/aggregate.py11
-rw-r--r--openstackclient/compute/v2/console.py8
-rw-r--r--openstackclient/compute/v2/console_connection.py2
-rw-r--r--openstackclient/compute/v2/flavor.py2
-rw-r--r--openstackclient/compute/v2/host.py2
-rw-r--r--openstackclient/compute/v2/hypervisor.py2
-rw-r--r--openstackclient/compute/v2/hypervisor_stats.py2
-rw-r--r--openstackclient/compute/v2/keypair.py2
-rw-r--r--openstackclient/compute/v2/server.py107
-rw-r--r--openstackclient/compute/v2/server_backup.py2
-rw-r--r--openstackclient/compute/v2/server_event.py2
-rw-r--r--openstackclient/compute/v2/server_group.py6
-rw-r--r--openstackclient/compute/v2/server_image.py2
-rw-r--r--openstackclient/compute/v2/server_migration.py2
-rw-r--r--openstackclient/compute/v2/server_volume.py2
-rw-r--r--openstackclient/compute/v2/service.py2
-rw-r--r--openstackclient/compute/v2/usage.py10
-rw-r--r--openstackclient/identity/common.py34
-rw-r--r--openstackclient/identity/v2_0/catalog.py5
-rw-r--r--openstackclient/identity/v2_0/ec2creds.py2
-rw-r--r--openstackclient/identity/v2_0/endpoint.py2
-rw-r--r--openstackclient/identity/v2_0/project.py24
-rw-r--r--openstackclient/identity/v2_0/role.py2
-rw-r--r--openstackclient/identity/v2_0/role_assignment.py6
-rw-r--r--openstackclient/identity/v2_0/service.py6
-rw-r--r--openstackclient/identity/v2_0/token.py2
-rw-r--r--openstackclient/identity/v2_0/user.py4
-rw-r--r--openstackclient/identity/v3/access_rule.py20
-rw-r--r--openstackclient/identity/v3/application_credential.py40
-rw-r--r--openstackclient/identity/v3/catalog.py6
-rw-r--r--openstackclient/identity/v3/consumer.py2
-rw-r--r--openstackclient/identity/v3/credential.py2
-rw-r--r--openstackclient/identity/v3/domain.py14
-rw-r--r--openstackclient/identity/v3/ec2creds.py2
-rw-r--r--openstackclient/identity/v3/endpoint.py45
-rw-r--r--openstackclient/identity/v3/endpoint_group.py2
-rw-r--r--openstackclient/identity/v3/federation_protocol.py81
-rw-r--r--openstackclient/identity/v3/group.py16
-rw-r--r--openstackclient/identity/v3/identity_provider.py22
-rw-r--r--openstackclient/identity/v3/implied_role.py2
-rw-r--r--openstackclient/identity/v3/limit.py171
-rw-r--r--openstackclient/identity/v3/mapping.py2
-rw-r--r--openstackclient/identity/v3/policy.py2
-rw-r--r--openstackclient/identity/v3/project.py306
-rw-r--r--openstackclient/identity/v3/region.py2
-rw-r--r--openstackclient/identity/v3/registered_limit.py206
-rw-r--r--openstackclient/identity/v3/role.py59
-rw-r--r--openstackclient/identity/v3/role_assignment.py35
-rw-r--r--openstackclient/identity/v3/service.py2
-rw-r--r--openstackclient/identity/v3/service_provider.py2
-rw-r--r--openstackclient/identity/v3/tag.py12
-rw-r--r--openstackclient/identity/v3/token.py5
-rw-r--r--openstackclient/identity/v3/trust.py6
-rw-r--r--openstackclient/identity/v3/unscoped_saml.py2
-rw-r--r--openstackclient/identity/v3/user.py35
-rw-r--r--openstackclient/image/v1/image.py35
-rw-r--r--openstackclient/image/v2/cache.py2
-rw-r--r--openstackclient/image/v2/image.py28
-rw-r--r--openstackclient/image/v2/info.py2
-rw-r--r--openstackclient/image/v2/metadef_namespaces.py2
-rw-r--r--openstackclient/image/v2/metadef_objects.py2
-rw-r--r--openstackclient/image/v2/metadef_properties.py5
-rw-r--r--openstackclient/image/v2/metadef_resource_type_association.py2
-rw-r--r--openstackclient/image/v2/metadef_resource_types.py2
-rw-r--r--openstackclient/image/v2/task.py2
-rw-r--r--openstackclient/network/common.py19
-rw-r--r--openstackclient/network/v2/address_group.py7
-rw-r--r--openstackclient/network/v2/address_scope.py14
-rw-r--r--openstackclient/network/v2/default_security_group_rule.py17
-rw-r--r--openstackclient/network/v2/floating_ip.py25
-rw-r--r--openstackclient/network/v2/floating_ip_port_forwarding.py15
-rw-r--r--openstackclient/network/v2/ip_availability.py11
-rw-r--r--openstackclient/network/v2/l3_conntrack_helper.py15
-rw-r--r--openstackclient/network/v2/local_ip.py20
-rw-r--r--openstackclient/network/v2/local_ip_association.py11
-rw-r--r--openstackclient/network/v2/ndp_proxy.py19
-rw-r--r--openstackclient/network/v2/network.py49
-rw-r--r--openstackclient/network/v2/network_agent.py10
-rw-r--r--openstackclient/network/v2/network_auto_allocated_topology.py2
-rw-r--r--openstackclient/network/v2/network_flavor.py2
-rw-r--r--openstackclient/network/v2/network_flavor_profile.py2
-rw-r--r--openstackclient/network/v2/network_meter.py2
-rw-r--r--openstackclient/network/v2/network_meter_rule.py2
-rw-r--r--openstackclient/network/v2/network_qos_policy.py12
-rw-r--r--openstackclient/network/v2/network_qos_rule.py2
-rw-r--r--openstackclient/network/v2/network_qos_rule_type.py2
-rw-r--r--openstackclient/network/v2/network_rbac.py13
-rw-r--r--openstackclient/network/v2/network_segment.py4
-rw-r--r--openstackclient/network/v2/network_segment_range.py19
-rw-r--r--openstackclient/network/v2/network_service_provider.py2
-rw-r--r--openstackclient/network/v2/network_trunk.py107
-rw-r--r--openstackclient/network/v2/port.py42
-rw-r--r--openstackclient/network/v2/router.py27
-rw-r--r--openstackclient/network/v2/security_group.py16
-rw-r--r--openstackclient/network/v2/security_group_rule.py16
-rw-r--r--openstackclient/network/v2/subnet.py35
-rw-r--r--openstackclient/network/v2/subnet_pool.py20
-rw-r--r--openstackclient/network/v2/taas/__init__.py0
-rw-r--r--openstackclient/network/v2/taas/tap_flow.py245
-rw-r--r--openstackclient/network/v2/taas/tap_mirror.py237
-rw-r--r--openstackclient/network/v2/taas/tap_service.py211
-rw-r--r--openstackclient/object/v1/account.py2
-rw-r--r--openstackclient/object/v1/container.py2
-rw-r--r--openstackclient/object/v1/object.py2
-rw-r--r--openstackclient/shell.py26
-rw-r--r--openstackclient/tests/functional/identity/v3/test_catalog.py65
-rw-r--r--openstackclient/tests/functional/identity/v3/test_limit.py47
-rw-r--r--openstackclient/tests/functional/identity/v3/test_role_assignment.py174
-rw-r--r--openstackclient/tests/functional/image/v2/test_cache.py54
-rw-r--r--openstackclient/tests/functional/image/v2/test_metadef_objects.py69
-rw-r--r--openstackclient/tests/functional/image/v2/test_metadef_resource_type.py55
-rw-r--r--openstackclient/tests/functional/volume/v3/test_volume_snapshot.py178
-rw-r--r--openstackclient/tests/unit/common/test_command.py2
-rw-r--r--openstackclient/tests/unit/common/test_extension.py5
-rw-r--r--openstackclient/tests/unit/common/test_logs.py221
-rw-r--r--openstackclient/tests/unit/common/test_module.py21
-rw-r--r--openstackclient/tests/unit/common/test_quota.py79
-rw-r--r--openstackclient/tests/unit/compute/v2/test_aggregate.py8
-rw-r--r--openstackclient/tests/unit/compute/v2/test_console.py5
-rw-r--r--openstackclient/tests/unit/compute/v2/test_flavor.py4
-rw-r--r--openstackclient/tests/unit/compute/v2/test_hypervisor_stats.py10
-rw-r--r--openstackclient/tests/unit/compute/v2/test_server.py408
-rw-r--r--openstackclient/tests/unit/compute/v2/test_server_backup.py4
-rw-r--r--openstackclient/tests/unit/compute/v2/test_service.py4
-rw-r--r--openstackclient/tests/unit/fakes.py169
-rw-r--r--openstackclient/tests/unit/identity/test_common.py100
-rw-r--r--openstackclient/tests/unit/identity/v2_0/test_project.py8
-rw-r--r--openstackclient/tests/unit/identity/v3/fakes.py12
-rw-r--r--openstackclient/tests/unit/identity/v3/test_application_credential.py6
-rw-r--r--openstackclient/tests/unit/identity/v3/test_domain.py2
-rw-r--r--openstackclient/tests/unit/identity/v3/test_endpoint.py2
-rw-r--r--openstackclient/tests/unit/identity/v3/test_group.py6
-rw-r--r--openstackclient/tests/unit/identity/v3/test_identity_provider.py20
-rw-r--r--openstackclient/tests/unit/identity/v3/test_limit.py342
-rw-r--r--openstackclient/tests/unit/identity/v3/test_oauth.py2
-rw-r--r--openstackclient/tests/unit/identity/v3/test_project.py1345
-rw-r--r--openstackclient/tests/unit/identity/v3/test_protocol.py185
-rw-r--r--openstackclient/tests/unit/identity/v3/test_registered_limit.py577
-rw-r--r--openstackclient/tests/unit/identity/v3/test_role.py83
-rw-r--r--openstackclient/tests/unit/identity/v3/test_user.py58
-rw-r--r--openstackclient/tests/unit/image/v2/test_image.py121
-rw-r--r--openstackclient/tests/unit/network/test_common.py22
-rw-r--r--openstackclient/tests/unit/network/v2/taas/__init__.py0
-rw-r--r--openstackclient/tests/unit/network/v2/taas/test_osc_tap_flow.py276
-rw-r--r--openstackclient/tests/unit/network/v2/taas/test_osc_tap_mirror.py288
-rw-r--r--openstackclient/tests/unit/network/v2/taas/test_osc_tap_service.py271
-rw-r--r--openstackclient/tests/unit/network/v2/test_address_group.py41
-rw-r--r--openstackclient/tests/unit/network/v2/test_address_scope.py25
-rw-r--r--openstackclient/tests/unit/network/v2/test_default_security_group_rule.py87
-rw-r--r--openstackclient/tests/unit/network/v2/test_floating_ip_network.py48
-rw-r--r--openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py39
-rw-r--r--openstackclient/tests/unit/network/v2/test_ip_availability.py14
-rw-r--r--openstackclient/tests/unit/network/v2/test_l3_conntrack_helper.py21
-rw-r--r--openstackclient/tests/unit/network/v2/test_local_ip.py35
-rw-r--r--openstackclient/tests/unit/network/v2/test_local_ip_association.py31
-rw-r--r--openstackclient/tests/unit/network/v2/test_ndp_proxy.py32
-rw-r--r--openstackclient/tests/unit/network/v2/test_network.py78
-rw-r--r--openstackclient/tests/unit/network/v2/test_network_agent.py33
-rw-r--r--openstackclient/tests/unit/network/v2/test_network_auto_allocated_topology.py13
-rw-r--r--openstackclient/tests/unit/network/v2/test_network_flavor.py40
-rw-r--r--openstackclient/tests/unit/network/v2/test_network_flavor_profile.py31
-rw-r--r--openstackclient/tests/unit/network/v2/test_network_meter.py24
-rw-r--r--openstackclient/tests/unit/network/v2/test_network_meter_rule.py30
-rw-r--r--openstackclient/tests/unit/network/v2/test_network_qos_policy.py20
-rw-r--r--openstackclient/tests/unit/network/v2/test_network_qos_rule.py98
-rw-r--r--openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py9
-rw-r--r--openstackclient/tests/unit/network/v2/test_network_rbac.py57
-rw-r--r--openstackclient/tests/unit/network/v2/test_network_segment.py42
-rw-r--r--openstackclient/tests/unit/network/v2/test_network_segment_range.py39
-rw-r--r--openstackclient/tests/unit/network/v2/test_network_service_provider.py5
-rw-r--r--openstackclient/tests/unit/network/v2/test_network_trunk.py99
-rw-r--r--openstackclient/tests/unit/network/v2/test_port.py161
-rw-r--r--openstackclient/tests/unit/network/v2/test_router.py230
-rw-r--r--openstackclient/tests/unit/network/v2/test_security_group_network.py45
-rw-r--r--openstackclient/tests/unit/network/v2/test_security_group_rule_network.py35
-rw-r--r--openstackclient/tests/unit/network/v2/test_subnet.py81
-rw-r--r--openstackclient/tests/unit/network/v2/test_subnet_pool.py54
-rw-r--r--openstackclient/tests/unit/volume/test_find_resource.py17
-rw-r--r--openstackclient/tests/unit/volume/v2/test_consistency_group.py10
-rw-r--r--openstackclient/tests/unit/volume/v2/test_volume.py13
-rw-r--r--openstackclient/tests/unit/volume/v2/test_volume_backup.py4
-rw-r--r--openstackclient/tests/unit/volume/v3/test_volume.py50
-rw-r--r--openstackclient/tests/unit/volume/v3/test_volume_backup.py9
-rw-r--r--openstackclient/volume/client.py24
-rw-r--r--openstackclient/volume/v2/backup_record.py2
-rw-r--r--openstackclient/volume/v2/consistency_group.py18
-rw-r--r--openstackclient/volume/v2/consistency_group_snapshot.py6
-rw-r--r--openstackclient/volume/v2/qos_specs.py6
-rw-r--r--openstackclient/volume/v2/service.py2
-rw-r--r--openstackclient/volume/v2/volume.py21
-rw-r--r--openstackclient/volume/v2/volume_backend.py2
-rw-r--r--openstackclient/volume/v2/volume_backup.py12
-rw-r--r--openstackclient/volume/v2/volume_host.py3
-rw-r--r--openstackclient/volume/v2/volume_snapshot.py8
-rw-r--r--openstackclient/volume/v2/volume_transfer_request.py6
-rw-r--r--openstackclient/volume/v2/volume_type.py27
-rw-r--r--openstackclient/volume/v3/block_storage_cleanup.py2
-rw-r--r--openstackclient/volume/v3/block_storage_cluster.py2
-rw-r--r--openstackclient/volume/v3/block_storage_log_level.py2
-rw-r--r--openstackclient/volume/v3/block_storage_manage.py2
-rw-r--r--openstackclient/volume/v3/block_storage_resource_filter.py2
-rw-r--r--openstackclient/volume/v3/service.py2
-rw-r--r--openstackclient/volume/v3/volume.py25
-rw-r--r--openstackclient/volume/v3/volume_attachment.py11
-rw-r--r--openstackclient/volume/v3/volume_backup.py25
-rw-r--r--openstackclient/volume/v3/volume_group.py2
-rw-r--r--openstackclient/volume/v3/volume_group_snapshot.py2
-rw-r--r--openstackclient/volume/v3/volume_group_type.py2
-rw-r--r--openstackclient/volume/v3/volume_message.py2
-rw-r--r--openstackclient/volume/v3/volume_snapshot.py8
-rw-r--r--openstackclient/volume/v3/volume_transfer_request.py6
-rw-r--r--openstackclient/volume/v3/volume_type.py34
-rw-r--r--pyproject.toml30
-rw-r--r--releasenotes/notes/add-volume-backup-project-filter-6c09b2c8aba83341.yaml5
-rw-r--r--releasenotes/notes/bug-2126565-a119ac242d9ac795.yaml8
-rw-r--r--releasenotes/notes/bug-2137636-fix-quota-usage-display-2d8f07dccc21f79c.yaml5
-rw-r--r--releasenotes/notes/bug-2138903-f75c7348f22db195.yaml5
-rw-r--r--releasenotes/notes/fix-image-set-project-accept-owner-bug-2136795.yaml10
-rw-r--r--releasenotes/notes/fix-resize-server-args-required-2e9013bcbf207f6a.yaml8
-rw-r--r--releasenotes/notes/keystone-create-user-no-password-619bcddcd046dda8.yaml6
-rw-r--r--releasenotes/notes/limits-project-domain-option-84bfbb0e30e21b73.yaml5
-rw-r--r--releasenotes/notes/migrate-federation-protocol-to-sdk-43dc2b50fb277da6.yaml7
-rw-r--r--releasenotes/notes/migrate-limit-to-sdk-378037ec2b79e302.yaml9
-rw-r--r--releasenotes/notes/migrate-project-to-sdk-9201efd2804371de.yaml7
-rw-r--r--releasenotes/notes/migrate-registered-limit-to-sdk-36b6451e3a799a43.yaml10
-rw-r--r--releasenotes/notes/use-project-domain-for-parent-cb29ee3f5adeb647.yaml5
-rw-r--r--releasenotes/notes/volume-delete-cascade-384003efc8896096.yaml6
-rw-r--r--releasenotes/source/2024.1.rst2
-rw-r--r--releasenotes/source/2025.2.rst6
-rw-r--r--releasenotes/source/index.rst1
-rw-r--r--requirements.txt2
-rw-r--r--tox.ini132
255 files changed, 6930 insertions, 3935 deletions
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 09a9172..718c80f 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,13 +1,13 @@
---
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v5.0.0
+ rev: v6.0.0
hooks:
- id: trailing-whitespace
- id: mixed-line-ending
args: ['--fix', 'lf']
exclude: '.*\.(svg)$'
- - id: check-byte-order-marker
+ - id: fix-byte-order-marker
- id: check-executables-have-shebangs
- id: check-merge-conflict
- id: debug-statements
@@ -15,27 +15,14 @@ repos:
files: .*\.(yaml|yml)$
args: ['--unsafe']
- repo: https://github.com/astral-sh/ruff-pre-commit
- rev: v0.11.8
+ rev: v0.15.1
hooks:
- - id: ruff
+ - id: ruff-check
args: ['--fix', '--unsafe-fixes']
- id: ruff-format
- repo: https://opendev.org/openstack/hacking
- rev: 7.0.0
+ rev: 8.0.0
hooks:
- id: hacking
additional_dependencies: []
exclude: '^(doc|releasenotes)/.*$'
- - repo: https://github.com/pre-commit/mirrors-mypy
- rev: v1.15.0
- hooks:
- - id: mypy
- additional_dependencies:
- - types-requests
- # keep this in-sync with '[mypy] exclude' in 'setup.cfg'
- exclude: |
- (?x)(
- doc/.*
- | examples/.*
- | releasenotes/.*
- )
diff --git a/.zuul.yaml b/.zuul.yaml
index 74ca67d..d63ee7c 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -173,6 +173,8 @@
- release-notes-jobs-python3
check:
jobs:
+ - openstackclient-check-plugins:
+ voting: true
- osc-build-image:
voting: false
- osc-functional-devstack
diff --git a/bindep.txt b/bindep.txt
index 83ebf2d..8402431 100644
--- a/bindep.txt
+++ b/bindep.txt
@@ -8,4 +8,4 @@ libffi-dev [compile test platform:dpkg]
libssl-dev [compile test platform:dpkg]
python3-dev [compile test platform:dpkg]
python3-devel [compile test platform:rpm]
-libpcre3-dev [test platform:dpkg]
+libpcre2-dev [test platform:dpkg]
diff --git a/debian/changelog b/debian/changelog
index b49ae48..7a19b8e 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,13 @@
+python-openstackclient (9.0.0-1) experimental; urgency=medium
+
+ * New upstream release.
+ * Fixed (build-)depends for this release.
+ * Removed patches applied upstream:
+ - Fix_openstack_quota_show_without_cinder.patch
+ - add-missing-backup_id-field.patch
+
+ -- Thomas Goirand <zigo@debian.org> Fri, 27 Feb 2026 19:32:22 +0100
+
python-openstackclient (8.2.0-9) unstable; urgency=medium
* Correctly (build-)depends on python3-openstacksdk >= 4.7.2.
diff --git a/debian/control b/debian/control
index b828212..a09784a 100644
--- a/debian/control
+++ b/debian/control
@@ -17,7 +17,7 @@ Build-Depends-Indep:
python3-aodhclient <!nodoc>,
python3-barbicanclient <!nodoc>,
python3-cinderclient,
- python3-cliff,
+ python3-cliff (>= 4.13.0),
python3-cloudkittyclient <!nodoc>,
python3-coverage,
python3-cryptography,
@@ -90,7 +90,7 @@ Package: python3-openstackclient
Architecture: all
Depends:
python3-cinderclient,
- python3-cliff,
+ python3-cliff (>= 4.13.0),
python3-cryptography,
python3-glanceclient,
python3-iso8601,
diff --git a/debian/patches/Fix_openstack_quota_show_without_cinder.patch b/debian/patches/Fix_openstack_quota_show_without_cinder.patch
deleted file mode 100644
index 3e6eebf..0000000
--- a/debian/patches/Fix_openstack_quota_show_without_cinder.patch
+++ /dev/null
@@ -1,106 +0,0 @@
-Description: Fix openstack quota show without cinder
- Per this Debian bug [1], 'openstack quota show --default' fails when
- cinder is NOT installed. This is also true of other services.
- .
- [1] https://bugs.debian.org/1109288
-Author: Svein-Erik Skjelbred <svein-erik@skjelbred.com>
-Date: Mon, 29 Sep 2025 14:59:03 +0200
-Change-Id: I361da44b9f1d09ba3a454632d41e2110a3815395
-Signed-off-by: Svein-Erik Skjelbred <svein-erik@skjelbred.com>
-Signed-off-by: Thomas Goirand <zigo@debian.org>
-Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
-Forwarded: https://review.opendev.org/c/openstack/python-openstackclient/+/962838
-Bug-Debian: https://bugs.debian.org/1109288
-
-diff --git a/openstackclient/common/quota.py b/openstackclient/common/quota.py
-index f706a59..41c57e6 100644
---- a/openstackclient/common/quota.py
-+++ b/openstackclient/common/quota.py
-@@ -746,21 +746,32 @@
- # values if the project or class does not exist. This is expected
- # behavior. However, we have already checked for the presence of the
- # project above so it shouldn't be an issue.
-- if parsed_args.service in {'all', 'compute'}:
-+ if parsed_args.service == 'compute' or (
-+ parsed_args.service == 'all'
-+ and self.app.client_manager.is_compute_endpoint_enabled()
-+ ):
- compute_quota_info = get_compute_quotas(
- self.app,
- project,
- detail=parsed_args.usage,
- default=parsed_args.default,
- )
-- if parsed_args.service in {'all', 'volume'}:
-+
-+ if parsed_args.service == 'volume' or (
-+ parsed_args.service == 'all'
-+ and self.app.client_manager.is_volume_endpoint_enabled()
-+ ):
- volume_quota_info = get_volume_quotas(
- self.app,
- project,
- detail=parsed_args.usage,
- default=parsed_args.default,
- )
-- if parsed_args.service in {'all', 'network'}:
-+
-+ if parsed_args.service == 'network' or (
-+ parsed_args.service == 'all'
-+ and self.app.client_manager.is_network_endpoint_enabled()
-+ ):
- network_quota_info = get_network_quotas(
- self.app,
- project,
-@@ -906,12 +917,18 @@
- )
-
- # compute quotas
-- if parsed_args.service in {'all', 'compute'}:
-+ if parsed_args.service == 'compute' or (
-+ parsed_args.service == 'all'
-+ and self.app.client_manager.is_compute_endpoint_enabled()
-+ ):
- compute_client = self.app.client_manager.compute
- compute_client.revert_quota_set(project.id)
-
- # volume quotas
-- if parsed_args.service in {'all', 'volume'}:
-+ if parsed_args.service == 'volume' or (
-+ parsed_args.service == 'all'
-+ and self.app.client_manager.is_volume_endpoint_enabled()
-+ ):
- volume_client = self.app.client_manager.sdk_connection.volume
- volume_client.revert_quota_set(project.id)
-
-diff --git a/openstackclient/tests/unit/common/test_quota.py b/openstackclient/tests/unit/common/test_quota.py
-index 53df4da..a2418d0 100644
---- a/openstackclient/tests/unit/common/test_quota.py
-+++ b/openstackclient/tests/unit/common/test_quota.py
-@@ -1041,6 +1041,26 @@
- )
- self.assertNotCalled(self.network_client.get_quota_default)
-
-+ def test_quota_show__missing_services(self):
-+ self.app.client_manager.compute_endpoint_enabled = False
-+ self.app.client_manager.volume_endpoint_enabled = False
-+ self.app.client_manager.network_endpoint_enabled = False
-+
-+ arglist = [
-+ self.projects[0].name,
-+ ]
-+ verifylist = [
-+ ('service', 'all'),
-+ ('project', self.projects[0].name),
-+ ]
-+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-+
-+ self.cmd.take_action(parsed_args)
-+
-+ self.compute_client.get_quota_set.assert_not_called()
-+ self.volume_sdk_client.get_quota_set.assert_not_called()
-+ self.network_client.get_quota.assert_not_called()
-+
- def test_quota_show__with_compute(self):
- arglist = [
- '--compute',
diff --git a/debian/patches/add-missing-backup_id-field.patch b/debian/patches/add-missing-backup_id-field.patch
deleted file mode 100644
index 5efff0e..0000000
--- a/debian/patches/add-missing-backup_id-field.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-Description: Add missing backup_id field
-Author: Luan Utimura <luan.utimura@luizalabs.com>
-Bug-Debian: https://bugs.debian.org/1123450
-Origin: upstream, https://review.opendev.org/c/openstack/python-openstackclient/+/971255
-Last-Update: 2025-12-23
-
-Index: python-openstackclient/openstackclient/tests/unit/volume/v3/test_volume.py
-===================================================================
---- python-openstackclient.orig/openstackclient/tests/unit/volume/v3/test_volume.py
-+++ python-openstackclient/openstackclient/tests/unit/volume/v3/test_volume.py
-@@ -37,6 +37,7 @@ class TestVolumeCreate(volume_fakes.Test
- columns = (
- 'attachments',
- 'availability_zone',
-+ 'backup_id',
- 'bootable',
- 'cluster_name',
- 'consistencygroup_id',
-@@ -78,6 +79,7 @@ class TestVolumeCreate(volume_fakes.Test
- self.datalist = (
- self.volume.attachments,
- self.volume.availability_zone,
-+ self.volume.backup_id,
- self.volume.is_bootable,
- self.volume.cluster_name,
- self.volume.consistency_group_id,
-@@ -2011,6 +2013,7 @@ class TestVolumeShow(volume_fakes.TestVo
- self.columns = (
- 'attachments',
- 'availability_zone',
-+ 'backup_id',
- 'bootable',
- 'cluster_name',
- 'consistencygroup_id',
-@@ -2045,6 +2048,7 @@ class TestVolumeShow(volume_fakes.TestVo
- self.data = (
- self.volume.attachments,
- self.volume.availability_zone,
-+ self.volume.backup_id,
- self.volume.is_bootable,
- self.volume.cluster_name,
- self.volume.consistency_group_id,
diff --git a/debian/patches/series b/debian/patches/series
index 27d569e..bb74ab0 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,3 +1 @@
package-all-files.patch
-Fix_openstack_quota_show_without_cinder.patch
-add-missing-backup_id-field.patch
diff --git a/doc/requirements.txt b/doc/requirements.txt
index 79e3ded..05a9bfa 100644
--- a/doc/requirements.txt
+++ b/doc/requirements.txt
@@ -4,7 +4,7 @@ sphinx>=2.0.0,!=2.1.0 # BSD
sphinxcontrib-apidoc>=0.2.0 # BSD
# redirect tests in docs
-whereto>=0.4.0 # Apache-2.0
+whereto>=0.5.0 # Apache-2.0
# Install these to generate sphinx autodocs
aodhclient>=0.9.0 # Apache-2.0
diff --git a/examples/common.py b/examples/common.py
index 650139e..8213f4b 100755
--- a/examples/common.py
+++ b/examples/common.py
@@ -264,7 +264,7 @@ def main(opts, run):
if dump_stack_trace:
_logger.error(traceback.format_exc(e))
else:
- _logger.error('Exception raised: ' + str(e))
+ _logger.error('Exception raised: %s', e)
return 1
diff --git a/hacking/checks.py b/hacking/checks.py
new file mode 100644
index 0000000..0eb485e
--- /dev/null
+++ b/hacking/checks.py
@@ -0,0 +1,179 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import ast
+import os
+import re
+
+from hacking import core
+
+"""
+Guidelines for writing new hacking checks
+
+ - Use only for python-openstackclient specific tests. OpenStack general tests
+ should be submitted to the common 'hacking' module.
+ - Pick numbers in the range O4xx. Find the current test with the highest
+ allocated number and then pick the next value.
+"""
+
+
+@core.flake8ext
+def assert_no_oslo(logical_line):
+ """Check for use of oslo libraries.
+
+ O400
+ """
+ if re.match(r'(from|import) oslo_.*', logical_line):
+ yield (0, "0400: oslo libraries should not be used in SDK projects")
+
+
+@core.flake8ext
+def assert_no_duplicated_setup(logical_line, filename):
+ """Check for use of various unnecessary test duplications.
+
+ O401
+ """
+ if os.path.join('openstackclient', 'tests', 'unit') not in filename:
+ return
+
+ if re.match(r'self.app = .*\(self.app, self.namespace\)', logical_line):
+ yield (
+ 0,
+ 'O401: It is not necessary to create dummy Namespace objects',
+ )
+
+ if os.path.basename(filename) != 'fakes.py':
+ if re.match(
+ r'self.[a-z_]+_client = self.app.client_manager.*', logical_line
+ ):
+ yield (
+ 0,
+ "O401: Aliases for mocks of the service client are already "
+ "provided by the respective service's FakeClientMixin class",
+ )
+
+ if match := re.match(
+ r'self.app.client_manager.([a-z_]+) = mock.Mock', logical_line
+ ):
+ service = match.group(1)
+ if service == 'auth_ref':
+ return
+ yield (
+ 0,
+ f"O401: client_manager.{service} mocks are already provided "
+ f"by the {service} service's FakeClientMixin class",
+ )
+
+
+@core.flake8ext
+def assert_use_of_client_aliases(logical_line):
+ """Ensure we use $service_client instead of $sdk_connection.service.
+
+ O402
+ """
+ # we should expand the list of services as we drop legacy clients
+ if match := re.match(
+ r'self\.app\.client_manager\.sdk_connnection\.(compute|network|image)',
+ logical_line,
+ ):
+ service = match.group(1)
+ yield (0, f"0402: prefer {service}_client to sdk_connection.{service}")
+
+ if match := re.match(
+ r'(self\.app\.client_manager\.(compute|network|image)+\.[a-z_]+) = mock.Mock', # noqa: E501
+ logical_line,
+ ):
+ yield (
+ 0,
+ f"O402: {match.group(1)} is already a mock: there's no need to "
+ f"assign a new mock.Mock instance.",
+ )
+
+ if match := re.match(
+ r'(self\.(compute|network|image)_client\.[a-z_]+) = mock.Mock',
+ logical_line,
+ ):
+ yield (
+ 0,
+ f"O402: {match.group(1)} is already a mock: there's no need to "
+ f"assign a new mock.Mock instance.",
+ )
+
+
+class SDKProxyFindChecker(ast.NodeVisitor):
+ """NodeVisitor to find ``*_client.find_*`` statements."""
+
+ def __init__(self):
+ self.error = False
+
+ def visit_Call(self, node):
+ # No need to keep visiting the AST if we already found something.
+ if self.error:
+ return
+
+ self.generic_visit(node)
+
+ if not (
+ isinstance(node.func, ast.Attribute)
+ and node.func.attr.startswith('find_') # and
+ # isinstance(node.func.value, ast.Attribute) and
+ # node.func.value.attr.endswith('_client')
+ ):
+ # print(f'skipping: got {node.func}')
+ return
+
+ if not (
+ (
+ # handle calls like 'identity_client.find_project'
+ isinstance(node.func.value, ast.Name)
+ and node.func.value.id.endswith('client')
+ )
+ or (
+ # handle calls like 'self.app.client_manager.image.find_image'
+ isinstance(node.func.value, ast.Attribute)
+ and node.func.value.attr
+ in ('identity', 'network', 'image', 'compute')
+ )
+ ):
+ return
+
+ if not any(kw.arg == 'ignore_missing' for kw in node.keywords):
+ self.error = True
+
+
+@core.flake8ext
+def assert_find_ignore_missing_kwargs(logical_line, filename):
+ """Ensure ignore_missing is always used for ``find_*`` SDK proxy calls.
+
+ Okay: self.compute_client.find_server(foo, ignore_missing=True)
+ Okay: self.image_client.find_server(foo, ignore_missing=False)
+ Okay: self.volume_client.volumes.find(name='foo')
+ O403: self.network_client.find_network(parsed_args.network)
+ O403: self.compute_client.find_flavor(flavor_id, get_extra_specs=True)
+ """
+ if 'tests' in filename:
+ return
+
+ checker = SDKProxyFindChecker()
+ try:
+ parsed_logical_line = ast.parse(logical_line)
+ except SyntaxError:
+ # let flake8 catch this itself
+ # https://github.com/PyCQA/flake8/issues/1948
+ return
+ checker.visit(parsed_logical_line)
+ if checker.error:
+ yield (
+ 0,
+ 'O403: Calls to find_* proxy methods must explicitly set '
+ 'ignore_missing',
+ )
diff --git a/openstackclient/api/object_store_v1.py b/openstackclient/api/object_store_v1.py
index fd941e4..933b01b 100644
--- a/openstackclient/api/object_store_v1.py
+++ b/openstackclient/api/object_store_v1.py
@@ -256,7 +256,10 @@ class APIv1(api.BaseAPI):
# object's name in the container.
object_name_str = name if name else object
- full_url = f"{urllib.parse.quote(container)}/{urllib.parse.quote(object_name_str)}"
+ full_url = (
+ f"{urllib.parse.quote(container)}/"
+ f"{urllib.parse.quote(object_name_str)}"
+ )
with open(object, 'rb') as f:
response = self.create(
full_url,
diff --git a/openstackclient/command.py b/openstackclient/command.py
new file mode 100644
index 0000000..124d755
--- /dev/null
+++ b/openstackclient/command.py
@@ -0,0 +1,27 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from cliff import lister
+from cliff import show
+from osc_lib.command import command
+
+from openstackclient import shell
+
+
+class Command(command.Command):
+ app: shell.OpenStackShell
+
+
+class Lister(Command, lister.Lister): ...
+
+
+class ShowOne(Command, show.ShowOne): ...
diff --git a/openstackclient/common/availability_zone.py b/openstackclient/common/availability_zone.py
index 61f77cc..6f5e4fd 100644
--- a/openstackclient/common/availability_zone.py
+++ b/openstackclient/common/availability_zone.py
@@ -17,9 +17,9 @@ import copy
import logging
from openstack import exceptions as sdk_exceptions
-from osc_lib.command import command
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/common/clientmanager.py b/openstackclient/common/clientmanager.py
index a0455bf..51911aa 100644
--- a/openstackclient/common/clientmanager.py
+++ b/openstackclient/common/clientmanager.py
@@ -15,15 +15,25 @@
"""Manage access to the clients, including authenticating when needed."""
+import argparse
+from collections.abc import Callable
import importlib
import logging
import sys
import typing as ty
+from osc_lib.cli import client_config
from osc_lib import clientmanager
from osc_lib import shell
import stevedore
+if ty.TYPE_CHECKING:
+ from keystoneauth1 import access as ksa_access
+ from openstack.compute.v2 import _proxy as compute_proxy
+ from openstack.image.v2 import _proxy as image_proxy
+ from openstack.network.v2 import _proxy as network_proxy
+
+ from openstackclient.api import object_store_v1
LOG = logging.getLogger(__name__)
@@ -40,11 +50,23 @@ class ClientManager(clientmanager.ClientManager):
in osc-lib so we need to maintain a transition period.
"""
- # A simple incrementing version for the plugin to know what is available
- PLUGIN_INTERFACE_VERSION = "2"
-
- # Let the commands set this
- _auth_required = False
+ if ty.TYPE_CHECKING:
+ # we know this will be set by us and will not be nullable
+ auth_ref: ksa_access.AccessInfo
+
+ # this is a hack to keep mypy happy: the actual attributes are set in
+ # get_plugin_modules below
+ # TODO(stephenfin): Change the types of identity and volume once we've
+ # migrated everything to SDK. Hopefully by then we'll have figured out
+ # how to statically distinguish between the v2 and v3 versions of both
+ # services...
+ # TODO(stephenfin): We also need to migrate object storage...
+ compute: compute_proxy.Proxy
+ identity: ty.Any
+ image: image_proxy.Proxy
+ network: network_proxy.Proxy
+ object_store: object_store_v1.APIv1
+ volume: ty.Any
def __init__(
self,
@@ -81,6 +103,12 @@ class ClientManager(clientmanager.ClientManager):
self._auth_required
and self._cli_options._openstack_config is not None
):
+ if not isinstance(
+ self._cli_options._openstack_config, client_config.OSC_Config
+ ):
+ # programmer error
+ raise TypeError('unexpected type for _openstack_config')
+
self._cli_options._openstack_config._pw_callback = (
shell.prompt_for_password
)
@@ -107,6 +135,13 @@ class ClientManager(clientmanager.ClientManager):
self._cli_options.config['auth_type'] = self._original_auth_type
del self._cli_options.config['auth']['token']
del self._cli_options.config['auth']['endpoint']
+
+ if not isinstance(
+ self._cli_options._openstack_config, client_config.OSC_Config
+ ):
+ # programmer error
+ raise TypeError('unexpected type for _openstack_config')
+
self._cli_options._auth = (
self._cli_options._openstack_config.load_auth_plugin(
self._cli_options.config,
@@ -144,11 +179,25 @@ class ClientManager(clientmanager.ClientManager):
# Plugin Support
+ArgumentParserT = ty.TypeVar('ArgumentParserT', bound=argparse.ArgumentParser)
+
+
+@ty.runtime_checkable # Optional: allows usage with isinstance()
+class PluginModule(ty.Protocol):
+ DEFAULT_API_VERSION: str
+ API_VERSION_OPTION: str
+ API_NAME: str
+ API_VERSIONS: tuple[str]
+
+ make_client: Callable[..., ty.Any]
+ build_option_parser: Callable[[ArgumentParserT], ArgumentParserT]
+ check_api_version: Callable[[str], bool]
+
def _on_load_failure_callback(
manager: stevedore.ExtensionManager,
ep: importlib.metadata.EntryPoint,
- err: Exception,
+ err: BaseException,
) -> None:
sys.stderr.write(
f"WARNING: Failed to import plugin {ep.group}:{ep.name}: {err}.\n"
@@ -158,36 +207,25 @@ def _on_load_failure_callback(
def get_plugin_modules(group):
"""Find plugin entry points"""
mod_list = []
+ mgr: stevedore.ExtensionManager[PluginModule]
mgr = stevedore.ExtensionManager(
group, on_load_failure_callback=_on_load_failure_callback
)
for ep in mgr:
LOG.debug('Found plugin %s', ep.name)
- # Different versions of stevedore use different
- # implementations of EntryPoint from other libraries, which
- # are not API-compatible.
- try:
- module_name = ep.entry_point.module_name
- except AttributeError:
- try:
- module_name = ep.entry_point.module
- except AttributeError:
- module_name = ep.entry_point.value
+ module_name = ep.entry_point.module
try:
module = importlib.import_module(module_name)
except Exception as err:
sys.stderr.write(
- f"WARNING: Failed to import plugin {ep.group}:{ep.name}: "
- f"{err}.\n"
+ f"WARNING: Failed to import plugin "
+ f"{ep.module_name}:{ep.name}: {err}.\n"
)
continue
mod_list.append(module)
- init_func = getattr(module, 'Initialize', None)
- if init_func:
- init_func('x')
# Add the plugin to the ClientManager
setattr(
diff --git a/openstackclient/common/configuration.py b/openstackclient/common/configuration.py
index 418f7fd..4637ad2 100644
--- a/openstackclient/common/configuration.py
+++ b/openstackclient/common/configuration.py
@@ -14,8 +14,8 @@
"""Configuration action implementations"""
from keystoneauth1.loading import base
-from osc_lib.command import command
+from openstackclient import command
from openstackclient.i18n import _
REDACTED = "<redacted>"
diff --git a/openstackclient/common/extension.py b/openstackclient/common/extension.py
index 42c2e9b..3f9b257 100644
--- a/openstackclient/common/extension.py
+++ b/openstackclient/common/extension.py
@@ -17,9 +17,9 @@
import logging
-from osc_lib.command import command
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
diff --git a/openstackclient/common/limits.py b/openstackclient/common/limits.py
index 0c92805..6512e0f 100644
--- a/openstackclient/common/limits.py
+++ b/openstackclient/common/limits.py
@@ -17,9 +17,9 @@
import itertools
-from osc_lib.command import command
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
diff --git a/openstackclient/common/module.py b/openstackclient/common/module.py
index d4a5b95..0985107 100644
--- a/openstackclient/common/module.py
+++ b/openstackclient/common/module.py
@@ -17,9 +17,9 @@
import sys
-from osc_lib.command import command
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
@@ -48,7 +48,9 @@ class ListCommand(command.Lister):
columns = ('Command Group', 'Commands')
if parsed_args.group:
- groups = (group for group in groups if parsed_args.group in group)
+ groups = sorted(
+ group for group in groups if parsed_args.group in group
+ )
commands = []
for group in groups:
@@ -59,7 +61,7 @@ class ListCommand(command.Lister):
# TODO(bapalm): Fix this when cliff properly supports
# handling the detection rather than using the hard-code below.
if parsed_args.formatter == 'table':
- command_names = utils.format_list(command_names, "\n")
+ command_names = utils.format_list(command_names, "\n") # type: ignore
commands.append((group, command_names))
diff --git a/openstackclient/common/project_cleanup.py b/openstackclient/common/project_cleanup.py
index 84a0735..444f23e 100644
--- a/openstackclient/common/project_cleanup.py
+++ b/openstackclient/common/project_cleanup.py
@@ -20,8 +20,8 @@ import queue
import typing as ty
from cliff.formatters import table
-from osc_lib.command import command
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
@@ -90,17 +90,19 @@ class ProjectCleanup(command.Command):
return parser
def take_action(self, parsed_args):
- sdk = self.app.client_manager.sdk_connection
+ connection = self.app.client_manager.sdk_connection
if parsed_args.auth_project:
- project_connect = sdk
+ # is we've got a project already configured, use the connection
+ # as-is
+ pass
elif parsed_args.project:
- project = sdk.identity.find_project(
+ project = connection.identity.find_project(
name_or_id=parsed_args.project, ignore_missing=False
)
- project_connect = sdk.connect_as_project(project)
+ connection = connection.connect_as_project(project)
- if project_connect:
+ if connection:
status_queue: queue.Queue[ty.Any] = queue.Queue()
parsed_args.max_width = int(
os.environ.get('CLIFF_MAX_TERM_WIDTH', 0)
@@ -120,7 +122,7 @@ class ProjectCleanup(command.Command):
if parsed_args.updated_before:
filters['updated_at'] = parsed_args.updated_before
- project_connect.project_cleanup(
+ connection.project_cleanup(
dry_run=True,
status_queue=status_queue,
filters=filters,
@@ -150,7 +152,7 @@ class ProjectCleanup(command.Command):
self.log.warning(_('Deleting resources'))
- project_connect.project_cleanup(
+ connection.project_cleanup(
dry_run=False,
status_queue=status_queue,
filters=filters,
diff --git a/openstackclient/common/quota.py b/openstackclient/common/quota.py
index f706a59..0e7edf4 100644
--- a/openstackclient/common/quota.py
+++ b/openstackclient/common/quota.py
@@ -21,10 +21,10 @@ import sys
import typing as ty
from openstack import exceptions as sdk_exceptions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.network import common
@@ -272,7 +272,10 @@ class ListQuota(command.Lister):
sdk_exceptions.NotFoundException,
) as exc:
# Project not found, move on to next one
- LOG.warning(f"Project {project_id} not found: {exc}")
+ LOG.warning(
+ 'Project %(project_id)s not found: %(exc)s',
+ {'project_id': project_id, 'exc': exc},
+ )
continue
project_result = _xform_get_quota(
@@ -334,7 +337,10 @@ class ListQuota(command.Lister):
sdk_exceptions.NotFoundException,
) as exc:
# Project not found, move on to next one
- LOG.warning(f"Project {project_id} not found: {exc}")
+ LOG.warning(
+ 'Project %(project_id)s not found: %(exc)s',
+ {'project_id': project_id, 'exc': exc},
+ )
continue
project_result = _xform_get_quota(
@@ -389,7 +395,10 @@ class ListQuota(command.Lister):
sdk_exceptions.ForbiddenException,
) as exc:
# Project not found, move on to next one
- LOG.warning(f"Project {project_id} not found: {exc}")
+ LOG.warning(
+ 'Project %(project_id)s not found: %(exc)s',
+ {'project_id': project_id, 'exc': exc},
+ )
continue
project_result = _xform_get_quota(
@@ -746,21 +755,32 @@ and ``server-group-members`` output for a given quota class."""
# values if the project or class does not exist. This is expected
# behavior. However, we have already checked for the presence of the
# project above so it shouldn't be an issue.
- if parsed_args.service in {'all', 'compute'}:
+ if parsed_args.service == 'compute' or (
+ parsed_args.service == 'all'
+ and self.app.client_manager.is_compute_endpoint_enabled()
+ ):
compute_quota_info = get_compute_quotas(
self.app,
project,
detail=parsed_args.usage,
default=parsed_args.default,
)
- if parsed_args.service in {'all', 'volume'}:
+
+ if parsed_args.service == 'volume' or (
+ parsed_args.service == 'all'
+ and self.app.client_manager.is_volume_endpoint_enabled()
+ ):
volume_quota_info = get_volume_quotas(
self.app,
project,
detail=parsed_args.usage,
default=parsed_args.default,
)
- if parsed_args.service in {'all', 'network'}:
+
+ if parsed_args.service == 'network' or (
+ parsed_args.service == 'all'
+ and self.app.client_manager.is_network_endpoint_enabled()
+ ):
network_quota_info = get_network_quotas(
self.app,
project,
@@ -786,20 +806,25 @@ and ``server-group-members`` output for a given quota class."""
info.update(volume_quota_info)
info.update(network_quota_info)
- # Map the internal quota names to the external ones
- # COMPUTE_QUOTAS and NETWORK_QUOTAS share floating-ips,
- # secgroup-rules and secgroups as dict value, so when
- # neutron is enabled, quotas of these three resources
- # in nova will be replaced by neutron's.
- for k, v in itertools.chain(
- COMPUTE_QUOTAS.items(),
- NOVA_NETWORK_QUOTAS.items(),
- VOLUME_QUOTAS.items(),
- NETWORK_QUOTAS.items(),
- ):
- if not k == v and info.get(k) is not None:
- info[v] = info[k]
- info.pop(k)
+ def _normalize_names(section: dict) -> None:
+ # Map the internal quota names to the external ones
+ # COMPUTE_QUOTAS and NETWORK_QUOTAS share floating-ips,
+ # secgroup-rules and secgroups as dict value, so when
+ # neutron is enabled, quotas of these three resources
+ # in nova will be replaced by neutron's.
+ for k, v in itertools.chain(
+ COMPUTE_QUOTAS.items(),
+ NOVA_NETWORK_QUOTAS.items(),
+ VOLUME_QUOTAS.items(),
+ NETWORK_QUOTAS.items(),
+ ):
+ if not k == v and section.get(k) is not None:
+ section[v] = section.pop(k)
+
+ _normalize_names(info)
+ if parsed_args.usage:
+ _normalize_names(info["reservation"])
+ _normalize_names(info["usage"])
# Remove the 'id' field since it's not very useful
if 'id' in info:
@@ -906,12 +931,18 @@ class DeleteQuota(command.Command):
)
# compute quotas
- if parsed_args.service in {'all', 'compute'}:
+ if parsed_args.service == 'compute' or (
+ parsed_args.service == 'all'
+ and self.app.client_manager.is_compute_endpoint_enabled()
+ ):
compute_client = self.app.client_manager.compute
compute_client.revert_quota_set(project.id)
# volume quotas
- if parsed_args.service in {'all', 'volume'}:
+ if parsed_args.service == 'volume' or (
+ parsed_args.service == 'all'
+ and self.app.client_manager.is_volume_endpoint_enabled()
+ ):
volume_client = self.app.client_manager.sdk_connection.volume
volume_client.revert_quota_set(project.id)
diff --git a/openstackclient/common/versions.py b/openstackclient/common/versions.py
index 6622338..dfd84e0 100644
--- a/openstackclient/common/versions.py
+++ b/openstackclient/common/versions.py
@@ -14,8 +14,7 @@
"""Versions Action Implementation"""
-from osc_lib.command import command
-
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/compute/v2/agent.py b/openstackclient/compute/v2/agent.py
index 5bc6603..71b68d4 100644
--- a/openstackclient/compute/v2/agent.py
+++ b/openstackclient/compute/v2/agent.py
@@ -18,10 +18,10 @@
import logging
from openstack import exceptions as sdk_exceptions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/compute/v2/aggregate.py b/openstackclient/compute/v2/aggregate.py
index e649607..f8c3d96 100644
--- a/openstackclient/compute/v2/aggregate.py
+++ b/openstackclient/compute/v2/aggregate.py
@@ -19,20 +19,21 @@
import logging
import typing as ty
+from cliff import columns
from openstack import utils as sdk_utils
from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
-_aggregate_formatters = {
+_aggregate_formatters: dict[str, type[columns.FormattableColumn[ty.Any]]] = {
'Hosts': format_columns.ListColumn,
'Metadata': format_columns.DictColumn,
'hosts': format_columns.ListColumn,
@@ -438,15 +439,15 @@ class CacheImageForAggregate(command.Command):
)
raise exceptions.CommandError(msg)
+ image_client = self.app.client_manager.sdk_connection.image
+
aggregate = compute_client.find_aggregate(
parsed_args.aggregate, ignore_missing=False
)
images = []
for img in parsed_args.image:
- image = self.app.client_manager.sdk_connection.image.find_image(
- img, ignore_missing=False
- )
+ image = image_client.find_image(img, ignore_missing=False)
images.append(image.id)
compute_client.aggregate_precache_images(aggregate.id, images)
diff --git a/openstackclient/compute/v2/console.py b/openstackclient/compute/v2/console.py
index bcabcd2..cbcce4b 100644
--- a/openstackclient/compute/v2/console.py
+++ b/openstackclient/compute/v2/console.py
@@ -16,9 +16,9 @@
"""Compute v2 Console action implementations"""
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
@@ -64,13 +64,15 @@ class ShowConsoleLog(command.Command):
output = compute_client.get_server_console_output(
server.id, length=parsed_args.lines
)
- data = None
+ data: str | None = None
if output:
data = output.get('output', None)
if data and data[-1] != '\n':
data += '\n'
- self.app.stdout.write(data)
+
+ if data:
+ self.app.stdout.write(data)
class ShowConsoleURL(command.ShowOne):
diff --git a/openstackclient/compute/v2/console_connection.py b/openstackclient/compute/v2/console_connection.py
index d90b2ce..97eb1a8 100644
--- a/openstackclient/compute/v2/console_connection.py
+++ b/openstackclient/compute/v2/console_connection.py
@@ -13,9 +13,9 @@
"""Compute v2 Console auth token implementations."""
-from osc_lib.command import command
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/compute/v2/flavor.py b/openstackclient/compute/v2/flavor.py
index c0e043e..de3a710 100644
--- a/openstackclient/compute/v2/flavor.py
+++ b/openstackclient/compute/v2/flavor.py
@@ -21,10 +21,10 @@ from openstack import exceptions as sdk_exceptions
from openstack import utils as sdk_utils
from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.common import pagination
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
diff --git a/openstackclient/compute/v2/host.py b/openstackclient/compute/v2/host.py
index aa1d1a5..5802367 100644
--- a/openstackclient/compute/v2/host.py
+++ b/openstackclient/compute/v2/host.py
@@ -16,9 +16,9 @@
"""Host action implementations"""
from openstack import exceptions as sdk_exceptions
-from osc_lib.command import command
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/compute/v2/hypervisor.py b/openstackclient/compute/v2/hypervisor.py
index 0a6cc53..9e1b265 100644
--- a/openstackclient/compute/v2/hypervisor.py
+++ b/openstackclient/compute/v2/hypervisor.py
@@ -21,10 +21,10 @@ import re
from openstack import exceptions as sdk_exceptions
from openstack import utils as sdk_utils
from osc_lib.cli import format_columns
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.common import pagination
from openstackclient.i18n import _
diff --git a/openstackclient/compute/v2/hypervisor_stats.py b/openstackclient/compute/v2/hypervisor_stats.py
index 3b9a686..d151b41 100644
--- a/openstackclient/compute/v2/hypervisor_stats.py
+++ b/openstackclient/compute/v2/hypervisor_stats.py
@@ -13,9 +13,9 @@
"""Hypervisor Stats action implementations"""
-from osc_lib.command import command
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/compute/v2/keypair.py b/openstackclient/compute/v2/keypair.py
index 97dd04f..b774469 100644
--- a/openstackclient/compute/v2/keypair.py
+++ b/openstackclient/compute/v2/keypair.py
@@ -22,10 +22,10 @@ import os
from cryptography.hazmat.primitives.asymmetric import ed25519
from cryptography.hazmat.primitives import serialization
from openstack import utils as sdk_utils
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.common import pagination
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py
index e14392a..a52657c 100644
--- a/openstackclient/compute/v2/server.py
+++ b/openstackclient/compute/v2/server.py
@@ -21,6 +21,7 @@ import getpass
import json
import logging
import os
+import typing as ty
from cliff import columns as cliff_columns
import iso8601
@@ -28,11 +29,11 @@ from openstack import exceptions as sdk_exceptions
from openstack import utils as sdk_utils
from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
from openstackclient.api import compute_v2
+from openstackclient import command
from openstackclient.common import envvars
from openstackclient.common import pagination
from openstackclient.i18n import _
@@ -44,7 +45,7 @@ LOG = logging.getLogger(__name__)
IMAGE_STRING_FOR_BFV = 'N/A (booted from volume)'
-class PowerStateColumn(cliff_columns.FormattableColumn):
+class PowerStateColumn(cliff_columns.FormattableColumn[int]):
"""Generate a formatted string of a server's power state."""
power_states = [
@@ -65,7 +66,7 @@ class PowerStateColumn(cliff_columns.FormattableColumn):
return 'N/A'
-class AddressesColumn(cliff_columns.FormattableColumn):
+class AddressesColumn(cliff_columns.FormattableColumn[ty.Any]):
"""Generate a formatted string of a server's addresses."""
def human_readable(self):
@@ -86,7 +87,7 @@ class AddressesColumn(cliff_columns.FormattableColumn):
}
-class HostColumn(cliff_columns.FormattableColumn):
+class HostColumn(cliff_columns.FormattableColumn[str | None]):
"""Generate a formatted string of a hostname."""
def human_readable(self):
@@ -183,9 +184,17 @@ def _prep_server_detail(compute_client, image_client, server, *, refresh=True):
'updated_at': 'updated',
'user_data': 'OS-EXT-SRV-ATTR:user_data',
'vm_state': 'OS-EXT-STS:vm_state',
- 'pinned_availability_zone': 'pinned_availability_zone',
- 'scheduler_hints': 'scheduler_hints',
}
+ # NOTE(ratailor): microversion 2.96 introduces
+ # pinned_availability_zone support
+ if sdk_utils.supports_microversion(compute_client, '2.96'):
+ column_map['pinned_availability_zone'] = 'pinned_availability_zone'
+
+ # NOTE(ratailor): microversion 2.100 introduces
+ # scheduler_hints support
+ if sdk_utils.supports_microversion(compute_client, '2.100'):
+ column_map['scheduler_hints'] = 'scheduler_hints'
+
# Some columns returned by openstacksdk should not be shown because they're
# either irrelevant or duplicates
ignored_columns = {
@@ -240,6 +249,11 @@ def _prep_server_detail(compute_client, image_client, server, *, refresh=True):
if not sdk_utils.supports_microversion(compute_client, '2.100'):
info.pop('scheduler_hints', None)
+ # NOTE(ratailor): microversion 2.96 introduces
+ # pinned_availability_zone support
+ if not sdk_utils.supports_microversion(compute_client, '2.96'):
+ info.pop('pinned_availability_zone', None)
+
# Convert the image blob to a name
image_info = info.get('image', {})
if image_info and any(image_info.values()):
@@ -326,10 +340,11 @@ def _prep_server_detail(compute_client, image_client, server, *, refresh=True):
info['OS-EXT-STS:power_state']
)
- if 'scheduler_hints' in info:
- info['scheduler_hints'] = format_columns.DictListColumn(
- info.pop('scheduler_hints', {}),
- )
+ if sdk_utils.supports_microversion(compute_client, '2.100'):
+ if 'scheduler_hints' in info:
+ info['scheduler_hints'] = format_columns.DictListColumn(
+ info.pop('scheduler_hints', {}),
+ )
return info
@@ -2166,7 +2181,9 @@ class CreateServerDump(command.Command):
def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute
for name_or_id in parsed_args.server:
- server = compute_client.find_server(name_or_id)
+ server = compute_client.find_server(
+ name_or_id, ignore_missing=False
+ )
server.trigger_crash_dump(compute_client)
@@ -2209,24 +2226,49 @@ class DeleteServer(command.Command):
self.app.stdout.flush()
compute_client = self.app.client_manager.compute
+
+ deleted_servers = []
for server in parsed_args.server:
- server_obj = compute_client.find_server(
- server,
- ignore_missing=False,
- all_projects=parsed_args.all_projects,
- )
+ try:
+ server_obj = compute_client.find_server(
+ server,
+ ignore_missing=False,
+ all_projects=parsed_args.all_projects,
+ )
- compute_client.delete_server(server_obj, force=parsed_args.force)
+ compute_client.delete_server(
+ server_obj, force=parsed_args.force
+ )
+ deleted_servers.append(server_obj)
+ except Exception as e:
+ LOG.error(
+ _(
+ "Failed to delete server with "
+ "name or ID '%(server)s': %(e)s"
+ ),
+ {'server': server, 'e': e},
+ )
- if parsed_args.wait:
+ if parsed_args.wait:
+ for server_obj in deleted_servers:
try:
compute_client.wait_for_delete(
server_obj, callback=_show_progress
)
except sdk_exceptions.ResourceTimeout:
msg = _('Error deleting server: %s') % server_obj.id
+ deleted_servers.remove(server_obj)
raise exceptions.CommandError(msg)
+ fails = len(parsed_args.server) - len(deleted_servers)
+ if fails > 0:
+ total = len(parsed_args.server)
+ msg = _("%(fails)s of %(total)s servers failed to delete.") % {
+ 'fails': fails,
+ 'total': total,
+ }
+ raise exceptions.CommandError(msg)
+
class PercentAction(argparse.Action):
def __init__(
@@ -2838,18 +2880,21 @@ class ListServer(command.Lister):
if parsed_args.long:
columns += (
'availability_zone',
- 'pinned_availability_zone',
'hypervisor_hostname',
'metadata',
- 'scheduler_hints',
)
column_headers += (
'Availability Zone',
- 'Pinned Availability Zone',
'Host',
'Properties',
- 'Scheduler Hints',
)
+ if sdk_utils.supports_microversion(compute_client, '2.96'):
+ columns += ('pinned_availability_zone',)
+ column_headers += ('Pinned Availability Zone',)
+
+ if sdk_utils.supports_microversion(compute_client, '2.100'):
+ columns += ('scheduler_hints',)
+ column_headers += ('Scheduler Hints',)
if parsed_args.all_projects:
columns += ('project_id',)
@@ -2887,10 +2932,11 @@ class ListServer(command.Lister):
column_headers += ('Availability Zone',)
if c in (
'pinned_availability_zone',
- "Pinned Availability Zone",
+ 'Pinned Availability Zone',
):
- columns += ('Pinned Availability Zone',)
- column_headers += ('Pinned Availability Zone',)
+ if sdk_utils.supports_microversion(compute_client, '2.96'):
+ columns += ('pinned_availability_zone',)
+ column_headers += ('Pinned Availability Zone',)
if c in ('Host', "host"):
columns += ('hypervisor_hostname',)
column_headers += ('Host',)
@@ -2901,8 +2947,11 @@ class ListServer(command.Lister):
'scheduler_hints',
"Scheduler Hints",
):
- columns += ('scheduler_hints',)
- column_headers += ('Scheduler Hints',)
+ if sdk_utils.supports_microversion(
+ compute_client, '2.100'
+ ):
+ columns += ('scheduler_hints',)
+ column_headers += ('Scheduler Hints',)
# remove duplicates
column_headers = tuple(dict.fromkeys(column_headers))
@@ -4218,7 +4267,7 @@ release the new server and restart the old one."""
metavar='<server>',
help=_('Server (name or ID)'),
)
- phase_group = parser.add_mutually_exclusive_group()
+ phase_group = parser.add_mutually_exclusive_group(required=True)
phase_group.add_argument(
'--flavor',
metavar='<flavor>',
@@ -4969,7 +5018,7 @@ class SshServer(command.Command):
)
cmd = ' '.join(['ssh', ip_address] + args)
- LOG.debug(f"ssh command: {cmd}")
+ LOG.debug('ssh command: %s', cmd)
# we intentionally pass through user-provided arguments and run this in
# the user's shell
os.system(cmd) # noqa: S605
diff --git a/openstackclient/compute/v2/server_backup.py b/openstackclient/compute/v2/server_backup.py
index b0395db..bb06f76 100644
--- a/openstackclient/compute/v2/server_backup.py
+++ b/openstackclient/compute/v2/server_backup.py
@@ -17,10 +17,10 @@
import importlib
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/compute/v2/server_event.py b/openstackclient/compute/v2/server_event.py
index 3275df9..0e1e2b4 100644
--- a/openstackclient/compute/v2/server_event.py
+++ b/openstackclient/compute/v2/server_event.py
@@ -22,10 +22,10 @@ from cliff import columns
import iso8601
from openstack import exceptions as sdk_exceptions
from openstack import utils as sdk_utils
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.common import pagination
from openstackclient.i18n import _
diff --git a/openstackclient/compute/v2/server_group.py b/openstackclient/compute/v2/server_group.py
index 7356748..b74c256 100644
--- a/openstackclient/compute/v2/server_group.py
+++ b/openstackclient/compute/v2/server_group.py
@@ -16,21 +16,23 @@
"""Compute v2 Server Group action implementations"""
import logging
+import typing as ty
+from cliff import columns
from openstack import utils as sdk_utils
from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.common import pagination
from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
-_formatters = {
+_formatters: dict[str, type[columns.FormattableColumn[ty.Any]]] = {
'member_ids': format_columns.ListColumn,
'policies': format_columns.ListColumn,
'rules': format_columns.DictColumn,
diff --git a/openstackclient/compute/v2/server_image.py b/openstackclient/compute/v2/server_image.py
index cb19173..26dbb4c 100644
--- a/openstackclient/compute/v2/server_image.py
+++ b/openstackclient/compute/v2/server_image.py
@@ -19,10 +19,10 @@ import importlib
import logging
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/compute/v2/server_migration.py b/openstackclient/compute/v2/server_migration.py
index c356bd8..f2ea683 100644
--- a/openstackclient/compute/v2/server_migration.py
+++ b/openstackclient/compute/v2/server_migration.py
@@ -15,10 +15,10 @@
import uuid
from openstack import utils as sdk_utils
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.common import pagination
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
diff --git a/openstackclient/compute/v2/server_volume.py b/openstackclient/compute/v2/server_volume.py
index a27c63f..d92d137 100644
--- a/openstackclient/compute/v2/server_volume.py
+++ b/openstackclient/compute/v2/server_volume.py
@@ -15,10 +15,10 @@
"""Compute v2 Server action implementations"""
from openstack import utils as sdk_utils
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/compute/v2/service.py b/openstackclient/compute/v2/service.py
index 3660ddd..b911835 100644
--- a/openstackclient/compute/v2/service.py
+++ b/openstackclient/compute/v2/service.py
@@ -18,10 +18,10 @@
import logging
from openstack import utils as sdk_utils
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/compute/v2/usage.py b/openstackclient/compute/v2/usage.py
index d045c1e..3015a9e 100644
--- a/openstackclient/compute/v2/usage.py
+++ b/openstackclient/compute/v2/usage.py
@@ -15,19 +15,21 @@
"""Usage action implementations"""
+from collections.abc import Collection
import datetime
import functools
+import typing as ty
from cliff import columns as cliff_columns
-from osc_lib.command import command
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
# TODO(stephenfin): This exists in a couple of places and should be moved to a
# common module
-class ProjectColumn(cliff_columns.FormattableColumn):
+class ProjectColumn(cliff_columns.FormattableColumn[str]):
"""Formattable column for project column.
Unlike the parent FormattableColumn class, the initializer of the class
@@ -53,12 +55,12 @@ class ProjectColumn(cliff_columns.FormattableColumn):
return project
-class CountColumn(cliff_columns.FormattableColumn):
+class CountColumn(cliff_columns.FormattableColumn[Collection[ty.Any]]):
def human_readable(self):
return len(self._value) if self._value is not None else None
-class FloatColumn(cliff_columns.FormattableColumn):
+class FloatColumn(cliff_columns.FormattableColumn[float]):
def human_readable(self):
return float(f"{self._value:.2f}")
diff --git a/openstackclient/identity/common.py b/openstackclient/identity/common.py
index c6e6cfc..f33c370 100644
--- a/openstackclient/identity/common.py
+++ b/openstackclient/identity/common.py
@@ -99,7 +99,8 @@ def find_service_sdk(identity_client, name_type_or_id):
if next(services, None):
msg = _(
- "Multiple service matches found for '%(query)s', use an ID to be more specific."
+ "Multiple service matches found for '%(query)s', "
+ "use an ID to be more specific."
) % {"query": name_type_or_id}
raise exceptions.CommandError(msg)
@@ -255,6 +256,37 @@ def find_project(identity_client, name_or_id, domain_name_or_id=None):
)
+def find_project_id_sdk(
+ identity_client,
+ name_or_id,
+ domain_name_or_id=None,
+ *,
+ validate_actor_existence=True,
+ validate_domain_actor_existence=None,
+):
+ if domain_name_or_id is None:
+ return _find_sdk_id(
+ identity_client.find_project,
+ name_or_id=name_or_id,
+ validate_actor_existence=validate_actor_existence,
+ )
+
+ if validate_domain_actor_existence is None:
+ validate_domain_actor_existence = validate_actor_existence
+
+ domain_id = find_domain_id_sdk(
+ identity_client,
+ name_or_id=domain_name_or_id,
+ validate_actor_existence=validate_domain_actor_existence,
+ )
+ return _find_sdk_id(
+ identity_client.find_project,
+ name_or_id=name_or_id,
+ validate_actor_existence=validate_actor_existence,
+ domain_id=domain_id,
+ )
+
+
def find_user(identity_client, name_or_id, domain_name_or_id=None):
if domain_name_or_id is None:
return _find_identity_resource(
diff --git a/openstackclient/identity/v2_0/catalog.py b/openstackclient/identity/v2_0/catalog.py
index ccac5d0..437cad2 100644
--- a/openstackclient/identity/v2_0/catalog.py
+++ b/openstackclient/identity/v2_0/catalog.py
@@ -14,19 +14,20 @@
"""Identity v2 Service Catalog action implementations"""
import logging
+import typing as ty
from cliff import columns as cliff_columns
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
-class EndpointsColumn(cliff_columns.FormattableColumn):
+class EndpointsColumn(cliff_columns.FormattableColumn[ty.Any]):
def human_readable(self):
if not self._value:
return ""
diff --git a/openstackclient/identity/v2_0/ec2creds.py b/openstackclient/identity/v2_0/ec2creds.py
index 25ee8a7..360a090 100644
--- a/openstackclient/identity/v2_0/ec2creds.py
+++ b/openstackclient/identity/v2_0/ec2creds.py
@@ -18,10 +18,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/identity/v2_0/endpoint.py b/openstackclient/identity/v2_0/endpoint.py
index db8efed..38f7f4e 100644
--- a/openstackclient/identity/v2_0/endpoint.py
+++ b/openstackclient/identity/v2_0/endpoint.py
@@ -17,10 +17,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common
diff --git a/openstackclient/identity/v2_0/project.py b/openstackclient/identity/v2_0/project.py
index a0c3c1e..bf19d7d 100644
--- a/openstackclient/identity/v2_0/project.py
+++ b/openstackclient/identity/v2_0/project.py
@@ -20,10 +20,10 @@ import logging
from keystoneauth1 import exceptions as ks_exc
from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
@@ -59,6 +59,7 @@ class CreateProject(command.ShowOne):
parser.add_argument(
'--property',
metavar='<key=value>',
+ dest='properties',
action=parseractions.KeyValueAction,
help=_(
'Add a property to <name> '
@@ -79,8 +80,8 @@ class CreateProject(command.ShowOne):
if parsed_args.disable:
enabled = False
kwargs = {}
- if parsed_args.property:
- kwargs = parsed_args.property.copy()
+ if parsed_args.properties:
+ kwargs.update(parsed_args.properties)
try:
project = identity_client.tenants.create(
@@ -105,7 +106,14 @@ class CreateProject(command.ShowOne):
class DeleteProject(command.Command):
- _description = _("Delete project(s)")
+ _description = _(
+ "Delete project(s). This command will remove specified "
+ "existing project(s) if an active user is authorized to do "
+ "this. If there are resources managed by other services "
+ "(for example, Nova, Neutron, Cinder) associated with "
+ "specified project(s), delete operation will proceed "
+ "regardless."
+ )
def get_parser(self, prog_name):
parser = super().get_parser(prog_name)
@@ -223,6 +231,7 @@ class SetProject(command.Command):
parser.add_argument(
'--property',
metavar='<key=value>',
+ dest='properties',
action=parseractions.KeyValueAction,
help=_(
'Set a project property '
@@ -248,8 +257,8 @@ class SetProject(command.Command):
kwargs['enabled'] = True
if parsed_args.disable:
kwargs['enabled'] = False
- if parsed_args.property:
- kwargs.update(parsed_args.property)
+ if parsed_args.properties:
+ kwargs.update(parsed_args.properties)
if 'id' in kwargs:
del kwargs['id']
if 'name' in kwargs:
@@ -331,6 +340,7 @@ class UnsetProject(command.Command):
parser.add_argument(
'--property',
metavar='<key>',
+ dest='properties',
action='append',
default=[],
help=_(
@@ -347,7 +357,7 @@ class UnsetProject(command.Command):
parsed_args.project,
)
kwargs = project._info
- for key in parsed_args.property:
+ for key in parsed_args.properties:
if key in kwargs:
kwargs[key] = None
identity_client.tenants.update(project.id, **kwargs)
diff --git a/openstackclient/identity/v2_0/role.py b/openstackclient/identity/v2_0/role.py
index 1faab2e..e54c07a 100644
--- a/openstackclient/identity/v2_0/role.py
+++ b/openstackclient/identity/v2_0/role.py
@@ -18,10 +18,10 @@
import logging
from keystoneauth1 import exceptions as ks_exc
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/identity/v2_0/role_assignment.py b/openstackclient/identity/v2_0/role_assignment.py
index 54d01b4..0aa800e 100644
--- a/openstackclient/identity/v2_0/role_assignment.py
+++ b/openstackclient/identity/v2_0/role_assignment.py
@@ -13,10 +13,10 @@
"""Identity v2 Assignment action implementations"""
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _ # noqa
@@ -68,7 +68,7 @@ class ListRoleAssignment(command.Lister):
parsed_args.user,
)
elif parsed_args.authuser:
- if auth_ref:
+ if auth_ref and auth_ref.user_id:
user = utils.find_resource(
identity_client.users, auth_ref.user_id
)
@@ -80,7 +80,7 @@ class ListRoleAssignment(command.Lister):
parsed_args.project,
)
elif parsed_args.authproject:
- if auth_ref:
+ if auth_ref and auth_ref.project_id:
project = utils.find_resource(
identity_client.projects, auth_ref.project_id
)
diff --git a/openstackclient/identity/v2_0/service.py b/openstackclient/identity/v2_0/service.py
index 978e926..a93a953 100644
--- a/openstackclient/identity/v2_0/service.py
+++ b/openstackclient/identity/v2_0/service.py
@@ -17,10 +17,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common
@@ -160,7 +160,9 @@ class ShowService(command.ShowOne):
for service, service_endpoints in endpoints.items():
if service_endpoints:
info = {"type": service}
- info.update(service_endpoints[0])
+ # FIXME(stephenfin): The return type for this in ksa is
+ # wrong
+ info.update(service_endpoints[0]) # type: ignore
return zip(*sorted(info.items()))
msg = _(
diff --git a/openstackclient/identity/v2_0/token.py b/openstackclient/identity/v2_0/token.py
index fe9436d..ebb2269 100644
--- a/openstackclient/identity/v2_0/token.py
+++ b/openstackclient/identity/v2_0/token.py
@@ -15,9 +15,9 @@
"""Identity v2 Token action implementations"""
-from osc_lib.command import command
from osc_lib import exceptions
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/identity/v2_0/user.py b/openstackclient/identity/v2_0/user.py
index c4cd52b..244b9e9 100644
--- a/openstackclient/identity/v2_0/user.py
+++ b/openstackclient/identity/v2_0/user.py
@@ -20,17 +20,17 @@ import logging
from cliff import columns as cliff_columns
from keystoneauth1 import exceptions as ks_exc
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
-class ProjectColumn(cliff_columns.FormattableColumn):
+class ProjectColumn(cliff_columns.FormattableColumn[str]):
"""Formattable column for project column.
Unlike the parent FormattableColumn class, the initializer of the
diff --git a/openstackclient/identity/v3/access_rule.py b/openstackclient/identity/v3/access_rule.py
index 367c649..1859ef6 100644
--- a/openstackclient/identity/v3/access_rule.py
+++ b/openstackclient/identity/v3/access_rule.py
@@ -17,10 +17,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common
@@ -44,7 +44,11 @@ class DeleteAccessRule(command.Command):
def take_action(self, parsed_args):
identity_client = self.app.client_manager.sdk_connection.identity
conn = self.app.client_manager.sdk_connection
- user_id = conn.config.get_auth().get_user_id(conn.identity)
+ auth = conn.config.get_auth()
+ if auth is None:
+ # this will never happen
+ raise exceptions.CommandError('invalid authentication info')
+ user_id = auth.get_user_id(conn.identity)
errors = 0
for ac in parsed_args.access_rule:
@@ -87,7 +91,11 @@ class ListAccessRule(command.Lister):
).id
else:
conn = self.app.client_manager.sdk_connection
- user_id = conn.config.get_auth().get_user_id(conn.identity)
+ auth = conn.config.get_auth()
+ if auth is None:
+ # this will never happen
+ raise exceptions.CommandError('invalid authentication info')
+ user_id = auth.get_user_id(conn.identity)
columns = ('ID', 'Service', 'Method', 'Path')
data = identity_client.access_rules(user=user_id)
@@ -119,7 +127,11 @@ class ShowAccessRule(command.ShowOne):
def take_action(self, parsed_args):
identity_client = self.app.client_manager.sdk_connection.identity
conn = self.app.client_manager.sdk_connection
- user_id = conn.config.get_auth().get_user_id(conn.identity)
+ auth = conn.config.get_auth()
+ if auth is None:
+ # this will never happen
+ raise exceptions.CommandError('invalid authentication info')
+ user_id = auth.get_user_id(conn.identity)
access_rule = identity_client.get_access_rule(
user_id, parsed_args.access_rule
diff --git a/openstackclient/identity/v3/application_credential.py b/openstackclient/identity/v3/application_credential.py
index 4c4cd3f..3b38f17 100644
--- a/openstackclient/identity/v3/application_credential.py
+++ b/openstackclient/identity/v3/application_credential.py
@@ -18,24 +18,25 @@
import datetime
import json
import logging
+import typing as ty
import uuid
from cliff import columns as cliff_columns
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common
LOG = logging.getLogger(__name__)
-class RolesColumn(cliff_columns.FormattableColumn):
+class RolesColumn(cliff_columns.FormattableColumn[ty.Any]):
"""Generate a formatted string of role names."""
def human_readable(self):
- return utils.format_list(r['name'] for r in self._value)
+ return utils.format_list(list(r['name'] for r in self._value))
def _format_application_credential(
@@ -148,6 +149,7 @@ class CreateApplicationCredential(command.ShowOne):
parser.add_argument(
'--role',
metavar='<role>',
+ dest='roles',
action='append',
default=[],
help=_(
@@ -204,10 +206,15 @@ class CreateApplicationCredential(command.ShowOne):
def take_action(self, parsed_args):
identity_client = self.app.client_manager.sdk_connection.identity
conn = self.app.client_manager.sdk_connection
- user_id = conn.config.get_auth().get_user_id(conn.identity)
+ auth = conn.config.get_auth()
+ if auth is None:
+ # this will never happen
+ raise exceptions.CommandError('invalid authentication info')
+
+ user_id = auth.get_user_id(conn.identity)
role_ids = []
- for role in parsed_args.role:
+ for role in parsed_args.roles:
if is_uuid_like(role):
role_ids.append({'id': role})
else:
@@ -272,13 +279,18 @@ class DeleteApplicationCredential(command.Command):
def take_action(self, parsed_args):
identity_client = self.app.client_manager.sdk_connection.identity
conn = self.app.client_manager.sdk_connection
- user_id = conn.config.get_auth().get_user_id(conn.identity)
+ auth = conn.config.get_auth()
+ if auth is None:
+ # this will never happen
+ raise exceptions.CommandError('invalid authentication info')
+
+ user_id = auth.get_user_id(conn.identity)
errors = 0
for ac in parsed_args.application_credential:
try:
app_cred = identity_client.find_application_credential(
- user_id, ac
+ user_id, ac, ignore_missing=False
)
identity_client.delete_application_credential(
user_id, app_cred.id
@@ -325,7 +337,11 @@ class ListApplicationCredential(command.Lister):
)
else:
conn = self.app.client_manager.sdk_connection
- user_id = conn.config.get_auth().get_user_id(conn.identity)
+ auth = conn.config.get_auth()
+ if auth is None:
+ # this will never happen
+ raise exceptions.CommandError('invalid authentication info')
+ user_id = auth.get_user_id(conn.identity)
application_credentials = identity_client.application_credentials(
user=user_id
@@ -349,10 +365,14 @@ class ShowApplicationCredential(command.ShowOne):
def take_action(self, parsed_args):
identity_client = self.app.client_manager.sdk_connection.identity
conn = self.app.client_manager.sdk_connection
- user_id = conn.config.get_auth().get_user_id(conn.identity)
+ auth = conn.config.get_auth()
+ if auth is None:
+ # this will never happen
+ raise exceptions.CommandError('invalid authentication info')
+ user_id = auth.get_user_id(conn.identity)
application_credential = identity_client.find_application_credential(
- user_id, parsed_args.application_credential
+ user_id, parsed_args.application_credential, ignore_missing=False
)
return _format_application_credential(application_credential)
diff --git a/openstackclient/identity/v3/catalog.py b/openstackclient/identity/v3/catalog.py
index a161461..7d37e6c 100644
--- a/openstackclient/identity/v3/catalog.py
+++ b/openstackclient/identity/v3/catalog.py
@@ -9,24 +9,24 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
-#
"""Identity v3 Service Catalog action implementations"""
import logging
+import typing as ty
from cliff import columns as cliff_columns
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
-class EndpointsColumn(cliff_columns.FormattableColumn):
+class EndpointsColumn(cliff_columns.FormattableColumn[ty.Any]):
def human_readable(self):
if not self._value:
return ""
diff --git a/openstackclient/identity/v3/consumer.py b/openstackclient/identity/v3/consumer.py
index 933f48a..c58441c 100644
--- a/openstackclient/identity/v3/consumer.py
+++ b/openstackclient/identity/v3/consumer.py
@@ -17,10 +17,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/identity/v3/credential.py b/openstackclient/identity/v3/credential.py
index 7d9c7c4..02eef64 100644
--- a/openstackclient/identity/v3/credential.py
+++ b/openstackclient/identity/v3/credential.py
@@ -17,10 +17,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common
diff --git a/openstackclient/identity/v3/domain.py b/openstackclient/identity/v3/domain.py
index 536243a..28481c0 100644
--- a/openstackclient/identity/v3/domain.py
+++ b/openstackclient/identity/v3/domain.py
@@ -18,10 +18,10 @@
import logging
from openstack import exceptions as sdk_exceptions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common
@@ -107,7 +107,9 @@ class CreateDomain(command.ShowOne):
)
except sdk_exceptions.ConflictException:
if parsed_args.or_show:
- domain = identity_client.find_domain(parsed_args.name)
+ domain = identity_client.find_domain(
+ parsed_args.name, ignore_missing=False
+ )
LOG.info(_('Returning existing domain %s'), domain.name)
else:
raise
@@ -238,7 +240,9 @@ class SetDomain(command.Command):
def take_action(self, parsed_args):
identity_client = self.app.client_manager.sdk_connection.identity
- domain = identity_client.find_domain(parsed_args.domain)
+ domain = identity_client.find_domain(
+ parsed_args.domain, ignore_missing=False
+ )
kwargs = {}
if parsed_args.name:
kwargs['name'] = parsed_args.name
@@ -266,6 +270,8 @@ class ShowDomain(command.ShowOne):
def take_action(self, parsed_args):
identity_client = self.app.client_manager.sdk_connection.identity
- domain = identity_client.find_domain(parsed_args.domain)
+ domain = identity_client.find_domain(
+ parsed_args.domain, ignore_missing=False
+ )
return _format_domain(domain)
diff --git a/openstackclient/identity/v3/ec2creds.py b/openstackclient/identity/v3/ec2creds.py
index 84700f4..dbbf7a2 100644
--- a/openstackclient/identity/v3/ec2creds.py
+++ b/openstackclient/identity/v3/ec2creds.py
@@ -14,10 +14,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common
diff --git a/openstackclient/identity/v3/endpoint.py b/openstackclient/identity/v3/endpoint.py
index 1dfa881..9083fdc 100644
--- a/openstackclient/identity/v3/endpoint.py
+++ b/openstackclient/identity/v3/endpoint.py
@@ -17,10 +17,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common
@@ -169,7 +169,9 @@ class DeleteEndpoint(command.Command):
result = 0
for i in parsed_args.endpoint:
try:
- endpoint_id = identity_client.find_endpoint(i).id
+ endpoint_id = identity_client.find_endpoint(
+ i, ignore_missing=False
+ ).id
identity_client.delete_endpoint(endpoint_id)
except Exception as e:
result += 1
@@ -230,12 +232,25 @@ class ListEndpoint(command.Lister):
endpoint = None
if parsed_args.endpoint:
- endpoint = identity_client.find_endpoint(parsed_args.endpoint)
- project = None
+ endpoint = identity_client.find_endpoint(
+ parsed_args.endpoint, ignore_missing=False
+ )
+
+ project_domain_id = None
+ if parsed_args.project_domain:
+ project_domain_id = common._find_sdk_id(
+ identity_client.find_domain,
+ name_or_id=parsed_args.project_domain,
+ )
+
+ project_id = None
if parsed_args.project:
- project = identity_client.find_project(
- parsed_args.project,
- parsed_args.project_domain,
+ project_id = common._find_sdk_id(
+ identity_client.find_project,
+ name_or_id=common._get_token_resource(
+ identity_client, 'project', parsed_args.project
+ ),
+ domain_id=project_domain_id,
)
if endpoint:
@@ -273,15 +288,17 @@ class ListEndpoint(command.Lister):
region = identity_client.get_region(parsed_args.region)
kwargs['region_id'] = region.id
- if project:
+ if project_id:
data = list(
- identity_client.project_endpoints(project=project.id)
+ identity_client.project_endpoints(project=project_id)
)
else:
data = list(identity_client.endpoints(**kwargs))
for ep in data:
- service = identity_client.find_service(ep.service_id)
+ service = identity_client.find_service(
+ ep.service_id, ignore_missing=False
+ )
ep.service_name = getattr(service, 'name', '')
ep.service_type = service.type
@@ -382,7 +399,9 @@ class SetEndpoint(command.Command):
def take_action(self, parsed_args):
identity_client = self.app.client_manager.sdk_connection.identity
- endpoint = identity_client.find_endpoint(parsed_args.endpoint)
+ endpoint = identity_client.find_endpoint(
+ parsed_args.endpoint, ignore_missing=False
+ )
kwargs = {}
@@ -429,7 +448,9 @@ class ShowEndpoint(command.ShowOne):
def take_action(self, parsed_args):
identity_client = self.app.client_manager.sdk_connection.identity
- endpoint = identity_client.find_endpoint(parsed_args.endpoint)
+ endpoint = identity_client.find_endpoint(
+ parsed_args.endpoint, ignore_missing=False
+ )
service = common.find_service_sdk(identity_client, endpoint.service_id)
diff --git a/openstackclient/identity/v3/endpoint_group.py b/openstackclient/identity/v3/endpoint_group.py
index e4611a1..3965f31 100644
--- a/openstackclient/identity/v3/endpoint_group.py
+++ b/openstackclient/identity/v3/endpoint_group.py
@@ -16,10 +16,10 @@
import json
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common
diff --git a/openstackclient/identity/v3/federation_protocol.py b/openstackclient/identity/v3/federation_protocol.py
index 4e98086..3e1dea1 100644
--- a/openstackclient/identity/v3/federation_protocol.py
+++ b/openstackclient/identity/v3/federation_protocol.py
@@ -16,16 +16,25 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
+def _format_protocol(protocol):
+ columns = ('name', 'idp_id', 'mapping_id')
+ column_headers = ('id', 'identity_provider', 'mapping')
+ return (
+ column_headers,
+ utils.get_item_properties(protocol, columns),
+ )
+
+
class CreateProtocol(command.ShowOne):
_description = _("Create new federation protocol")
@@ -58,21 +67,15 @@ class CreateProtocol(command.ShowOne):
return parser
def take_action(self, parsed_args):
- identity_client = self.app.client_manager.identity
- protocol = identity_client.federation.protocols.create(
- protocol_id=parsed_args.federation_protocol,
- identity_provider=parsed_args.identity_provider,
- mapping=parsed_args.mapping,
+ identity_client = self.app.client_manager.sdk_connection.identity
+
+ protocol = identity_client.create_federation_protocol(
+ name=parsed_args.federation_protocol,
+ idp_id=parsed_args.identity_provider,
+ mapping_id=parsed_args.mapping,
)
- info = dict(protocol._info)
- # NOTE(marek-denis): Identity provider is not included in a response
- # from Keystone, however it should be listed to the user. Add it
- # manually to the output list, simply reusing value provided by the
- # user.
- info['identity_provider'] = parsed_args.identity_provider
- info['mapping'] = info.pop('mapping_id')
- info.pop('links', None)
- return zip(*sorted(info.items()))
+
+ return _format_protocol(protocol)
class DeleteProtocol(command.Command):
@@ -99,12 +102,15 @@ class DeleteProtocol(command.Command):
return parser
def take_action(self, parsed_args):
- identity_client = self.app.client_manager.identity
+ identity_client = self.app.client_manager.sdk_connection.identity
+
result = 0
for i in parsed_args.federation_protocol:
try:
- identity_client.federation.protocols.delete(
- parsed_args.identity_provider, i
+ identity_client.delete_federation_protocol(
+ idp_id=parsed_args.identity_provider,
+ protocol=i,
+ ignore_missing=False,
)
except Exception as e:
result += 1
@@ -140,9 +146,9 @@ class ListProtocols(command.Lister):
return parser
def take_action(self, parsed_args):
- identity_client = self.app.client_manager.identity
+ identity_client = self.app.client_manager.sdk_connection.identity
- protocols = identity_client.federation.protocols.list(
+ protocols = identity_client.federation_protocols(
parsed_args.identity_provider
)
columns = ('id', 'mapping')
@@ -181,21 +187,16 @@ class SetProtocol(command.Command):
return parser
def take_action(self, parsed_args):
- identity_client = self.app.client_manager.identity
+ identity_client = self.app.client_manager.sdk_connection.identity
- protocol = identity_client.federation.protocols.update(
- parsed_args.identity_provider,
- parsed_args.federation_protocol,
- parsed_args.mapping,
- )
- info = dict(protocol._info)
- # NOTE(marek-denis): Identity provider is not included in a response
- # from Keystone, however it should be listed to the user. Add it
- # manually to the output list, simply reusing value provided by the
- # user.
- info['identity_provider'] = parsed_args.identity_provider
- info['mapping'] = info.pop('mapping_id')
- return zip(*sorted(info.items()))
+ kwargs = {'idp_id': parsed_args.identity_provider}
+ if parsed_args.federation_protocol:
+ kwargs['name'] = parsed_args.federation_protocol
+ if parsed_args.mapping:
+ kwargs['mapping_id'] = parsed_args.mapping
+
+ protocol = identity_client.update_federation_protocol(**kwargs)
+ return _format_protocol(protocol)
class ShowProtocol(command.ShowOne):
@@ -220,12 +221,10 @@ class ShowProtocol(command.ShowOne):
return parser
def take_action(self, parsed_args):
- identity_client = self.app.client_manager.identity
+ identity_client = self.app.client_manager.sdk_connection.identity
- protocol = identity_client.federation.protocols.get(
- parsed_args.identity_provider, parsed_args.federation_protocol
+ protocol = identity_client.get_federation_protocol(
+ idp_id=parsed_args.identity_provider,
+ protocol=parsed_args.federation_protocol,
)
- info = dict(protocol._info)
- info['mapping'] = info.pop('mapping_id')
- info.pop('links', None)
- return zip(*sorted(info.items()))
+ return _format_protocol(protocol)
diff --git a/openstackclient/identity/v3/group.py b/openstackclient/identity/v3/group.py
index 92980ac..a2c2fd3 100644
--- a/openstackclient/identity/v3/group.py
+++ b/openstackclient/identity/v3/group.py
@@ -18,10 +18,10 @@
import logging
from openstack import exceptions as sdk_exc
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common
@@ -211,10 +211,15 @@ class CreateGroup(command.ShowOne):
if parsed_args.or_show:
if parsed_args.domain:
group = identity_client.find_group(
- parsed_args.name, domain_id=parsed_args.domain
+ parsed_args.name,
+ domain_id=parsed_args.domain,
+ ignore_missing=False,
)
else:
- group = identity_client.find_group(parsed_args.name)
+ group = identity_client.find_group(
+ parsed_args.name,
+ ignore_missing=False,
+ )
LOG.info(_('Returning existing group %s'), group.name)
else:
raise
@@ -310,8 +315,9 @@ class ListGroup(command.Lister):
parsed_args.user_domain,
)
if domain:
- # NOTE(0weng): The API doesn't actually support filtering additionally by domain_id,
- # so this doesn't really do anything.
+ # NOTE(0weng): The API doesn't actually support filtering
+ # additionally by domain_id, so this doesn't really do
+ # anything.
data = identity_client.user_groups(user, domain_id=domain)
else:
data = identity_client.user_groups(user)
diff --git a/openstackclient/identity/v3/identity_provider.py b/openstackclient/identity/v3/identity_provider.py
index d0c3243..f1af03f 100644
--- a/openstackclient/identity/v3/identity_provider.py
+++ b/openstackclient/identity/v3/identity_provider.py
@@ -16,10 +16,10 @@
import logging
from osc_lib.cli import format_columns
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common
@@ -41,6 +41,7 @@ class CreateIdentityProvider(command.ShowOne):
identity_remote_id_provider.add_argument(
'--remote-id',
metavar='<remote-id>',
+ dest='remote_ids',
action='append',
help=_(
'Remote IDs to associate with the Identity Provider '
@@ -99,16 +100,15 @@ class CreateIdentityProvider(command.ShowOne):
def take_action(self, parsed_args):
identity_client = self.app.client_manager.identity
+ remote_ids: list[str] | None = None
if parsed_args.remote_id_file:
file_content = utils.read_blob_file_contents(
parsed_args.remote_id_file
)
remote_ids = file_content.splitlines()
remote_ids = list(map(str.strip, remote_ids))
- else:
- remote_ids = (
- parsed_args.remote_id if parsed_args.remote_id else None
- )
+ elif parsed_args.remote_ids:
+ remote_ids = parsed_args.remote_ids
domain_id = None
if parsed_args.domain:
@@ -137,8 +137,9 @@ class CreateIdentityProvider(command.ShowOne):
)
idp._info.pop('links', None)
- remote_ids = format_columns.ListColumn(idp._info.pop('remote_ids', []))
- idp._info['remote_ids'] = remote_ids
+ idp._info['remote_ids'] = format_columns.ListColumn(
+ idp._info.pop('remote_ids', [])
+ )
return zip(*sorted(idp._info.items()))
@@ -240,6 +241,7 @@ class SetIdentityProvider(command.Command):
identity_remote_id_provider.add_argument(
'--remote-id',
metavar='<remote-id>',
+ dest='remote_ids',
action='append',
help=_(
'Remote IDs to associate with the Identity Provider '
@@ -287,8 +289,8 @@ class SetIdentityProvider(command.Command):
)
remote_ids = file_content.splitlines()
remote_ids = list(map(str.strip, remote_ids))
- elif parsed_args.remote_id:
- remote_ids = parsed_args.remote_id
+ elif parsed_args.remote_ids:
+ remote_ids = parsed_args.remote_ids
# Setup keyword args for the client
kwargs = {}
@@ -298,7 +300,7 @@ class SetIdentityProvider(command.Command):
kwargs['enabled'] = True
if parsed_args.disable:
kwargs['enabled'] = False
- if parsed_args.remote_id_file or parsed_args.remote_id:
+ if parsed_args.remote_id_file or parsed_args.remote_ids:
kwargs['remote_ids'] = remote_ids
# TODO(pas-ha) actually check for 3.14 microversion
diff --git a/openstackclient/identity/v3/implied_role.py b/openstackclient/identity/v3/implied_role.py
index 3958896..c1236ad 100644
--- a/openstackclient/identity/v3/implied_role.py
+++ b/openstackclient/identity/v3/implied_role.py
@@ -17,8 +17,8 @@
import logging
-from osc_lib.command import command
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/identity/v3/limit.py b/openstackclient/identity/v3/limit.py
index 7f2fe88..94f6bca 100644
--- a/openstackclient/identity/v3/limit.py
+++ b/openstackclient/identity/v3/limit.py
@@ -15,16 +15,38 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common as common_utils
LOG = logging.getLogger(__name__)
+def _format_limit(limit):
+ columns = (
+ "description",
+ "id",
+ "project_id",
+ "region_id",
+ "resource_limit",
+ "resource_name",
+ "service_id",
+ )
+ column_headers = (
+ "description",
+ "id",
+ "project_id",
+ "region_id",
+ "resource_limit",
+ "resource_name",
+ "service_id",
+ )
+ return (column_headers, utils.get_item_properties(limit, columns))
+
+
class CreateLimit(command.ShowOne):
_description = _("Create a limit")
@@ -46,6 +68,7 @@ class CreateLimit(command.ShowOne):
required=True,
help=_('Project to associate the resource limit to'),
)
+ common_utils.add_project_domain_option_to_parser(parser)
parser.add_argument(
'--service',
metavar='<service>',
@@ -67,47 +90,33 @@ class CreateLimit(command.ShowOne):
return parser
def take_action(self, parsed_args):
- identity_client = self.app.client_manager.identity
-
- project = common_utils.find_project(
- identity_client, parsed_args.project
+ identity_client = self.app.client_manager.sdk_connection.identity
+
+ kwargs = {
+ "resource_name": parsed_args.resource_name,
+ "resource_limit": parsed_args.resource_limit,
+ }
+ if parsed_args.description:
+ kwargs["description"] = parsed_args.description
+
+ kwargs["project_id"] = common_utils.find_project_id_sdk(
+ identity_client,
+ parsed_args.project,
+ domain_name_or_id=parsed_args.project_domain,
)
- service = common_utils.find_service(
+
+ kwargs["service_id"] = common_utils.find_service_sdk(
identity_client, parsed_args.service
- )
- region = None
+ ).id
+
if parsed_args.region:
- if 'None' not in parsed_args.region:
- # NOTE (vishakha): Due to bug #1799153 and for any another
- # related case where GET resource API does not support the
- # filter by name, osc_lib.utils.find_resource() method cannot
- # be used because that method try to fall back to list all the
- # resource if requested resource cannot be get via name. Which
- # ends up with NoUniqueMatch error.
- # So osc_lib.utils.find_resource() function cannot be used for
- # 'regions', using common_utils.get_resource() instead.
- region = common_utils.get_resource(
- identity_client.regions, parsed_args.region
- )
- else:
- self.log.warning(
- _(
- "Passing 'None' to indicate no region is deprecated. "
- "Instead, don't pass --region."
- )
- )
+ kwargs["region_id"] = identity_client.get_region(
+ parsed_args.region
+ ).id
- limit = identity_client.limits.create(
- project,
- service,
- parsed_args.resource_name,
- parsed_args.resource_limit,
- description=parsed_args.description,
- region=region,
- )
+ limit = identity_client.create_limit(**kwargs)
- limit._info.pop('links', None)
- return zip(*sorted(limit._info.items()))
+ return _format_limit(limit)
class ListLimit(command.Lister):
@@ -136,50 +145,41 @@ class ListLimit(command.Lister):
metavar='<project>',
help=_('List resource limits associated with project'),
)
+ common_utils.add_project_domain_option_to_parser(parser)
+
return parser
def take_action(self, parsed_args):
- identity_client = self.app.client_manager.identity
+ identity_client = self.app.client_manager.sdk_connection.identity
- service = None
+ kwargs = {}
if parsed_args.service:
- service = common_utils.find_service(
+ kwargs["service_id"] = common_utils.find_service_sdk(
identity_client, parsed_args.service
)
- region = None
+
if parsed_args.region:
- if 'None' not in parsed_args.region:
- # NOTE (vishakha): Due to bug #1799153 and for any another
- # related case where GET resource API does not support the
- # filter by name, osc_lib.utils.find_resource() method cannot
- # be used because that method try to fall back to list all the
- # resource if requested resource cannot be get via name. Which
- # ends up with NoUniqueMatch error.
- # So osc_lib.utils.find_resource() function cannot be used for
- # 'regions', using common_utils.get_resource() instead.
- region = common_utils.get_resource(
- identity_client.regions, parsed_args.region
- )
- else:
- self.log.warning(
- _(
- "Passing 'None' to indicate no region is deprecated. "
- "Instead, don't pass --region."
- )
- )
+ kwargs["region_id"] = identity_client.get_region(
+ parsed_args.region
+ ).id
- project = None
if parsed_args.project:
- project = utils.find_resource(
- identity_client.projects, parsed_args.project
+ project_domain_id = None
+ if parsed_args.project_domain:
+ project_domain_id = common_utils.find_domain_id_sdk(
+ identity_client, parsed_args.project_domain
+ )
+
+ kwargs["project_id"] = common_utils._find_sdk_id(
+ identity_client.find_project,
+ name_or_id=parsed_args.project,
+ domain_id=project_domain_id,
)
- limits = identity_client.limits.list(
- service=service,
- resource_name=parsed_args.resource_name,
- region=region,
- project=project,
- )
+ if parsed_args.resource_name:
+ kwargs["resource_name"] = parsed_args.resource_name
+
+ limits = identity_client.limits(**kwargs)
columns = (
'ID',
@@ -209,10 +209,9 @@ class ShowLimit(command.ShowOne):
return parser
def take_action(self, parsed_args):
- identity_client = self.app.client_manager.identity
- limit = identity_client.limits.get(parsed_args.limit_id)
- limit._info.pop('links', None)
- return zip(*sorted(limit._info.items()))
+ identity_client = self.app.client_manager.sdk_connection.identity
+ limit = identity_client.get_limit(parsed_args.limit_id)
+ return _format_limit(limit)
class SetLimit(command.ShowOne):
@@ -240,17 +239,16 @@ class SetLimit(command.ShowOne):
return parser
def take_action(self, parsed_args):
- identity_client = self.app.client_manager.identity
-
- limit = identity_client.limits.update(
- parsed_args.limit_id,
- description=parsed_args.description,
- resource_limit=parsed_args.resource_limit,
- )
+ identity_client = self.app.client_manager.sdk_connection.identity
- limit._info.pop('links', None)
+ kwargs = {}
+ if parsed_args.description:
+ kwargs["description"] = parsed_args.description
+ if parsed_args.resource_limit:
+ kwargs["resource_limit"] = parsed_args.resource_limit
+ limit = identity_client.update_limit(parsed_args.limit_id, **kwargs)
- return zip(*sorted(limit._info.items()))
+ return _format_limit(limit)
class DeleteLimit(command.Command):
@@ -262,17 +260,20 @@ class DeleteLimit(command.Command):
'limit_id',
metavar='<limit-id>',
nargs="+",
- help=_('Limit to delete (ID)'),
+ help=_(
+ 'Limit to delete (ID) '
+ '(repeat option to remove multiple limits)'
+ ),
)
return parser
def take_action(self, parsed_args):
- identity_client = self.app.client_manager.identity
+ identity_client = self.app.client_manager.sdk_connection.identity
errors = 0
for limit_id in parsed_args.limit_id:
try:
- identity_client.limits.delete(limit_id)
+ identity_client.delete_limit(limit_id)
except Exception as e:
errors += 1
LOG.error(
diff --git a/openstackclient/identity/v3/mapping.py b/openstackclient/identity/v3/mapping.py
index 8c2d0bf..a041f19 100644
--- a/openstackclient/identity/v3/mapping.py
+++ b/openstackclient/identity/v3/mapping.py
@@ -18,10 +18,10 @@
import json
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/identity/v3/policy.py b/openstackclient/identity/v3/policy.py
index d5b8fec..3554903 100644
--- a/openstackclient/identity/v3/policy.py
+++ b/openstackclient/identity/v3/policy.py
@@ -17,10 +17,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/identity/v3/project.py b/openstackclient/identity/v3/project.py
index 3832154..9924239 100644
--- a/openstackclient/identity/v3/project.py
+++ b/openstackclient/identity/v3/project.py
@@ -17,12 +17,12 @@
import logging
-from keystoneauth1 import exceptions as ks_exc
+from openstack import exceptions as sdk_exc
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common
from openstackclient.identity.v3 import tag
@@ -30,6 +30,21 @@ from openstackclient.identity.v3 import tag
LOG = logging.getLogger(__name__)
+def _format_project(project):
+ # NOTE(0weng): Projects allow unknown attributes in the body, so extract
+ # the column names separately.
+ (column_headers, columns) = utils.get_osc_show_columns_for_sdk_resource(
+ project,
+ {'is_enabled': 'enabled'},
+ ['links', 'location', 'parents_as_ids', 'subtree_as_ids'],
+ )
+
+ return (
+ column_headers,
+ utils.get_item_properties(project, columns),
+ )
+
+
class CreateProject(command.ShowOne):
_description = _("Create new project")
@@ -73,8 +88,8 @@ class CreateProject(command.ShowOne):
parser.add_argument(
'--property',
metavar='<key=value>',
- action=parseractions.KeyValueAction,
dest='properties',
+ action=parseractions.KeyValueAction,
help=_(
'Add a property to <name> '
'(repeat option to set multiple properties)'
@@ -90,22 +105,13 @@ class CreateProject(command.ShowOne):
return parser
def take_action(self, parsed_args):
- identity_client = self.app.client_manager.identity
-
- domain = None
- if parsed_args.domain:
- domain = common.find_domain(identity_client, parsed_args.domain).id
-
- parent = None
- if parsed_args.parent:
- parent = utils.find_resource(
- identity_client.projects,
- parsed_args.parent,
- ).id
+ identity_client = self.app.client_manager.sdk_connection.identity
kwargs = {}
+
if parsed_args.properties:
kwargs = parsed_args.properties.copy()
+
if 'is_domain' in kwargs.keys():
if kwargs['is_domain'].lower() == "true":
kwargs['is_domain'] = True
@@ -114,39 +120,66 @@ class CreateProject(command.ShowOne):
elif kwargs['is_domain'].lower() == "none":
kwargs['is_domain'] = None
- kwargs['tags'] = list(set(parsed_args.tags))
+ if parsed_args.description:
+ kwargs['description'] = parsed_args.description
+
+ if parsed_args.name:
+ kwargs['name'] = parsed_args.name
+
+ domain = None
+ if parsed_args.domain:
+ domain = common.find_domain_id_sdk(
+ identity_client, parsed_args.domain
+ )
+ kwargs['domain_id'] = domain
+
+ if parsed_args.parent:
+ kwargs['parent_id'] = common.find_project_id_sdk(
+ identity_client,
+ parsed_args.parent,
+ domain_name_or_id=domain,
+ )
+
+ kwargs['is_enabled'] = parsed_args.enabled
+
+ if parsed_args.tags:
+ kwargs['tags'] = list(set(parsed_args.tags))
- options = {}
if parsed_args.immutable is not None:
- options['immutable'] = parsed_args.immutable
+ kwargs['options'] = {'immutable': parsed_args.immutable}
try:
- project = identity_client.projects.create(
- name=parsed_args.name,
- domain=domain,
- parent=parent,
- description=parsed_args.description,
- enabled=parsed_args.enabled,
- options=options,
+ project = identity_client.create_project(
**kwargs,
)
- except ks_exc.Conflict:
+ except sdk_exc.ConflictException:
if parsed_args.or_show:
- project = utils.find_resource(
- identity_client.projects,
- parsed_args.name,
- domain_id=domain,
- )
+ if parsed_args.domain:
+ project = identity_client.find_project(
+ parsed_args.name,
+ domain_id=domain,
+ ignore_missing=False,
+ )
+ else:
+ project = identity_client.find_project(
+ parsed_args.name, ignore_missing=False
+ )
LOG.info(_('Returning existing project %s'), project.name)
else:
raise
- project._info.pop('links')
- return zip(*sorted(project._info.items()))
+ return _format_project(project)
class DeleteProject(command.Command):
- _description = _("Delete project(s)")
+ _description = _(
+ "Delete project(s). This command will remove specified "
+ "existing project(s) if an active user is authorized to do "
+ "this. If there are resources managed by other services "
+ "(for example, Nova, Neutron, Cinder) associated with "
+ "specified project(s), delete operation will proceed "
+ "regardless."
+ )
def get_parser(self, prog_name):
parser = super().get_parser(prog_name)
@@ -164,23 +197,19 @@ class DeleteProject(command.Command):
return parser
def take_action(self, parsed_args):
- identity_client = self.app.client_manager.identity
+ identity_client = self.app.client_manager.sdk_connection.identity
- domain = None
- if parsed_args.domain:
- domain = common.find_domain(identity_client, parsed_args.domain)
errors = 0
for project in parsed_args.projects:
try:
- if domain is not None:
- project_obj = utils.find_resource(
- identity_client.projects, project, domain_id=domain.id
- )
- else:
- project_obj = utils.find_resource(
- identity_client.projects, project
- )
- identity_client.projects.delete(project_obj.id)
+ project = common.find_project_id_sdk(
+ identity_client,
+ project,
+ domain_name_or_id=parsed_args.domain,
+ validate_actor_existence=True,
+ validate_domain_actor_existence=False,
+ )
+ identity_client.delete_project(project)
except Exception as e:
errors += 1
LOG.error(
@@ -261,38 +290,46 @@ class ListProject(command.Lister):
return parser
def take_action(self, parsed_args):
- identity_client = self.app.client_manager.identity
- columns: tuple[str, ...] = ('ID', 'Name')
+ identity_client = self.app.client_manager.sdk_connection.identity
+
+ column_headers: tuple[str, ...] = ('ID', 'Name')
+ if parsed_args.long:
+ column_headers += ('Domain ID', 'Description', 'Enabled')
+
+ columns: tuple[str, ...] = ('id', 'name')
if parsed_args.long:
- columns += ('Domain ID', 'Description', 'Enabled')
+ columns += ('domain_id', 'description', 'is_enabled')
+
kwargs = {}
domain_id = None
if parsed_args.domain:
- domain_id = common.find_domain(
+ domain_id = common.find_domain_id_sdk(
identity_client, parsed_args.domain
- ).id
- kwargs['domain'] = domain_id
+ )
+ kwargs['domain_id'] = domain_id
if parsed_args.parent:
- parent_id = common.find_project(
- identity_client, parsed_args.parent
- ).id
- kwargs['parent'] = parent_id
+ parent_id = common.find_project_id_sdk(
+ identity_client,
+ parsed_args.parent,
+ domain_name_or_id=domain_id,
+ )
+ kwargs['parent_id'] = parent_id
+ user = None
if parsed_args.user:
if parsed_args.domain:
- user_id = utils.find_resource(
- identity_client.users,
+ user = common.find_user_id_sdk(
+ identity_client,
parsed_args.user,
- domain_id=domain_id,
- ).id
+ domain_name_or_id=domain_id,
+ )
else:
- user_id = utils.find_resource(
- identity_client.users, parsed_args.user
- ).id
-
- kwargs['user'] = user_id
+ user = common.find_user_id_sdk(
+ identity_client,
+ parsed_args.user,
+ )
if parsed_args.is_enabled is not None:
kwargs['is_enabled'] = parsed_args.is_enabled
@@ -301,32 +338,29 @@ class ListProject(command.Lister):
if parsed_args.my_projects:
# NOTE(adriant): my-projects supersedes all the other filters.
- kwargs = {'user': self.app.client_manager.auth_ref.user_id}
+ kwargs = {}
+ user = self.app.client_manager.auth_ref.user_id
- try:
- data = identity_client.projects.list(**kwargs)
- except ks_exc.Forbidden:
- # NOTE(adriant): if no filters, assume a forbidden is non-admin
- # wanting their own project list.
- if not kwargs:
- user = self.app.client_manager.auth_ref.user_id
- data = identity_client.projects.list(user=user)
- else:
- raise
+ if user:
+ data = identity_client.user_projects(user, **kwargs)
+ else:
+ try:
+ data = identity_client.projects(**kwargs)
+ except sdk_exc.ForbiddenException:
+ # NOTE(adriant): if no filters, assume a forbidden is non-admin
+ # wanting their own project list.
+ if not kwargs:
+ user = self.app.client_manager.auth_ref.user_id
+ data = identity_client.user_projects(user)
+ else:
+ raise
if parsed_args.sort:
data = utils.sort_items(data, parsed_args.sort)
return (
- columns,
- (
- utils.get_item_properties(
- s,
- columns,
- formatters={},
- )
- for s in data
- ),
+ column_headers,
+ (utils.get_item_properties(s, columns) for s in data),
)
@@ -385,11 +419,7 @@ class SetProject(command.Command):
return parser
def take_action(self, parsed_args):
- identity_client = self.app.client_manager.identity
-
- project = common.find_project(
- identity_client, parsed_args.project, parsed_args.domain
- )
+ identity_client = self.app.client_manager.sdk_connection.identity
kwargs = {}
if parsed_args.name:
@@ -402,9 +432,50 @@ class SetProject(command.Command):
kwargs['options'] = {'immutable': parsed_args.immutable}
if parsed_args.properties:
kwargs.update(parsed_args.properties)
- tag.update_tags_in_args(parsed_args, project, kwargs)
- identity_client.projects.update(project.id, **kwargs)
+ if parsed_args.domain:
+ domain = common.find_domain_id_sdk(
+ identity_client,
+ parsed_args.domain,
+ validate_actor_existence=False,
+ )
+ project = identity_client.find_project(
+ parsed_args.project,
+ domain_id=domain,
+ ignore_missing=True,
+ )
+ else:
+ project = identity_client.find_project(
+ parsed_args.project,
+ ignore_missing=True,
+ )
+
+ if (
+ parsed_args.tags
+ or parsed_args.remove_tags
+ or parsed_args.clear_tags
+ ):
+ existing_tags = []
+ if project:
+ existing_tags = project.tags
+
+ if parsed_args.clear_tags:
+ kwargs['tags'] = []
+ else:
+ existing_tags_set = set(existing_tags)
+ if parsed_args.remove_tags:
+ tags = sorted(
+ existing_tags_set - set(parsed_args.remove_tags)
+ )
+ if parsed_args.tags:
+ tags = sorted(
+ existing_tags_set.union(set(parsed_args.tags))
+ )
+ kwargs['tags'] = tags
+
+ project_id = project.id if project else parsed_args.project
+
+ identity_client.update_project(project_id, **kwargs)
class ShowProject(command.ShowOne):
@@ -437,31 +508,36 @@ class ShowProject(command.ShowOne):
return parser
def take_action(self, parsed_args):
- identity_client = self.app.client_manager.identity
+ identity_client = self.app.client_manager.sdk_connection.identity
- project_str = common._get_token_resource(
- identity_client, 'project', parsed_args.project, parsed_args.domain
- )
+ kwargs = {}
+ domain = None
if parsed_args.domain:
- domain = common.find_domain(identity_client, parsed_args.domain)
- project = utils.find_resource(
- identity_client.projects, project_str, domain_id=domain.id
- )
- else:
- project = utils.find_resource(
- identity_client.projects, project_str
+ domain = common.find_domain_id_sdk(
+ identity_client, parsed_args.domain
)
- if parsed_args.parents or parsed_args.children:
- # NOTE(RuiChen): utils.find_resource() can't pass kwargs,
- # if id query hit the result at first, so call
- # identity manager.get() with kwargs directly.
- project = identity_client.projects.get(
- project.id,
- parents_as_ids=parsed_args.parents,
- subtree_as_ids=parsed_args.children,
- )
+ kwargs['domain_id'] = domain
+
+ # Get project id first; otherwise, find_project() can't find
+ # parents/children if only project name was given
+ project = common.find_project_id_sdk(
+ identity_client,
+ parsed_args.project,
+ domain_name_or_id=domain,
+ validate_actor_existence=False,
+ validate_domain_actor_existence=False,
+ )
+
+ # Include these options as query parameters if they are provided
+ if parsed_args.parents:
+ kwargs['parents_as_ids'] = True
+ if parsed_args.children:
+ kwargs['subtree_as_ids'] = True
+
+ project = identity_client.find_project(
+ project, **kwargs, ignore_missing=False
+ )
- project._info.pop('links')
- return zip(*sorted(project._info.items()))
+ return _format_project(project)
diff --git a/openstackclient/identity/v3/region.py b/openstackclient/identity/v3/region.py
index 40d3819..4882c9e 100644
--- a/openstackclient/identity/v3/region.py
+++ b/openstackclient/identity/v3/region.py
@@ -15,10 +15,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/identity/v3/registered_limit.py b/openstackclient/identity/v3/registered_limit.py
index 34ce210..4be829b 100644
--- a/openstackclient/identity/v3/registered_limit.py
+++ b/openstackclient/identity/v3/registered_limit.py
@@ -15,16 +15,39 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common as common_utils
LOG = logging.getLogger(__name__)
+def _format_registered_limit(registered_limit):
+ columns = (
+ 'default_limit',
+ 'description',
+ 'id',
+ 'region_id',
+ 'resource_name',
+ 'service_id',
+ )
+ column_headers = (
+ 'default_limit',
+ 'description',
+ 'id',
+ 'region_id',
+ 'resource_name',
+ 'service_id',
+ )
+ return (
+ column_headers,
+ utils.get_item_properties(registered_limit, columns),
+ )
+
+
class CreateRegisteredLimit(command.ShowOne):
_description = _("Create a registered limit")
@@ -44,7 +67,10 @@ class CreateRegisteredLimit(command.ShowOne):
'--service',
metavar='<service>',
required=True,
- help=_('Service responsible for the resource to limit (required)'),
+ help=_(
+ 'Service responsible for the resource to limit (required) '
+ '(name or ID)'
+ ),
)
parser.add_argument(
'--default-limit',
@@ -61,43 +87,28 @@ class CreateRegisteredLimit(command.ShowOne):
return parser
def take_action(self, parsed_args):
- identity_client = self.app.client_manager.identity
+ identity_client = self.app.client_manager.sdk_connection.identity
+
+ kwargs = {}
+
+ if parsed_args.description:
+ kwargs["description"] = parsed_args.description
+
+ kwargs["service_id"] = common_utils.find_service_sdk(
+ identity_client, parsed_args.service
+ ).id
- service = utils.find_resource(
- identity_client.services, parsed_args.service
- )
- region = None
if parsed_args.region:
- if 'None' not in parsed_args.region:
- # NOTE (vishakha): Due to bug #1799153 and for any another
- # related case where GET resource API does not support the
- # filter by name, osc_lib.utils.find_resource() method cannot
- # be used because that method try to fall back to list all the
- # resource if requested resource cannot be get via name. Which
- # ends up with NoUniqueMatch error.
- # So osc_lib.utils.find_resource() function cannot be used for
- # 'regions', using common_utils.get_resource() instead.
- region = common_utils.get_resource(
- identity_client.regions, parsed_args.region
- )
- else:
- self.log.warning(
- _(
- "Passing 'None' to indicate no region is deprecated. "
- "Instead, don't pass --region."
- )
- )
+ kwargs["region_id"] = identity_client.get_region(
+ parsed_args.region
+ ).id
- registered_limit = identity_client.registered_limits.create(
- service,
- parsed_args.resource_name,
- parsed_args.default_limit,
- description=parsed_args.description,
- region=region,
- )
+ kwargs["resource_name"] = parsed_args.resource_name
+ kwargs["default_limit"] = parsed_args.default_limit
- registered_limit._info.pop('links', None)
- return zip(*sorted(registered_limit._info.items()))
+ registered_limit = identity_client.create_registered_limit(**kwargs)
+
+ return _format_registered_limit(registered_limit)
class DeleteRegisteredLimit(command.Command):
@@ -106,20 +117,25 @@ class DeleteRegisteredLimit(command.Command):
def get_parser(self, prog_name):
parser = super().get_parser(prog_name)
parser.add_argument(
- 'registered_limit_id',
- metavar='<registered-limit-id>',
+ 'registered_limits',
+ metavar='<registered-limits>',
nargs="+",
- help=_('Registered limit to delete (ID)'),
+ help=_(
+ 'Registered limit(s) to delete (ID) '
+ '(repeat option to remove multiple registered limits)'
+ ),
)
return parser
def take_action(self, parsed_args):
- identity_client = self.app.client_manager.identity
+ identity_client = self.app.client_manager.sdk_connection.identity
errors = 0
- for registered_limit_id in parsed_args.registered_limit_id:
+ for registered_limit_id in parsed_args.registered_limits:
try:
- identity_client.registered_limits.delete(registered_limit_id)
+ identity_client.delete_registered_limit(
+ registered_limit_id, ignore_missing=False
+ )
except Exception as e:
errors += 1
from pprint import pprint
@@ -134,7 +150,7 @@ class DeleteRegisteredLimit(command.Command):
)
if errors > 0:
- total = len(parsed_args.registered_limit_id)
+ total = len(parsed_args.registered_limits)
msg = _(
"%(errors)s of %(total)s registered limits failed to delete."
) % {'errors': errors, 'total': total}
@@ -149,7 +165,9 @@ class ListRegisteredLimit(command.Lister):
parser.add_argument(
'--service',
metavar='<service>',
- help=_('Service responsible for the resource to limit'),
+ help=_(
+ 'Service responsible for the resource to limit (name or ID)'
+ ),
)
parser.add_argument(
'--resource-name',
@@ -165,40 +183,22 @@ class ListRegisteredLimit(command.Lister):
return parser
def take_action(self, parsed_args):
- identity_client = self.app.client_manager.identity
+ identity_client = self.app.client_manager.sdk_connection.identity
- service = None
+ kwargs = {}
if parsed_args.service:
- service = common_utils.find_service(
+ kwargs["service_id"] = common_utils.find_service_sdk(
identity_client, parsed_args.service
- )
- region = None
+ ).id
if parsed_args.region:
- if 'None' not in parsed_args.region:
- # NOTE (vishakha): Due to bug #1799153 and for any another
- # related case where GET resource API does not support the
- # filter by name, osc_lib.utils.find_resource() method cannot
- # be used because that method try to fall back to list all the
- # resource if requested resource cannot be get via name. Which
- # ends up with NoUniqueMatch error.
- # So osc_lib.utils.find_resource() function cannot be used for
- # 'regions', using common_utils.get_resource() instead.
- region = common_utils.get_resource(
- identity_client.regions, parsed_args.region
- )
- else:
- self.log.warning(
- _(
- "Passing 'None' to indicate no region is deprecated. "
- "Instead, don't pass --region."
- )
- )
+ kwargs["region_id"] = identity_client.get_region(
+ parsed_args.region
+ ).id
- registered_limits = identity_client.registered_limits.list(
- service=service,
- resource_name=parsed_args.resource_name,
- region=region,
- )
+ if parsed_args.resource_name:
+ kwargs["resource_name"] = parsed_args.resource_name
+
+ registered_limits = identity_client.registered_limits(**kwargs)
columns = (
'ID',
@@ -228,9 +228,9 @@ class SetRegisteredLimit(command.ShowOne):
'--service',
metavar='<service>',
help=_(
- 'Service to be updated responsible for the resource to '
- 'limit. Either --service, --resource-name or --region must '
- 'be different than existing value otherwise it will be '
+ 'Service to be updated responsible for the resource to limit '
+ '(name or ID). Either --service, --resource-name or --region '
+ 'must be different than existing value otherwise it will be '
'duplicate entry'
),
)
@@ -268,44 +268,33 @@ class SetRegisteredLimit(command.ShowOne):
return parser
def take_action(self, parsed_args):
- identity_client = self.app.client_manager.identity
+ identity_client = self.app.client_manager.sdk_connection.identity
- service = None
+ kwargs = {}
if parsed_args.service:
- service = common_utils.find_service(
+ kwargs["service_id"] = common_utils.find_service_sdk(
identity_client, parsed_args.service
- )
+ ).id
+
+ if parsed_args.resource_name:
+ kwargs["resource_name"] = parsed_args.resource_name
+
+ if parsed_args.default_limit:
+ kwargs["default_limit"] = parsed_args.default_limit
+
+ if parsed_args.description:
+ kwargs["description"] = parsed_args.description
- region = None
if parsed_args.region:
- if 'None' not in parsed_args.region:
- # NOTE (vishakha): Due to bug #1799153 and for any another
- # related case where GET resource API does not support the
- # filter by name, osc_lib.utils.find_resource() method cannot
- # be used because that method try to fall back to list all the
- # resource if requested resource cannot be get via name. Which
- # ends up with NoUniqueMatch error.
- # So osc_lib.utils.find_resource() function cannot be used for
- # 'regions', using common_utils.get_resource() instead.
- region = common_utils.get_resource(
- identity_client.regions, parsed_args.region
- )
- else:
- self.log.warning(
- _("Passing 'None' to indicate no region is deprecated.")
- )
+ kwargs["region_id"] = identity_client.get_region(
+ parsed_args.region
+ ).id
- registered_limit = identity_client.registered_limits.update(
- parsed_args.registered_limit_id,
- service=service,
- resource_name=parsed_args.resource_name,
- default_limit=parsed_args.default_limit,
- description=parsed_args.description,
- region=region,
+ registered_limit = identity_client.update_registered_limit(
+ parsed_args.registered_limit_id, **kwargs
)
- registered_limit._info.pop('links', None)
- return zip(*sorted(registered_limit._info.items()))
+ return _format_registered_limit(registered_limit)
class ShowRegisteredLimit(command.ShowOne):
@@ -321,9 +310,8 @@ class ShowRegisteredLimit(command.ShowOne):
return parser
def take_action(self, parsed_args):
- identity_client = self.app.client_manager.identity
- registered_limit = identity_client.registered_limits.get(
+ identity_client = self.app.client_manager.sdk_connection.identity
+ registered_limit = identity_client.get_registered_limit(
parsed_args.registered_limit_id
)
- registered_limit._info.pop('links', None)
- return zip(*sorted(registered_limit._info.items()))
+ return _format_registered_limit(registered_limit)
diff --git a/openstackclient/identity/v3/role.py b/openstackclient/identity/v3/role.py
index 3301c3f..3c580d6 100644
--- a/openstackclient/identity/v3/role.py
+++ b/openstackclient/identity/v3/role.py
@@ -18,10 +18,10 @@
import logging
from openstack import exceptions as sdk_exc
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common
@@ -82,32 +82,12 @@ def _add_identity_and_resource_options_to_parser(parser):
common.add_inherited_option_to_parser(parser)
-def _find_sdk_id(
- find_command, name_or_id, validate_actor_existence=True, **kwargs
-):
- try:
- resource = find_command(
- name_or_id=name_or_id, ignore_missing=False, **kwargs
- )
-
- # Mimic the behavior of
- # openstackclient.identity.common._find_identity_resource()
- # and ignore if we don't have permission to find a resource.
- except sdk_exc.ForbiddenException:
- return name_or_id
- except sdk_exc.ResourceNotFound as exc:
- if not validate_actor_existence:
- return name_or_id
- raise exceptions.CommandError from exc
- return resource.id
-
-
def _process_identity_and_resource_options(
parsed_args, identity_client, validate_actor_existence=True
):
def _find_user():
domain_id = (
- _find_sdk_id(
+ common._find_sdk_id(
identity_client.find_domain,
name_or_id=parsed_args.user_domain,
validate_actor_existence=validate_actor_existence,
@@ -115,7 +95,7 @@ def _process_identity_and_resource_options(
if parsed_args.user_domain
else None
)
- return _find_sdk_id(
+ return common._find_sdk_id(
identity_client.find_user,
name_or_id=parsed_args.user,
validate_actor_existence=validate_actor_existence,
@@ -124,7 +104,7 @@ def _process_identity_and_resource_options(
def _find_group():
domain_id = (
- _find_sdk_id(
+ common._find_sdk_id(
identity_client.find_domain,
name_or_id=parsed_args.group_domain,
validate_actor_existence=validate_actor_existence,
@@ -132,7 +112,7 @@ def _process_identity_and_resource_options(
if parsed_args.group_domain
else None
)
- return _find_sdk_id(
+ return common._find_sdk_id(
identity_client.find_group,
name_or_id=parsed_args.group,
validate_actor_existence=validate_actor_existence,
@@ -141,7 +121,7 @@ def _process_identity_and_resource_options(
def _find_project():
domain_id = (
- _find_sdk_id(
+ common._find_sdk_id(
identity_client.find_domain,
name_or_id=parsed_args.project_domain,
validate_actor_existence=validate_actor_existence,
@@ -149,7 +129,7 @@ def _process_identity_and_resource_options(
if parsed_args.project_domain
else None
)
- return _find_sdk_id(
+ return common._find_sdk_id(
identity_client.find_project,
name_or_id=parsed_args.project,
validate_actor_existence=validate_actor_existence,
@@ -162,7 +142,7 @@ def _process_identity_and_resource_options(
kwargs['system'] = parsed_args.system
elif parsed_args.user and parsed_args.domain:
kwargs['user'] = _find_user()
- kwargs['domain'] = _find_sdk_id(
+ kwargs['domain'] = common._find_sdk_id(
identity_client.find_domain,
name_or_id=parsed_args.domain,
validate_actor_existence=validate_actor_existence,
@@ -175,7 +155,7 @@ def _process_identity_and_resource_options(
kwargs['system'] = parsed_args.system
elif parsed_args.group and parsed_args.domain:
kwargs['group'] = _find_group()
- kwargs['domain'] = _find_sdk_id(
+ kwargs['domain'] = common._find_sdk_id(
identity_client.find_domain,
name_or_id=parsed_args.domain,
validate_actor_existence=validate_actor_existence,
@@ -228,10 +208,10 @@ class AddRole(command.Command):
domain_id = None
if parsed_args.role_domain:
- domain_id = _find_sdk_id(
+ domain_id = common._find_sdk_id(
identity_client.find_domain, name_or_id=parsed_args.role_domain
)
- role = _find_sdk_id(
+ role = common._find_sdk_id(
identity_client.find_role,
name_or_id=parsed_args.role,
domain_id=domain_id,
@@ -328,7 +308,7 @@ class CreateRole(command.ShowOne):
create_kwargs = {}
if parsed_args.domain:
- create_kwargs['domain_id'] = _find_sdk_id(
+ create_kwargs['domain_id'] = common._find_sdk_id(
identity_client.find_domain, name_or_id=parsed_args.domain
)
@@ -381,13 +361,13 @@ class DeleteRole(command.Command):
domain_id = None
if parsed_args.domain:
- domain_id = _find_sdk_id(
+ domain_id = common._find_sdk_id(
identity_client.find_domain, parsed_args.domain
)
errors = 0
for role in parsed_args.roles:
try:
- role_id = _find_sdk_id(
+ role_id = common._find_sdk_id(
identity_client.find_role,
name_or_id=role,
domain_id=domain_id,
@@ -430,6 +410,7 @@ class ListRole(command.Lister):
if parsed_args.domain:
domain = identity_client.find_domain(
name_or_id=parsed_args.domain,
+ ignore_missing=False,
)
data = identity_client.roles(domain_id=domain.id)
return (
@@ -482,11 +463,11 @@ class RemoveRole(command.Command):
domain_id = None
if parsed_args.role_domain:
- domain_id = _find_sdk_id(
+ domain_id = common._find_sdk_id(
identity_client.find_domain,
name_or_id=parsed_args.role_domain,
)
- role = _find_sdk_id(
+ role = common._find_sdk_id(
identity_client.find_role,
name_or_id=parsed_args.role,
domain_id=domain_id,
@@ -582,7 +563,7 @@ class SetRole(command.Command):
domain_id = None
if parsed_args.domain:
- domain_id = _find_sdk_id(
+ domain_id = common._find_sdk_id(
identity_client.find_domain,
name_or_id=parsed_args.domain,
)
@@ -591,7 +572,7 @@ class SetRole(command.Command):
if parsed_args.immutable is not None:
update_kwargs["options"] = {"immutable": parsed_args.immutable}
- role = _find_sdk_id(
+ role = common._find_sdk_id(
identity_client.find_role,
name_or_id=parsed_args.role,
domain_id=domain_id,
@@ -623,7 +604,7 @@ class ShowRole(command.ShowOne):
domain_id = None
if parsed_args.domain:
- domain_id = _find_sdk_id(
+ domain_id = common._find_sdk_id(
identity_client.find_domain,
name_or_id=parsed_args.domain,
)
diff --git a/openstackclient/identity/v3/role_assignment.py b/openstackclient/identity/v3/role_assignment.py
index 12e1527..78c010f 100644
--- a/openstackclient/identity/v3/role_assignment.py
+++ b/openstackclient/identity/v3/role_assignment.py
@@ -13,9 +13,7 @@
"""Identity v3 Assignment action implementations"""
-from openstack import exceptions as sdk_exceptions
-from osc_lib.command import command
-
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common
@@ -51,15 +49,6 @@ def _format_role_assignment_(assignment, include_names):
)
-def _find_sdk_id(find_command, name_or_id, **kwargs):
- try:
- return find_command(
- name_or_id=name_or_id, ignore_missing=False, **kwargs
- ).id
- except sdk_exceptions.ForbiddenException:
- return name_or_id
-
-
class ListRoleAssignment(command.Lister):
_description = _("List role assignments")
@@ -135,12 +124,12 @@ class ListRoleAssignment(command.Lister):
role_id = None
role_domain_id = None
if parsed_args.role_domain:
- role_domain_id = _find_sdk_id(
+ role_domain_id = common._find_sdk_id(
identity_client.find_domain,
name_or_id=parsed_args.role_domain,
)
if parsed_args.role:
- role_id = _find_sdk_id(
+ role_id = common._find_sdk_id(
identity_client.find_role,
name_or_id=parsed_args.role,
domain_id=role_domain_id,
@@ -148,21 +137,21 @@ class ListRoleAssignment(command.Lister):
user_domain_id = None
if parsed_args.user_domain:
- user_domain_id = _find_sdk_id(
+ user_domain_id = common._find_sdk_id(
identity_client.find_domain,
name_or_id=parsed_args.user_domain,
)
user_id = None
if parsed_args.user:
- user_id = _find_sdk_id(
+ user_id = common._find_sdk_id(
identity_client.find_user,
name_or_id=parsed_args.user,
domain_id=user_domain_id,
)
elif parsed_args.authuser:
if auth_ref:
- user_id = _find_sdk_id(
+ user_id = common._find_sdk_id(
identity_client.find_user,
name_or_id=auth_ref.user_id,
)
@@ -173,21 +162,21 @@ class ListRoleAssignment(command.Lister):
domain_id = None
if parsed_args.domain:
- domain_id = _find_sdk_id(
+ domain_id = common._find_sdk_id(
identity_client.find_domain,
name_or_id=parsed_args.domain,
)
project_domain_id = None
if parsed_args.project_domain:
- project_domain_id = _find_sdk_id(
+ project_domain_id = common._find_sdk_id(
identity_client.find_domain,
name_or_id=parsed_args.project_domain,
)
project_id = None
if parsed_args.project:
- project_id = _find_sdk_id(
+ project_id = common._find_sdk_id(
identity_client.find_project,
name_or_id=common._get_token_resource(
identity_client, 'project', parsed_args.project
@@ -196,21 +185,21 @@ class ListRoleAssignment(command.Lister):
)
elif parsed_args.authproject:
if auth_ref:
- project_id = _find_sdk_id(
+ project_id = common._find_sdk_id(
identity_client.find_project,
name_or_id=auth_ref.project_id,
)
group_domain_id = None
if parsed_args.group_domain:
- group_domain_id = _find_sdk_id(
+ group_domain_id = common._find_sdk_id(
identity_client.find_domain,
name_or_id=parsed_args.group_domain,
)
group_id = None
if parsed_args.group:
- group_id = _find_sdk_id(
+ group_id = common._find_sdk_id(
identity_client.find_group,
name_or_id=parsed_args.group,
domain_id=group_domain_id,
diff --git a/openstackclient/identity/v3/service.py b/openstackclient/identity/v3/service.py
index e8f4832..53a7062 100644
--- a/openstackclient/identity/v3/service.py
+++ b/openstackclient/identity/v3/service.py
@@ -17,10 +17,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common
diff --git a/openstackclient/identity/v3/service_provider.py b/openstackclient/identity/v3/service_provider.py
index 5b49cff..02aae66 100644
--- a/openstackclient/identity/v3/service_provider.py
+++ b/openstackclient/identity/v3/service_provider.py
@@ -15,10 +15,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/identity/v3/tag.py b/openstackclient/identity/v3/tag.py
index 0909fd1..f49a1ca 100644
--- a/openstackclient/identity/v3/tag.py
+++ b/openstackclient/identity/v3/tag.py
@@ -114,6 +114,7 @@ def add_tag_option_to_parser_for_set(parser, resource_name):
parser.add_argument(
'--remove-tag',
action='append',
+ dest='remove_tags',
metavar='<tag>',
default=[],
help=_(
@@ -122,14 +123,3 @@ def add_tag_option_to_parser_for_set(parser, resource_name):
)
% resource_name,
)
-
-
-def update_tags_in_args(parsed_args, obj, args):
- if parsed_args.clear_tags:
- args['tags'] = []
- obj.tags = []
- if parsed_args.remove_tag:
- args['tags'] = sorted(set(obj.tags) - set(parsed_args.remove_tag))
- return
- if parsed_args.tags:
- args['tags'] = sorted(set(obj.tags).union(set(parsed_args.tags)))
diff --git a/openstackclient/identity/v3/token.py b/openstackclient/identity/v3/token.py
index 5500ce1..05e374c 100644
--- a/openstackclient/identity/v3/token.py
+++ b/openstackclient/identity/v3/token.py
@@ -15,10 +15,10 @@
"""Identity v3 Token action implementations"""
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common
@@ -37,6 +37,7 @@ class AuthorizeRequestToken(command.ShowOne):
parser.add_argument(
'--role',
metavar='<role>',
+ dest='roles',
action='append',
default=[],
required=True,
@@ -52,7 +53,7 @@ class AuthorizeRequestToken(command.ShowOne):
# NOTE(stevemar): We want a list of role ids
roles = []
- for role in parsed_args.role:
+ for role in parsed_args.roles:
role_id = utils.find_resource(
identity_client.roles,
role,
diff --git a/openstackclient/identity/v3/trust.py b/openstackclient/identity/v3/trust.py
index df8e2f4..80808aa 100644
--- a/openstackclient/identity/v3/trust.py
+++ b/openstackclient/identity/v3/trust.py
@@ -18,10 +18,10 @@ import itertools
import logging
from openstack import exceptions as sdk_exceptions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common
@@ -179,7 +179,9 @@ class CreateTrust(command.ShowOne):
roles = []
for role in parsed_args.roles:
try:
- role_id = identity_client.find_role(role).id
+ role_id = identity_client.find_role(
+ role, ignore_missing=False
+ ).id
except sdk_exceptions.ForbiddenException:
role_id = role
roles.append({"id": role_id})
diff --git a/openstackclient/identity/v3/unscoped_saml.py b/openstackclient/identity/v3/unscoped_saml.py
index d26035d..e1efc15 100644
--- a/openstackclient/identity/v3/unscoped_saml.py
+++ b/openstackclient/identity/v3/unscoped_saml.py
@@ -17,9 +17,9 @@ The first step of federated auth is to fetch an unscoped token. From there,
the user can list domains and projects they are allowed to access, and request
a scoped token."""
-from osc_lib.command import command
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/identity/v3/user.py b/openstackclient/identity/v3/user.py
index fee7dbe..bec1c62 100644
--- a/openstackclient/identity/v3/user.py
+++ b/openstackclient/identity/v3/user.py
@@ -20,10 +20,10 @@ import logging
import typing as ty
from openstack import exceptions as sdk_exc
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common
@@ -82,9 +82,9 @@ def _get_options_for_user(identity_client, parsed_args):
options['multi_factor_auth_enabled'] = True
if parsed_args.disable_multi_factor_auth:
options['multi_factor_auth_enabled'] = False
- if parsed_args.multi_factor_auth_rule:
+ if parsed_args.multi_factor_auth_rules:
auth_rules = [
- rule.split(",") for rule in parsed_args.multi_factor_auth_rule
+ rule.split(",") for rule in parsed_args.multi_factor_auth_rules
]
if auth_rules:
options['multi_factor_auth_rules'] = auth_rules
@@ -175,7 +175,8 @@ def _add_user_options(parser):
parser.add_argument(
'--multi-factor-auth-rule',
metavar='<rule>',
- action="append",
+ dest='multi_factor_auth_rules',
+ action='append',
default=[],
help=_(
'Set multi-factor auth rules. For example, to set a rule '
@@ -298,6 +299,9 @@ class CreateUser(command.ShowOne):
"when a user does not have a password."
)
)
+ else:
+ kwargs['password'] = password
+
options = _get_options_for_user(identity_client, parsed_args)
if options:
kwargs['options'] = options
@@ -306,7 +310,6 @@ class CreateUser(command.ShowOne):
user = identity_client.create_user(
is_enabled=is_enabled,
name=parsed_args.name,
- password=password,
**kwargs,
)
except sdk_exc.ConflictException:
@@ -420,7 +423,8 @@ class ListUser(command.Lister):
dest='is_enabled',
default=None,
help=_(
- 'List only enabled users, does nothing with --project and --group'
+ 'List only enabled users, does nothing with '
+ '--project and --group'
),
)
parser.add_argument(
@@ -429,7 +433,8 @@ class ListUser(command.Lister):
dest='is_enabled',
default=None,
help=_(
- 'List only disabled users, does nothing with --project and --group'
+ 'List only disabled users, does nothing with '
+ '--project and --group'
),
)
return parser
@@ -441,6 +446,7 @@ class ListUser(command.Lister):
if parsed_args.domain:
domain = identity_client.find_domain(
name_or_id=parsed_args.domain,
+ ignore_missing=False,
).id
group = None
@@ -467,15 +473,13 @@ class ListUser(command.Lister):
ignore_missing=False,
).id
- assignments = identity_client.role_assignments_filter(
- project=project
- )
-
# NOTE(stevemar): If a user has more than one role on a project
# then they will have two entries in the returned data. Since we
# are looking for any role, let's just track unique user IDs.
user_ids = set()
- for assignment in assignments:
+ for assignment in identity_client.role_assignments(
+ scope_project_id=project
+ ):
if assignment.user:
user_ids.add(assignment.user['id'])
@@ -689,7 +693,12 @@ class SetPasswordUser(command.Command):
def take_action(self, parsed_args):
identity_client = self.app.client_manager.sdk_connection.identity
conn = self.app.client_manager.sdk_connection
- user_id = conn.config.get_auth().get_user_id(conn.identity)
+ auth = conn.config.get_auth()
+ if auth is None:
+ # this will never happen
+ raise exceptions.CommandError('invalid authentication info')
+
+ user_id = auth.get_user_id(conn.identity)
# FIXME(gyee): there are two scenarios:
#
diff --git a/openstackclient/image/v1/image.py b/openstackclient/image/v1/image.py
index 91b0db4..0ea7eca 100644
--- a/openstackclient/image/v1/image.py
+++ b/openstackclient/image/v1/image.py
@@ -19,15 +19,16 @@ import argparse
import logging
import os
import sys
+import typing as ty
from cliff import columns as cliff_columns
from osc_lib.api import utils as api_utils
from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
CONTAINER_CHOICES = ["ami", "ari", "aki", "bare", "docker", "ova", "ovf"]
@@ -67,10 +68,7 @@ def _get_columns(item):
)
-_formatters = {}
-
-
-class HumanReadableSizeColumn(cliff_columns.FormattableColumn):
+class HumanReadableSizeColumn(cliff_columns.FormattableColumn[int]):
def human_readable(self):
"""Return a formatted visibility string
@@ -84,7 +82,7 @@ class HumanReadableSizeColumn(cliff_columns.FormattableColumn):
return ''
-class VisibilityColumn(cliff_columns.FormattableColumn):
+class VisibilityColumn(cliff_columns.FormattableColumn[bool]):
def human_readable(self):
"""Return a formatted visibility string
@@ -340,9 +338,12 @@ class CreateImage(command.ShowOne):
if image:
display_columns, columns = _get_columns(image)
- _formatters['properties'] = format_columns.DictColumn
data = utils.get_item_properties(
- image, columns, formatters=_formatters
+ image,
+ columns,
+ formatters={
+ 'properties': format_columns.DictColumn,
+ },
)
return (display_columns, data)
elif info:
@@ -493,19 +494,19 @@ class ListImage(command.Lister):
column_headers = columns
# List of image data received
- data = list(image_client.images(**kwargs))
+ images = list(image_client.images(**kwargs))
if parsed_args.property:
# NOTE(dtroyer): coerce to a list to subscript it in py3
attr, value = list(parsed_args.property.items())[0]
api_utils.simple_filter(
- data,
+ images,
attr=attr,
value=value,
property_field='properties',
)
- data = utils.sort_items(data, parsed_args.sort)
+ data = utils.sort_items(images, parsed_args.sort)
return (
column_headers,
@@ -839,11 +840,13 @@ class ShowImage(command.ShowOne):
parsed_args.image, ignore_missing=False
)
+ formatters: dict[
+ str, type[cliff_columns.FormattableColumn[ty.Any]]
+ ] = {
+ 'properties': format_columns.DictColumn,
+ }
if parsed_args.human_readable:
- _formatters['size'] = HumanReadableSizeColumn
+ formatters['size'] = HumanReadableSizeColumn
display_columns, columns = _get_columns(image)
- _formatters['properties'] = format_columns.DictColumn
- data = utils.get_item_properties(
- image, columns, formatters=_formatters
- )
+ data = utils.get_item_properties(image, columns, formatters=formatters)
return (display_columns, data)
diff --git a/openstackclient/image/v2/cache.py b/openstackclient/image/v2/cache.py
index 9fbce84..952d9ed 100644
--- a/openstackclient/image/v2/cache.py
+++ b/openstackclient/image/v2/cache.py
@@ -17,10 +17,10 @@ import copy
import datetime
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/image/v2/image.py b/openstackclient/image/v2/image.py
index f35c572..a7db86c 100644
--- a/openstackclient/image/v2/image.py
+++ b/openstackclient/image/v2/image.py
@@ -30,10 +30,10 @@ from openstack import utils as sdk_utils
from osc_lib.api import utils as api_utils
from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.common import pagination
from openstackclient.common import progressbar
from openstackclient.i18n import _
@@ -551,7 +551,7 @@ class CreateImage(command.ShowOne):
sign_cert_id = parsed_args.sign_cert_id
signer = image_signer.ImageSigner()
try:
- pw = utils.get_password(
+ pw: str | None = utils.get_password(
self.app.stdin,
prompt=(
"Please enter private key password, leave "
@@ -562,12 +562,11 @@ class CreateImage(command.ShowOne):
if not pw or len(pw) < 1:
pw = None
- else:
- # load_private_key() requires the password to be
- # passed as bytes
- pw = pw.encode()
- signer.load_private_key(sign_key_path, password=pw)
+ signer.load_private_key(
+ sign_key_path,
+ password=pw.encode() if pw else None,
+ )
except Exception:
msg = _(
"Error during sign operation: private key "
@@ -623,7 +622,7 @@ class CreateImage(command.ShowOne):
)
# TODO(stephenfin): These should be an error in a future
# version
- LOG.warning(msg % opt_name)
+ LOG.warning(msg, opt_name)
source_volume = volume_client.find_volume(
parsed_args.volume, ignore_missing=False
@@ -933,18 +932,19 @@ class ListImage(command.Lister):
if 'limit' in kwargs:
# Disable automatic pagination in SDK
kwargs['paginated'] = False
- data = list(image_client.images(**kwargs))
+
+ images = list(image_client.images(**kwargs))
if parsed_args.property:
for attr, value in parsed_args.property.items():
api_utils.simple_filter(
- data,
+ images,
attr=attr,
value=value,
property_field='properties',
)
- data = utils.sort_items(data, parsed_args.sort, str)
+ data = utils.sort_items(images, parsed_args.sort, str)
return (
column_headers,
@@ -1393,7 +1393,10 @@ class SetImage(command.Command):
if parsed_args.visibility is not None:
kwargs['visibility'] = parsed_args.visibility
- if parsed_args.project:
+ # Only set owner_id if --project is used WITHOUT membership flags
+ # When --project is used with --accept/--reject/--pending, it should
+ # only identify which member's status to update, not change ownership
+ if parsed_args.project and not parsed_args.membership:
# We already did the project lookup above
kwargs['owner_id'] = project_id
@@ -1716,6 +1719,7 @@ class ImportImage(command.ShowOne):
)
stores_group.add_argument(
'--all-stores',
+ action='store_true',
help=_(
"Make image available to all stores "
"(either '--store' or '--all-stores' required with the "
diff --git a/openstackclient/image/v2/info.py b/openstackclient/image/v2/info.py
index 469b15a..6884813 100644
--- a/openstackclient/image/v2/info.py
+++ b/openstackclient/image/v2/info.py
@@ -12,8 +12,8 @@
from osc_lib.cli import format_columns
-from osc_lib.command import command
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/image/v2/metadef_namespaces.py b/openstackclient/image/v2/metadef_namespaces.py
index f753286..af30f71 100644
--- a/openstackclient/image/v2/metadef_namespaces.py
+++ b/openstackclient/image/v2/metadef_namespaces.py
@@ -18,10 +18,10 @@
import logging
from osc_lib.cli import format_columns
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
_formatters = {
diff --git a/openstackclient/image/v2/metadef_objects.py b/openstackclient/image/v2/metadef_objects.py
index 09fc249..d5cbec1 100644
--- a/openstackclient/image/v2/metadef_objects.py
+++ b/openstackclient/image/v2/metadef_objects.py
@@ -17,10 +17,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/image/v2/metadef_properties.py b/openstackclient/image/v2/metadef_properties.py
index 6027773..3a923c5 100644
--- a/openstackclient/image/v2/metadef_properties.py
+++ b/openstackclient/image/v2/metadef_properties.py
@@ -15,10 +15,10 @@
import json
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
@@ -127,7 +127,8 @@ class DeleteMetadefProperty(command.Command):
nargs="*",
help=_(
"Metadef properties to delete (name) "
- "(omit this argument to delete all properties in the namespace)"
+ "(omit this argument to delete all properties "
+ "in the namespace)"
),
)
return parser
diff --git a/openstackclient/image/v2/metadef_resource_type_association.py b/openstackclient/image/v2/metadef_resource_type_association.py
index 306783c..4d3ee46 100644
--- a/openstackclient/image/v2/metadef_resource_type_association.py
+++ b/openstackclient/image/v2/metadef_resource_type_association.py
@@ -12,10 +12,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
diff --git a/openstackclient/image/v2/metadef_resource_types.py b/openstackclient/image/v2/metadef_resource_types.py
index 3477df3..88001b7 100644
--- a/openstackclient/image/v2/metadef_resource_types.py
+++ b/openstackclient/image/v2/metadef_resource_types.py
@@ -12,9 +12,9 @@
"""Image V2 Action Implementations"""
-from osc_lib.command import command
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/image/v2/task.py b/openstackclient/image/v2/task.py
index 1b7170f..a0f1d35 100644
--- a/openstackclient/image/v2/task.py
+++ b/openstackclient/image/v2/task.py
@@ -11,9 +11,9 @@
# under the License.
from osc_lib.cli import format_columns
-from osc_lib.command import command
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
_formatters = {
diff --git a/openstackclient/network/common.py b/openstackclient/network/common.py
index 9bcd165..bc110e0 100644
--- a/openstackclient/network/common.py
+++ b/openstackclient/network/common.py
@@ -12,17 +12,16 @@
#
import abc
-import argparse
import contextlib
import logging
import typing as ty
-import cliff.app
+from cliff import _argparse
import openstack.exceptions
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.network import utils
@@ -68,8 +67,6 @@ class NetDetectionMixin(metaclass=abc.ABCMeta):
present the options for both network types, often qualified accordingly.
"""
- app: cliff.app.App
-
@property
def _network_type(self):
"""Discover whether the running cloud is using neutron or nova-network.
@@ -84,7 +81,7 @@ class NetDetectionMixin(metaclass=abc.ABCMeta):
# Have we set it up yet for this command?
if not hasattr(self, '_net_type'):
try:
- if self.app.client_manager.is_network_endpoint_enabled():
+ if self.app.client_manager.is_network_endpoint_enabled(): # type: ignore
net_type = _NET_TYPE_NEUTRON
else:
net_type = _NET_TYPE_COMPUTE
@@ -136,7 +133,7 @@ class NetDetectionMixin(metaclass=abc.ABCMeta):
)
)
- def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
+ def get_parser(self, prog_name: str) -> _argparse.ArgumentParser:
LOG.debug('get_parser(%s)', prog_name)
parser = super().get_parser(prog_name) # type: ignore
parser = self.update_parser_common(parser)
@@ -163,11 +160,13 @@ class NetDetectionMixin(metaclass=abc.ABCMeta):
def take_action(self, parsed_args):
if self.is_neutron:
return self.take_action_network(
- self.app.client_manager.network, parsed_args
+ self.app.client_manager.network, # type: ignore
+ parsed_args,
)
elif self.is_nova_network:
return self.take_action_compute(
- self.app.client_manager.compute, parsed_args
+ self.app.client_manager.compute, # type: ignore
+ parsed_args,
)
def take_action_network(self, client, parsed_args):
@@ -203,6 +202,8 @@ class NetworkAndComputeDelete(NetworkAndComputeCommand, metaclass=abc.ABCMeta):
following the rules in doc/source/command-errors.rst.
"""
+ resource: str
+
def take_action(self, parsed_args):
ret = 0
resources = getattr(parsed_args, self.resource, [])
diff --git a/openstackclient/network/v2/address_group.py b/openstackclient/network/v2/address_group.py
index d47c34c..178c3af 100644
--- a/openstackclient/network/v2/address_group.py
+++ b/openstackclient/network/v2/address_group.py
@@ -16,10 +16,10 @@
import logging
import netaddr
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
from openstackclient.network import common
@@ -151,13 +151,14 @@ class ListAddressGroup(command.Lister):
parser.add_argument(
'--name',
metavar='<name>',
- help=_("List only address groups of given name in output"),
+ help=_("List only address groups with the specified name"),
)
parser.add_argument(
'--project',
metavar="<project>",
help=_(
- "List address groups according to their project (name or ID)"
+ "List only address groups with the specified project "
+ "(name or ID)"
),
)
identity_common.add_project_domain_option_to_parser(parser)
diff --git a/openstackclient/network/v2/address_scope.py b/openstackclient/network/v2/address_scope.py
index a7f396b..8a38dab 100644
--- a/openstackclient/network/v2/address_scope.py
+++ b/openstackclient/network/v2/address_scope.py
@@ -15,10 +15,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
from openstackclient.network import common
@@ -160,7 +160,7 @@ class ListAddressScope(command.Lister):
parser.add_argument(
'--name',
metavar='<name>',
- help=_("List only address scopes of given name in output"),
+ help=_("List only address scopes with the specified name"),
)
parser.add_argument(
'--ip-version',
@@ -169,14 +169,16 @@ class ListAddressScope(command.Lister):
metavar='<ip-version>',
dest='ip_version',
help=_(
- "List address scopes of given IP version networks (4 or 6)"
+ "List only address scopes with the specified IP version "
+ "networks (4 or 6)"
),
)
parser.add_argument(
'--project',
metavar="<project>",
help=_(
- "List address scopes according to their project (name or ID)"
+ "List only address scopes with the specified project "
+ "(name or ID)"
),
)
identity_common.add_project_domain_option_to_parser(parser)
@@ -185,12 +187,12 @@ class ListAddressScope(command.Lister):
shared_group.add_argument(
'--share',
action='store_true',
- help=_("List address scopes shared between projects"),
+ help=_("List only address scopes shared between projects"),
)
shared_group.add_argument(
'--no-share',
action='store_true',
- help=_("List address scopes not shared between projects"),
+ help=_("List only address scopes not shared between projects"),
)
return parser
diff --git a/openstackclient/network/v2/default_security_group_rule.py b/openstackclient/network/v2/default_security_group_rule.py
index fddec68..2447585 100644
--- a/openstackclient/network/v2/default_security_group_rule.py
+++ b/openstackclient/network/v2/default_security_group_rule.py
@@ -16,10 +16,10 @@
import logging
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.network import common
from openstackclient.network import utils as network_utils
@@ -150,7 +150,7 @@ class CreateDefaultSecurityGroupRule(
return parser
def take_action(self, parsed_args):
- client = self.app.client_manager.sdk_connection.network
+ client = self.app.client_manager.network
# Build the create attributes.
attrs = {}
attrs['protocol'] = network_utils.get_protocol(parsed_args)
@@ -248,7 +248,7 @@ class DeleteDefaultSecurityGroupRule(command.Command):
def take_action(self, parsed_args):
result = 0
- client = self.app.client_manager.sdk_connection.network
+ client = self.app.client_manager.network
for r in parsed_args.rule:
try:
obj = client.find_default_security_group_rule(
@@ -300,7 +300,8 @@ class ListDefaultSecurityGroupRule(command.Lister):
metavar='<protocol>',
type=network_utils.convert_to_lowercase,
help=_(
- "List rules by the IP protocol (ah, dhcp, egp, esp, gre, "
+ "List only default rules with the specified IP protocol "
+ "(ah, dhcp, egp, esp, gre, "
"icmp, igmp, ipv6-encap, ipv6-frag, ipv6-icmp, "
"ipv6-nonxt, ipv6-opts, ipv6-route, ospf, pgm, rsvp, "
"sctp, tcp, udp, udplite, vrrp and integer "
@@ -319,7 +320,7 @@ class ListDefaultSecurityGroupRule(command.Lister):
'--ingress',
action='store_true',
help=_(
- "List default rules which will be applied to incoming "
+ "List only default rules which will be applied to incoming "
"network traffic"
),
)
@@ -327,14 +328,14 @@ class ListDefaultSecurityGroupRule(command.Lister):
'--egress',
action='store_true',
help=_(
- "List default rules which will be applied to outgoing "
+ "List only default rules which will be applied to outgoing "
"network traffic"
),
)
return parser
def take_action(self, parsed_args):
- client = self.app.client_manager.sdk_connection.network
+ client = self.app.client_manager.network
column_headers = (
'ID',
'IP Protocol',
@@ -403,7 +404,7 @@ class ShowDefaultSecurityGroupRule(command.ShowOne):
return parser
def take_action(self, parsed_args):
- client = self.app.client_manager.sdk_connection.network
+ client = self.app.client_manager.network
obj = client.find_default_security_group_rule(
parsed_args.rule, ignore_missing=False
)
diff --git a/openstackclient/network/v2/floating_ip.py b/openstackclient/network/v2/floating_ip.py
index 0b2f7fa..76b91a0 100644
--- a/openstackclient/network/v2/floating_ip.py
+++ b/openstackclient/network/v2/floating_ip.py
@@ -247,7 +247,7 @@ class ListFloatingIP(common.NetworkAndComputeLister):
action='append',
help=self.enhance_help_neutron(
_(
- "List floating IP(s) according to given network "
+ "List only floating IP(s) with the specified network "
"(name or ID) "
"(repeat option to fiter on multiple networks)"
)
@@ -260,7 +260,8 @@ class ListFloatingIP(common.NetworkAndComputeLister):
action='append',
help=self.enhance_help_neutron(
_(
- "List floating IP(s) according to given port (name or ID) "
+ "List only floating IP(s) with the specified port "
+ "(name or ID) "
"(repeat option to fiter on multiple ports)"
)
),
@@ -269,14 +270,20 @@ class ListFloatingIP(common.NetworkAndComputeLister):
'--fixed-ip-address',
metavar='<ip-address>',
help=self.enhance_help_neutron(
- _("List floating IP(s) according to given fixed IP address")
+ _(
+ "List only floating IP(s) with the specified fixed IP "
+ "address"
+ )
),
)
parser.add_argument(
'--floating-ip-address',
metavar='<ip-address>',
help=self.enhance_help_neutron(
- _("List floating IP(s) according to given floating IP address")
+ _(
+ "List only floating IP(s) with the specified floating IP "
+ "address"
+ )
),
)
parser.add_argument(
@@ -285,8 +292,8 @@ class ListFloatingIP(common.NetworkAndComputeLister):
choices=['ACTIVE', 'DOWN'],
help=self.enhance_help_neutron(
_(
- "List floating IP(s) according to given status ('ACTIVE', "
- "'DOWN')"
+ "List only floating IP(s) with the specified status "
+ "('ACTIVE', 'DOWN')"
)
),
)
@@ -295,8 +302,8 @@ class ListFloatingIP(common.NetworkAndComputeLister):
metavar='<project>',
help=self.enhance_help_neutron(
_(
- "List floating IP(s) according to given project "
- "(name or ID) "
+ "List only floating IP(s) with the specified project "
+ "(name or ID)"
)
),
)
@@ -308,7 +315,7 @@ class ListFloatingIP(common.NetworkAndComputeLister):
action='append',
help=self.enhance_help_neutron(
_(
- "List floating IP(s) according to given router "
+ "List only floating IP(s) with the specified router "
"(name or ID) "
"(repeat option to fiter on multiple routers)"
)
diff --git a/openstackclient/network/v2/floating_ip_port_forwarding.py b/openstackclient/network/v2/floating_ip_port_forwarding.py
index 3810ded..cf770c2 100644
--- a/openstackclient/network/v2/floating_ip_port_forwarding.py
+++ b/openstackclient/network/v2/floating_ip_port_forwarding.py
@@ -16,10 +16,10 @@
import logging
import typing as ty
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.network import common
@@ -265,8 +265,8 @@ class ListFloatingIPPortForwarding(command.Lister):
'--port',
metavar='<port>',
help=_(
- "Filter the list result by the ID or name of "
- "the internal network port"
+ "List only floating IP port forwardings with the "
+ "specified internal network port (name or ID)"
),
)
parser.add_argument(
@@ -274,14 +274,17 @@ class ListFloatingIPPortForwarding(command.Lister):
metavar='<port-number>',
dest='external_protocol_port',
help=_(
- "Filter the list result by the "
- "protocol port number of the floating IP"
+ "List only floating IP port forwardings with the "
+ "specified external protocol port number"
),
)
parser.add_argument(
'--protocol',
metavar='<protocol>',
- help=_("Filter the list result by the port protocol"),
+ help=_(
+ "List only floating IP port forwardings with the "
+ "specified protocol number"
+ ),
)
return parser
diff --git a/openstackclient/network/v2/ip_availability.py b/openstackclient/network/v2/ip_availability.py
index 51ea011..f78c7ec 100644
--- a/openstackclient/network/v2/ip_availability.py
+++ b/openstackclient/network/v2/ip_availability.py
@@ -14,9 +14,9 @@
"""IP Availability Info implementations"""
from osc_lib.cli import format_columns
-from osc_lib.command import command
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
@@ -47,14 +47,17 @@ class ListIPAvailability(command.Lister):
metavar='<ip-version>',
dest='ip_version',
help=_(
- "List IP availability of given IP version "
- "networks (default is 4)"
+ "List only IP availability with the specified IP version "
+ "networks (4 or 6, default is 4)"
),
)
parser.add_argument(
'--project',
metavar='<project>',
- help=_("List IP availability of given project (name or ID)"),
+ help=_(
+ "List only IP availability with the specified project "
+ "(name or ID)"
+ ),
)
identity_common.add_project_domain_option_to_parser(parser)
return parser
diff --git a/openstackclient/network/v2/l3_conntrack_helper.py b/openstackclient/network/v2/l3_conntrack_helper.py
index 011db39..742c263 100644
--- a/openstackclient/network/v2/l3_conntrack_helper.py
+++ b/openstackclient/network/v2/l3_conntrack_helper.py
@@ -15,10 +15,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
@@ -150,19 +150,26 @@ class ListConntrackHelper(command.Lister):
parser.add_argument(
'--helper',
metavar='<helper>',
- help=_('The netfilter conntrack helper module'),
+ help=_(
+ 'List only helpers using the specified netfilter conntrack '
+ 'helper module'
+ ),
)
parser.add_argument(
'--protocol',
metavar='<protocol>',
help=_(
- 'The network protocol for the netfilter conntrack target rule'
+ 'List only helpers with the specified network protocol for '
+ 'the netfilter conntrack target rule'
),
)
parser.add_argument(
'--port',
metavar='<port>',
- help=_('The network port for the netfilter conntrack target rule'),
+ help=_(
+ 'List only helpers with the specified network port for '
+ 'the netfilter conntrack target rule (name or ID)'
+ ),
)
return parser
diff --git a/openstackclient/network/v2/local_ip.py b/openstackclient/network/v2/local_ip.py
index 7fd5881..dde6ccd 100644
--- a/openstackclient/network/v2/local_ip.py
+++ b/openstackclient/network/v2/local_ip.py
@@ -17,10 +17,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
@@ -198,32 +198,38 @@ class ListLocalIP(command.Lister):
parser.add_argument(
'--name',
metavar='<name>',
- help=_("List only Local IPs of given name in output"),
+ help=_("List only local IP(s) with the specified name"),
)
parser.add_argument(
'--project',
metavar="<project>",
- help=_("List Local IPs according to their project (name or ID)"),
+ help=_(
+ "List only local IP(s) with the specified project (name or ID)"
+ ),
)
parser.add_argument(
'--network',
metavar='<network>',
- help=_("List Local IP(s) according to given network (name or ID)"),
+ help=_(
+ "List only local IP(s) with the specified network (name or ID)"
+ ),
)
parser.add_argument(
'--local-port',
metavar='<local-port>',
- help=_("List Local IP(s) according to given port (name or ID)"),
+ help=_(
+ "List only local IP(s) with the specified port (name or ID)"
+ ),
)
parser.add_argument(
'--local-ip-address',
metavar='<local-ip-address>',
- help=_("List Local IP(s) according to given Local IP Address"),
+ help=_("List only local IP(s) with the specified IP address"),
)
parser.add_argument(
'--ip-mode',
metavar='<ip_mode>',
- help=_("List Local IP(s) according to given IP mode"),
+ help=_("List only local IP(s) with the specified IP mode"),
)
identity_common.add_project_domain_option_to_parser(parser)
diff --git a/openstackclient/network/v2/local_ip_association.py b/openstackclient/network/v2/local_ip_association.py
index c6b5918..123faa6 100644
--- a/openstackclient/network/v2/local_ip_association.py
+++ b/openstackclient/network/v2/local_ip_association.py
@@ -17,10 +17,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
@@ -150,18 +150,21 @@ class ListLocalIPAssociation(command.Lister):
'--fixed-port',
metavar='<fixed-port>',
help=_(
- "Filter the list result by the ID or name of the fixed port"
+ "List only local IP assocations with the specified fixed IP "
+ "port (name or ID)"
),
)
parser.add_argument(
'--fixed-ip',
metavar='<fixed-ip>',
- help=_("Filter the list result by fixed ip"),
+ help=_(
+ "List only local IP associations with the specified fixed IP"
+ ),
)
parser.add_argument(
'--host',
metavar='<host>',
- help=_("Filter the list result by given host"),
+ help=_("List only local IP associations with the specified host"),
)
identity_common.add_project_domain_option_to_parser(parser)
diff --git a/openstackclient/network/v2/ndp_proxy.py b/openstackclient/network/v2/ndp_proxy.py
index fe97cd0..78a7ae9 100644
--- a/openstackclient/network/v2/ndp_proxy.py
+++ b/openstackclient/network/v2/ndp_proxy.py
@@ -17,10 +17,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
@@ -143,30 +143,37 @@ class ListNDPProxy(command.Lister):
'--router',
metavar='<router>',
help=_(
- "List only NDP proxies belonging to this router (name or ID)"
+ "List only NDP proxies associated with the specifed router "
+ "(name or ID)"
),
)
parser.add_argument(
'--port',
metavar='<port>',
help=_(
- "List only NDP proxies associated to this port (name or ID)"
+ "List only NDP proxies associated with the specified port "
+ "(name or ID)"
),
)
parser.add_argument(
'--ip-address',
metavar='<ip-address>',
- help=_("List only NDP proxies associated to this IPv6 address"),
+ help=_(
+ "List only NDP proxies associated with the specified "
+ "IPv6 address"
+ ),
)
parser.add_argument(
'--project',
metavar='<project>',
- help=_("List only NDP proxies of given project (name or ID)"),
+ help=_(
+ "List only NDP proxies with the specified project (name or ID)"
+ ),
)
parser.add_argument(
'--name',
metavar='<name>',
- help=_("List only NDP proxies of given name"),
+ help=_("List only NDP proxies with the specified name"),
)
identity_common.add_project_domain_option_to_parser(parser)
diff --git a/openstackclient/network/v2/network.py b/openstackclient/network/v2/network.py
index e04efed..c8e1f36 100644
--- a/openstackclient/network/v2/network.py
+++ b/openstackclient/network/v2/network.py
@@ -24,12 +24,12 @@ from openstackclient.identity import common as identity_common
from openstackclient.network import common
-class AdminStateColumn(cliff_columns.FormattableColumn):
+class AdminStateColumn(cliff_columns.FormattableColumn[bool]):
def human_readable(self):
return 'UP' if self._value else 'DOWN'
-class RouterExternalColumn(cliff_columns.FormattableColumn):
+class RouterExternalColumn(cliff_columns.FormattableColumn[bool]):
def human_readable(self):
return 'External' if self._value else 'Internal'
@@ -401,6 +401,16 @@ class CreateNetwork(
)
raise exceptions.CommandError(msg)
+ if (
+ parsed_args.segmentation_id
+ and not parsed_args.provider_network_type
+ ):
+ msg = _(
+ "--provider-segment requires --provider-network-type "
+ "to be specified."
+ )
+ raise exceptions.CommandError(msg)
+
attrs.update(
self._parse_extra_properties(parsed_args.extra_properties)
)
@@ -459,12 +469,12 @@ class ListNetwork(common.NetworkAndComputeLister):
router_ext_group.add_argument(
'--external',
action='store_true',
- help=self.enhance_help_neutron(_("List external networks")),
+ help=self.enhance_help_neutron(_("List only external networks")),
)
router_ext_group.add_argument(
'--internal',
action='store_true',
- help=self.enhance_help_neutron(_("List internal networks")),
+ help=self.enhance_help_neutron(_("List only internal networks")),
)
parser.add_argument(
'--long',
@@ -477,24 +487,26 @@ class ListNetwork(common.NetworkAndComputeLister):
'--name',
metavar='<name>',
help=self.enhance_help_neutron(
- _("List networks according to their name")
+ _("List only networks with the specified name")
),
)
admin_state_group = parser.add_mutually_exclusive_group()
admin_state_group.add_argument(
'--enable',
action='store_true',
- help=self.enhance_help_neutron(_("List enabled networks")),
+ help=self.enhance_help_neutron(_("List only enabled networks")),
)
admin_state_group.add_argument(
'--disable',
action='store_true',
- help=self.enhance_help_neutron(_("List disabled networks")),
+ help=self.enhance_help_neutron(_("List only disabled networks")),
)
parser.add_argument(
'--project',
metavar='<project>',
- help=_("List networks according to their project (name or ID)"),
+ help=_(
+ "List only networks with the specified project (name or ID)"
+ ),
)
identity_common.add_project_domain_option_to_parser(
parser, enhance_help=self.enhance_help_neutron
@@ -504,14 +516,14 @@ class ListNetwork(common.NetworkAndComputeLister):
'--share',
action='store_true',
help=self.enhance_help_neutron(
- _("List networks shared between projects")
+ _("List only networks shared between projects")
),
)
shared_group.add_argument(
'--no-share',
action='store_true',
help=self.enhance_help_neutron(
- _("List networks not shared between projects")
+ _("List only networks not shared between projects")
),
)
parser.add_argument(
@@ -520,7 +532,7 @@ class ListNetwork(common.NetworkAndComputeLister):
choices=['ACTIVE', 'BUILD', 'DOWN', 'ERROR'],
help=self.enhance_help_neutron(
_(
- "List networks according to their status "
+ "List only networks with the specified status "
"('ACTIVE', 'BUILD', 'DOWN', 'ERROR')"
)
),
@@ -531,7 +543,8 @@ class ListNetwork(common.NetworkAndComputeLister):
choices=['flat', 'geneve', 'gre', 'local', 'vlan', 'vxlan'],
help=self.enhance_help_neutron(
_(
- "List networks according to their physical mechanisms. "
+ "List only networks with the specified physical "
+ "mechanisms. "
"The supported options are: flat, geneve, gre, local, "
"vlan and vxlan."
)
@@ -542,7 +555,10 @@ class ListNetwork(common.NetworkAndComputeLister):
metavar='<provider-physical-network>',
dest='physical_network',
help=self.enhance_help_neutron(
- _("List networks according to name of the physical network")
+ _(
+ "List only networks with the specified physical network "
+ "name"
+ )
),
)
parser.add_argument(
@@ -551,8 +567,9 @@ class ListNetwork(common.NetworkAndComputeLister):
dest='segmentation_id',
help=self.enhance_help_neutron(
_(
- "List networks according to VLAN ID for VLAN networks or "
- "Tunnel ID for GENEVE/GRE/VXLAN networks"
+ "List only networks with the specified provider segment "
+ "ID (VLAN ID for VLAN networks or "
+ "Tunnel ID for GENEVE/GRE/VXLAN networks)"
)
),
)
@@ -561,7 +578,7 @@ class ListNetwork(common.NetworkAndComputeLister):
metavar='<agent-id>',
dest='agent_id',
help=self.enhance_help_neutron(
- _('List networks hosted by agent (ID only)')
+ _('List only networks hosted the specified agent (ID only)')
),
)
_tag.add_tag_filtering_option_to_parser(
diff --git a/openstackclient/network/v2/network_agent.py b/openstackclient/network/v2/network_agent.py
index 35b0fab..806422b 100644
--- a/openstackclient/network/v2/network_agent.py
+++ b/openstackclient/network/v2/network_agent.py
@@ -17,21 +17,21 @@ import logging
from cliff import columns as cliff_columns
from osc_lib.cli import format_columns
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
-class AliveColumn(cliff_columns.FormattableColumn):
+class AliveColumn(cliff_columns.FormattableColumn[bool]):
def human_readable(self):
return ":-)" if self._value else "XXX"
-class AdminStateColumn(cliff_columns.FormattableColumn):
+class AdminStateColumn(cliff_columns.FormattableColumn[bool]):
def human_readable(self):
return 'UP' if self._value else 'DOWN'
@@ -205,12 +205,12 @@ class ListNetworkAgent(command.Lister):
agent_type_group.add_argument(
'--network',
metavar='<network>',
- help=_('List agents hosting a network (name or ID)'),
+ help=_('List agents hosting the specified network (name or ID)'),
)
agent_type_group.add_argument(
'--router',
metavar='<router>',
- help=_('List agents hosting this router (name or ID)'),
+ help=_('List agents hosting the specified router (name or ID)'),
)
parser.add_argument(
'--long',
diff --git a/openstackclient/network/v2/network_auto_allocated_topology.py b/openstackclient/network/v2/network_auto_allocated_topology.py
index 3f5795e..1107cb7 100644
--- a/openstackclient/network/v2/network_auto_allocated_topology.py
+++ b/openstackclient/network/v2/network_auto_allocated_topology.py
@@ -15,9 +15,9 @@
import logging
-from osc_lib.command import command
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
diff --git a/openstackclient/network/v2/network_flavor.py b/openstackclient/network/v2/network_flavor.py
index c4d262d..99993f6 100644
--- a/openstackclient/network/v2/network_flavor.py
+++ b/openstackclient/network/v2/network_flavor.py
@@ -15,10 +15,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
from openstackclient.network import common
diff --git a/openstackclient/network/v2/network_flavor_profile.py b/openstackclient/network/v2/network_flavor_profile.py
index eeb4ce8..9792b01 100644
--- a/openstackclient/network/v2/network_flavor_profile.py
+++ b/openstackclient/network/v2/network_flavor_profile.py
@@ -13,10 +13,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.network import common
diff --git a/openstackclient/network/v2/network_meter.py b/openstackclient/network/v2/network_meter.py
index 625b742..bb3bf94 100644
--- a/openstackclient/network/v2/network_meter.py
+++ b/openstackclient/network/v2/network_meter.py
@@ -15,10 +15,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
from openstackclient.network import common
diff --git a/openstackclient/network/v2/network_meter_rule.py b/openstackclient/network/v2/network_meter_rule.py
index c755154..7a7c231 100644
--- a/openstackclient/network/v2/network_meter_rule.py
+++ b/openstackclient/network/v2/network_meter_rule.py
@@ -16,10 +16,10 @@
import logging
import typing as ty
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
from openstackclient.network import common
diff --git a/openstackclient/network/v2/network_qos_policy.py b/openstackclient/network/v2/network_qos_policy.py
index 1a96f93..ab620b8 100644
--- a/openstackclient/network/v2/network_qos_policy.py
+++ b/openstackclient/network/v2/network_qos_policy.py
@@ -14,12 +14,13 @@
# under the License.
import logging
+import typing as ty
from cliff import columns as cliff_columns
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
from openstackclient.network import common
@@ -27,7 +28,7 @@ from openstackclient.network import common
LOG = logging.getLogger(__name__)
-class RulesColumn(cliff_columns.FormattableColumn):
+class RulesColumn(cliff_columns.FormattableColumn[ty.Any]):
def human_readable(self):
return '\n'.join(str(v) for v in self._value)
@@ -190,7 +191,8 @@ class ListNetworkQosPolicy(command.Lister):
'--project',
metavar='<project>',
help=_(
- "List QoS policies according to their project (name or ID)"
+ "List only QoS policies with the specified project "
+ "(name or ID)"
),
)
identity_common.add_project_domain_option_to_parser(parser)
@@ -198,12 +200,12 @@ class ListNetworkQosPolicy(command.Lister):
shared_group.add_argument(
'--share',
action='store_true',
- help=_("List QoS policies shared between projects"),
+ help=_("List only QoS policies shared between projects"),
)
shared_group.add_argument(
'--no-share',
action='store_true',
- help=_("List QoS policies not shared between projects"),
+ help=_("List only QoS policies not shared between projects"),
)
return parser
diff --git a/openstackclient/network/v2/network_qos_rule.py b/openstackclient/network/v2/network_qos_rule.py
index 86f342f..b2ddd82 100644
--- a/openstackclient/network/v2/network_qos_rule.py
+++ b/openstackclient/network/v2/network_qos_rule.py
@@ -15,10 +15,10 @@
import itertools
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.network import common
diff --git a/openstackclient/network/v2/network_qos_rule_type.py b/openstackclient/network/v2/network_qos_rule_type.py
index fd4da84..c79c5fe 100644
--- a/openstackclient/network/v2/network_qos_rule_type.py
+++ b/openstackclient/network/v2/network_qos_rule_type.py
@@ -13,9 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
-from osc_lib.command import command
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/network/v2/network_rbac.py b/openstackclient/network/v2/network_rbac.py
index 0df7437..200175a 100644
--- a/openstackclient/network/v2/network_rbac.py
+++ b/openstackclient/network/v2/network_rbac.py
@@ -15,10 +15,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
from openstackclient.network import common
@@ -234,8 +234,8 @@ class ListNetworkRBAC(command.Lister):
'network',
],
help=_(
- 'List network RBAC policies according to '
- 'given object type ("address_group", "address_scope", '
+ 'List only network RBAC policies with the specified '
+ 'object type ("address_group", "address_scope", '
'"security_group", "subnetpool", "qos_policy" or '
'"network")'
),
@@ -245,14 +245,17 @@ class ListNetworkRBAC(command.Lister):
metavar='<action>',
choices=['access_as_external', 'access_as_shared'],
help=_(
- 'List network RBAC policies according to given '
+ 'List only network RBAC policies with the specified '
'action ("access_as_external" or "access_as_shared")'
),
)
parser.add_argument(
'--target-project',
metavar='<target-project>',
- help=_('List network RBAC policies for a specific target project'),
+ help=_(
+ 'List only network RBAC policies with the specified '
+ 'target project (name or ID)'
+ ),
)
parser.add_argument(
'--long',
diff --git a/openstackclient/network/v2/network_segment.py b/openstackclient/network/v2/network_segment.py
index 5e40108..c2e7bec 100644
--- a/openstackclient/network/v2/network_segment.py
+++ b/openstackclient/network/v2/network_segment.py
@@ -15,10 +15,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.network import common
@@ -160,7 +160,7 @@ class ListNetworkSegment(command.Lister):
'--network',
metavar='<network>',
help=_(
- 'List network segments that belong to this '
+ 'List only network segments associated with the specified '
'network (name or ID)'
),
)
diff --git a/openstackclient/network/v2/network_segment_range.py b/openstackclient/network/v2/network_segment_range.py
index e2716f1..c8b9a0e 100644
--- a/openstackclient/network/v2/network_segment_range.py
+++ b/openstackclient/network/v2/network_segment_range.py
@@ -20,10 +20,10 @@ import itertools
import logging
import typing as ty
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
from openstackclient.network import common
@@ -315,25 +315,32 @@ class ListNetworkSegmentRange(command.Lister):
used_group.add_argument(
'--used',
action='store_true',
- help=_('List network segment ranges that have segments in use'),
+ help=_(
+ 'List only network segment ranges that have segments in use'
+ ),
)
used_group.add_argument(
'--unused',
action='store_true',
help=_(
- 'List network segment ranges that have segments not in use'
+ 'List only network segment ranges that have segments '
+ 'not in use'
),
)
available_group = parser.add_mutually_exclusive_group()
available_group.add_argument(
'--available',
action='store_true',
- help=_('List network segment ranges that have available segments'),
+ help=_(
+ 'List only network segment ranges that have available segments'
+ ),
)
available_group.add_argument(
'--unavailable',
action='store_true',
- help=_('List network segment ranges without available segments'),
+ help=_(
+ 'List only network segment ranges without available segments'
+ ),
)
return parser
@@ -395,7 +402,7 @@ class ListNetworkSegmentRange(command.Lister):
'available',
)
- display_props: tuple[str, ...] = tuple()
+ display_props: tuple[ty.Any, ...] = tuple()
for s in data:
props = utils.get_item_properties(s, columns)
if (
diff --git a/openstackclient/network/v2/network_service_provider.py b/openstackclient/network/v2/network_service_provider.py
index f743bfa..1433c09 100644
--- a/openstackclient/network/v2/network_service_provider.py
+++ b/openstackclient/network/v2/network_service_provider.py
@@ -13,9 +13,9 @@
"""Network Service Providers Implementation"""
-from osc_lib.command import command
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/network/v2/network_trunk.py b/openstackclient/network/v2/network_trunk.py
index f8f1c5b..974a997 100644
--- a/openstackclient/network/v2/network_trunk.py
+++ b/openstackclient/network/v2/network_trunk.py
@@ -23,10 +23,10 @@ from cliff import columns as cliff_columns
from osc_lib.cli import format_columns
from osc_lib.cli import identity as identity_utils
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils as osc_utils
+from openstackclient import command
from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
@@ -36,7 +36,7 @@ TRUNKS = 'trunks'
SUB_PORTS = 'sub_ports'
-class AdminStateColumn(cliff_columns.FormattableColumn):
+class AdminStateColumn(cliff_columns.FormattableColumn[bool]):
def human_readable(self):
return 'UP' if self._value else 'DOWN'
@@ -88,9 +88,12 @@ class CreateNetworkTrunk(command.ShowOne):
return parser
def take_action(self, parsed_args):
- client = self.app.client_manager.network
- attrs = _get_attrs_for_trunk(self.app.client_manager, parsed_args)
- obj = client.create_trunk(**attrs)
+ network_client = self.app.client_manager.network
+ identity_client = self.app.client_manager.identity
+ attrs = _get_attrs_for_trunk(
+ network_client, identity_client, parsed_args
+ )
+ obj = network_client.create_trunk(**attrs)
display_columns, columns = _get_columns(obj)
data = osc_utils.get_dict_properties(
obj, columns, formatters=_formatters
@@ -112,12 +115,15 @@ class DeleteNetworkTrunk(command.Command):
return parser
def take_action(self, parsed_args):
- client = self.app.client_manager.network
+ network_client = self.app.client_manager.network
result = 0
for trunk in parsed_args.trunk:
try:
- trunk_id = client.find_trunk(trunk).id
- client.delete_trunk(trunk_id)
+ trunk_id = network_client.find_trunk(
+ trunk,
+ ignore_missing=False,
+ ).id
+ network_client.delete_trunk(trunk_id)
except Exception as e:
result += 1
LOG.error(
@@ -150,8 +156,8 @@ class ListNetworkTrunk(command.Lister):
return parser
def take_action(self, parsed_args):
- client = self.app.client_manager.network
- data = client.trunks()
+ network_client = self.app.client_manager.network
+ data = network_client.trunks()
headers: tuple[str, ...] = ('ID', 'Name', 'Parent Port', 'Description')
columns: tuple[str, ...] = ('id', 'name', 'port_id', 'description')
if parsed_args.long:
@@ -215,11 +221,17 @@ class SetNetworkTrunk(command.Command):
return parser
def take_action(self, parsed_args):
- client = self.app.client_manager.network
- trunk_id = client.find_trunk(parsed_args.trunk)
- attrs = _get_attrs_for_trunk(self.app.client_manager, parsed_args)
+ network_client = self.app.client_manager.network
+ identity_client = self.app.client_manager.identity
+ trunk_id = network_client.find_trunk(
+ parsed_args.trunk,
+ ignore_missing=False,
+ )
+ attrs = _get_attrs_for_trunk(
+ network_client, identity_client, parsed_args
+ )
try:
- client.update_trunk(trunk_id, **attrs)
+ network_client.update_trunk(trunk_id, **attrs)
except Exception as e:
msg = _("Failed to set trunk '%(t)s': %(e)s") % {
't': parsed_args.trunk,
@@ -228,10 +240,10 @@ class SetNetworkTrunk(command.Command):
raise exceptions.CommandError(msg)
if parsed_args.set_subports:
subport_attrs = _get_attrs_for_subports(
- self.app.client_manager, parsed_args
+ network_client, parsed_args
)
try:
- client.add_trunk_subports(trunk_id, subport_attrs)
+ network_client.add_trunk_subports(trunk_id, subport_attrs)
except Exception as e:
msg = _("Failed to add subports to trunk '%(t)s': %(e)s") % {
't': parsed_args.trunk,
@@ -251,9 +263,12 @@ class ShowNetworkTrunk(command.ShowOne):
return parser
def take_action(self, parsed_args):
- client = self.app.client_manager.network
- trunk_id = client.find_trunk(parsed_args.trunk).id
- obj = client.get_trunk(trunk_id)
+ network_client = self.app.client_manager.network
+ trunk_id = network_client.find_trunk(
+ parsed_args.trunk,
+ ignore_missing=False,
+ ).id
+ obj = network_client.get_trunk(trunk_id)
display_columns, columns = _get_columns(obj)
data = osc_utils.get_dict_properties(
obj, columns, formatters=_formatters
@@ -270,14 +285,17 @@ class ListNetworkSubport(command.Lister):
'--trunk',
required=True,
metavar="<trunk>",
- help=_("List subports belonging to this trunk (name or ID)"),
+ help=_("List only subports belonging to this trunk (name or ID)"),
)
return parser
def take_action(self, parsed_args):
- client = self.app.client_manager.network
- trunk_id = client.find_trunk(parsed_args.trunk)
- data = client.get_trunk_subports(trunk_id)
+ network_client = self.app.client_manager.network
+ trunk_id = network_client.find_trunk(
+ parsed_args.trunk,
+ ignore_missing=False,
+ )
+ data = network_client.get_trunk_subports(trunk_id)
headers: tuple[str, ...] = (
'Port',
'Segmentation Type',
@@ -324,10 +342,13 @@ class UnsetNetworkTrunk(command.Command):
return parser
def take_action(self, parsed_args):
- client = self.app.client_manager.network
- attrs = _get_attrs_for_subports(self.app.client_manager, parsed_args)
- trunk_id = client.find_trunk(parsed_args.trunk)
- client.delete_trunk_subports(trunk_id, attrs)
+ network_client = self.app.client_manager.network
+ attrs = _get_attrs_for_subports(network_client, parsed_args)
+ trunk_id = network_client.find_trunk(
+ parsed_args.trunk,
+ ignore_missing=False,
+ )
+ network_client.delete_trunk_subports(trunk_id, attrs)
_formatters = {
@@ -343,7 +364,7 @@ def _get_columns(item):
)
-def _get_attrs_for_trunk(client_manager, parsed_args):
+def _get_attrs_for_trunk(network_client, identity_client, parsed_args):
attrs: dict[str, ty.Any] = {}
if parsed_args.name is not None:
attrs['name'] = str(parsed_args.name)
@@ -354,18 +375,18 @@ def _get_attrs_for_trunk(client_manager, parsed_args):
if parsed_args.disable:
attrs['admin_state_up'] = False
if 'parent_port' in parsed_args and parsed_args.parent_port is not None:
- port_id = client_manager.network.find_port(parsed_args.parent_port)[
- 'id'
- ]
+ port_id = network_client.find_port(
+ parsed_args.parent_port,
+ ignore_missing=False,
+ ).id
attrs['port_id'] = port_id
if 'add_subports' in parsed_args and parsed_args.add_subports is not None:
attrs[SUB_PORTS] = _format_subports(
- client_manager, parsed_args.add_subports
+ network_client, parsed_args.add_subports
)
# "trunk set" command doesn't support setting project.
if 'project' in parsed_args and parsed_args.project is not None:
- identity_client = client_manager.identity
project_id = identity_utils.find_project(
identity_client,
parsed_args.project,
@@ -376,12 +397,15 @@ def _get_attrs_for_trunk(client_manager, parsed_args):
return attrs
-def _format_subports(client_manager, subports):
+def _format_subports(network_client, subports):
attrs = []
for subport in subports:
subport_attrs = {}
if subport.get('port'):
- port_id = client_manager.network.find_port(subport['port'])['id']
+ port_id = network_client.find_port(
+ subport['port'],
+ ignore_missing=False,
+ ).id
subport_attrs['port_id'] = port_id
if subport.get('segmentation-id'):
try:
@@ -400,21 +424,20 @@ def _format_subports(client_manager, subports):
return attrs
-def _get_attrs_for_subports(client_manager, parsed_args):
+def _get_attrs_for_subports(network_client, parsed_args):
attrs = []
if 'set_subports' in parsed_args and parsed_args.set_subports is not None:
- attrs = _format_subports(client_manager, parsed_args.set_subports)
+ attrs = _format_subports(network_client, parsed_args.set_subports)
if (
'unset_subports' in parsed_args
and parsed_args.unset_subports is not None
):
subports_list = []
for subport in parsed_args.unset_subports:
- port_id = client_manager.network.find_port(subport)['id']
+ port_id = network_client.find_port(
+ subport,
+ ignore_missing=False,
+ )['id']
subports_list.append({'port_id': port_id})
attrs = subports_list
return attrs
-
-
-def _get_id(client, id_or_name, resource):
- return client.find_resource(resource, str(id_or_name))['id']
diff --git a/openstackclient/network/v2/port.py b/openstackclient/network/v2/port.py
index 5cfc41d..e120515 100644
--- a/openstackclient/network/v2/port.py
+++ b/openstackclient/network/v2/port.py
@@ -22,11 +22,11 @@ import typing as ty
from cliff import columns as cliff_columns
from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
from osc_lib.utils import tags as _tag
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
from openstackclient.network import common
@@ -34,7 +34,7 @@ from openstackclient.network import common
LOG = logging.getLogger(__name__)
-class AdminStateColumn(cliff_columns.FormattableColumn):
+class AdminStateColumn(cliff_columns.FormattableColumn[bool]):
def human_readable(self):
return 'UP' if self._value else 'DOWN'
@@ -636,11 +636,11 @@ class CreatePort(command.ShowOne, common.NeutronCommandWithExtraArgs):
return parser
def take_action(self, parsed_args):
- client = self.app.client_manager.network
- _network = client.find_network(
+ network_client = self.app.client_manager.network
+ network = network_client.find_network(
parsed_args.network, ignore_missing=False
)
- parsed_args.network = _network.id
+ parsed_args.network = network.id
_prepare_fixed_ips(self.app.client_manager, parsed_args)
attrs = _get_attrs(self.app.client_manager, parsed_args)
@@ -654,7 +654,7 @@ class CreatePort(command.ShowOne, common.NeutronCommandWithExtraArgs):
if parsed_args.security_groups is not None:
attrs['security_group_ids'] = [
- client.find_security_group(sg, ignore_missing=False).id
+ network_client.find_security_group(sg, ignore_missing=False).id
for sg in parsed_args.security_groups
]
@@ -667,7 +667,7 @@ class CreatePort(command.ShowOne, common.NeutronCommandWithExtraArgs):
attrs["extra_dhcp_opts"] = _convert_extra_dhcp_options(parsed_args)
if parsed_args.qos_policy:
- attrs['qos_policy_id'] = client.find_qos_policy(
+ attrs['qos_policy_id'] = network_client.find_qos_policy(
parsed_args.qos_policy, ignore_missing=False
).id
@@ -675,7 +675,9 @@ class CreatePort(command.ShowOne, common.NeutronCommandWithExtraArgs):
_validate_port_hints(parsed_args.hint)
expanded_hints = _expand_port_hint_aliases(parsed_args.hint)
try:
- client.find_extension('port-hints', ignore_missing=False)
+ network_client.find_extension(
+ 'port-hints', ignore_missing=False
+ )
except Exception as e:
msg = _('Not supported by Network API: %(e)s') % {'e': e}
raise exceptions.CommandError(msg)
@@ -686,7 +688,7 @@ class CreatePort(command.ShowOne, common.NeutronCommandWithExtraArgs):
in expanded_hints['openvswitch']['other_config']
):
try:
- client.find_extension(
+ network_client.find_extension(
'port-hint-ovs-tx-steering', ignore_missing=False
)
except Exception as e:
@@ -695,7 +697,9 @@ class CreatePort(command.ShowOne, common.NeutronCommandWithExtraArgs):
attrs['hints'] = expanded_hints
set_tags_in_post = bool(
- client.find_extension('tag-ports-during-bulk-creation')
+ network_client.find_extension(
+ 'tag-ports-during-bulk-creation', ignore_missing=True
+ )
)
if set_tags_in_post:
if parsed_args.no_tag:
@@ -707,14 +711,12 @@ class CreatePort(command.ShowOne, common.NeutronCommandWithExtraArgs):
self._parse_extra_properties(parsed_args.extra_properties)
)
- with common.check_missing_extension_if_error(
- self.app.client_manager.network, attrs
- ):
- obj = client.create_port(**attrs)
+ with common.check_missing_extension_if_error(network_client, attrs):
+ obj = network_client.create_port(**attrs)
if not set_tags_in_post:
# tags cannot be set when created, so tags need to be set later.
- _tag.update_tags_for_set(client, obj, parsed_args)
+ _tag.update_tags_for_set(network_client, obj, parsed_args)
display_columns, columns = _get_columns(obj)
data = utils.get_item_properties(obj, columns, formatters=_formatters)
@@ -808,7 +810,7 @@ class ListPort(command.Lister):
parser.add_argument(
'--mac-address',
metavar='<mac-address>',
- help=_("List only ports with this MAC address"),
+ help=_("List only ports with the specified MAC address"),
)
parser.add_argument(
'--long',
@@ -819,12 +821,12 @@ class ListPort(command.Lister):
parser.add_argument(
'--project',
metavar='<project>',
- help=_("List ports according to their project (name or ID)"),
+ help=_("List only ports with the specified project (name or ID)"),
)
parser.add_argument(
'--name',
metavar='<name>',
- help=_("List ports according to their name"),
+ help=_("List only ports with the specified name"),
)
parser.add_argument(
'--security-group',
@@ -842,7 +844,7 @@ class ListPort(command.Lister):
metavar='<status>',
choices=('ACTIVE', 'BUILD', 'DOWN', 'ERROR'),
help=_(
- "List ports according to their status "
+ "List only ports with the specified status "
"('ACTIVE', 'BUILD', 'DOWN', 'ERROR')"
),
)
@@ -859,7 +861,7 @@ class ListPort(command.Lister):
"Desired IP and/or subnet for filtering ports "
"(name or ID): subnet=<subnet>,ip-address=<ip-address>,"
"ip-substring=<ip-substring> "
- "(repeat option to set multiple fixed IP addresses)"
+ "(repeat option to filter multiple fixed IP addresses)"
),
)
_tag.add_tag_filtering_option_to_parser(parser, _('ports'))
diff --git a/openstackclient/network/v2/router.py b/openstackclient/network/v2/router.py
index 67e3de0..939167d 100644
--- a/openstackclient/network/v2/router.py
+++ b/openstackclient/network/v2/router.py
@@ -23,11 +23,11 @@ import typing as ty
from cliff import columns as cliff_columns
from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
from osc_lib.utils import tags as _tag
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
from openstackclient.network import common
@@ -35,12 +35,12 @@ from openstackclient.network import common
LOG = logging.getLogger(__name__)
-class AdminStateColumn(cliff_columns.FormattableColumn):
+class AdminStateColumn(cliff_columns.FormattableColumn[bool]):
def human_readable(self):
return 'UP' if self._value else 'DOWN'
-class RouterInfoColumn(cliff_columns.FormattableColumn):
+class RouterInfoColumn(cliff_columns.FormattableColumn[ty.Any]):
def human_readable(self):
try:
return json.dumps(self._value)
@@ -48,7 +48,7 @@ class RouterInfoColumn(cliff_columns.FormattableColumn):
return ''
-class RoutesColumn(cliff_columns.FormattableColumn):
+class RoutesColumn(cliff_columns.FormattableColumn[ty.Any]):
def human_readable(self):
# Map the route keys to match --route option.
for route in self._value or []:
@@ -89,7 +89,12 @@ def _get_columns(item):
def is_multiple_gateways_supported(n_client):
- return n_client.find_extension("external-gateway-multihoming") is not None
+ return (
+ n_client.find_extension(
+ "external-gateway-multihoming", ignore_missing=True
+ )
+ is not None
+ )
def _passed_multiple_gateways(extension_supported, external_gateways):
@@ -236,7 +241,9 @@ def _get_attrs(client_manager, parsed_args):
# "router set" command doesn't support setting flavor_id.
if 'flavor_id' in parsed_args and parsed_args.flavor_id is not None:
- flavor = n_client.find_flavor(parsed_args.flavor_id)
+ flavor = n_client.find_flavor(
+ parsed_args.flavor_id, ignore_missing=False
+ )
attrs['flavor_id'] = flavor.id
elif 'flavor' in parsed_args and parsed_args.flavor is not None:
flavor = n_client.find_flavor(parsed_args.flavor, ignore_missing=False)
@@ -719,13 +726,17 @@ class ListRouter(command.Lister):
parser.add_argument(
'--project',
metavar='<project>',
- help=_("List routers according to their project (name or ID)"),
+ help=_(
+ "List only routers with the specified project (name or ID)"
+ ),
)
identity_common.add_project_domain_option_to_parser(parser)
parser.add_argument(
'--agent',
metavar='<agent-id>',
- help=_("List routers hosted by an agent (ID only)"),
+ help=_(
+ "List only routers hosted by the specified agent (ID only)"
+ ),
)
_tag.add_tag_filtering_option_to_parser(parser, _('routers'))
diff --git a/openstackclient/network/v2/security_group.py b/openstackclient/network/v2/security_group.py
index 6fb98c6..c6930de 100644
--- a/openstackclient/network/v2/security_group.py
+++ b/openstackclient/network/v2/security_group.py
@@ -14,13 +14,14 @@
"""Security Group action implementations"""
import argparse
+import typing as ty
from cliff import columns as cliff_columns
-from osc_lib.command import command
from osc_lib import utils
from osc_lib.utils import tags as _tag
from openstackclient.api import compute_v2
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
from openstackclient.network import common
@@ -65,12 +66,12 @@ def _format_compute_security_group_rules(sg_rules):
return utils.format_list(rules, separator='\n')
-class NetworkSecurityGroupRulesColumn(cliff_columns.FormattableColumn):
+class NetworkSecurityGroupRulesColumn(cliff_columns.FormattableColumn[ty.Any]):
def human_readable(self):
return _format_network_security_group_rules(self._value)
-class ComputeSecurityGroupRulesColumn(cliff_columns.FormattableColumn):
+class ComputeSecurityGroupRulesColumn(cliff_columns.FormattableColumn[ty.Any]):
def human_readable(self):
return _format_compute_security_group_rules(self._value)
@@ -246,7 +247,10 @@ class ListSecurityGroup(common.NetworkAndComputeLister):
'--project',
metavar='<project>',
help=self.enhance_help_neutron(
- _("List security groups according to the project (name or ID)")
+ _(
+ "List only security groups with the specified project "
+ "(name or ID)"
+ )
),
)
identity_common.add_project_domain_option_to_parser(
@@ -259,14 +263,14 @@ class ListSecurityGroup(common.NetworkAndComputeLister):
action='store_true',
dest='shared',
default=None,
- help=_("List security groups shared between projects"),
+ help=_("List only security groups shared between projects"),
)
shared_group.add_argument(
'--no-share',
action='store_false',
dest='shared',
default=None,
- help=_("List security groups not shared between projects"),
+ help=_("List only security groups not shared between projects"),
)
_tag.add_tag_filtering_option_to_parser(
diff --git a/openstackclient/network/v2/security_group_rule.py b/openstackclient/network/v2/security_group_rule.py
index 6cb0f7f..f6baac3 100644
--- a/openstackclient/network/v2/security_group_rule.py
+++ b/openstackclient/network/v2/security_group_rule.py
@@ -387,7 +387,8 @@ class ListSecurityGroupRule(common.NetworkAndComputeLister):
type=network_utils.convert_to_lowercase,
help=self.enhance_help_neutron(
_(
- "List rules by the IP protocol (ah, dhcp, egp, esp, gre, "
+ "List only rules with the specified IP protocol "
+ "(ah, dhcp, egp, esp, gre, "
"icmp, igmp, ipv6-encap, ipv6-frag, ipv6-icmp, "
"ipv6-nonxt, ipv6-opts, ipv6-route, ospf, pgm, rsvp, "
"sctp, tcp, udp, udplite, vrrp and integer "
@@ -401,7 +402,10 @@ class ListSecurityGroupRule(common.NetworkAndComputeLister):
metavar='<ethertype>',
type=network_utils.convert_to_lowercase,
help=self.enhance_help_neutron(
- _("List rules by the Ethertype (IPv4 or IPv6)")
+ _(
+ "List only rules with the specified Ethertype "
+ "(IPv4 or IPv6)"
+ )
),
)
direction_group = parser.add_mutually_exclusive_group()
@@ -409,14 +413,14 @@ class ListSecurityGroupRule(common.NetworkAndComputeLister):
'--ingress',
action='store_true',
help=self.enhance_help_neutron(
- _("List rules applied to incoming network traffic")
+ _("List only rules applied to incoming network traffic")
),
)
direction_group.add_argument(
'--egress',
action='store_true',
help=self.enhance_help_neutron(
- _("List rules applied to outgoing network traffic")
+ _("List only rules applied to outgoing network traffic")
),
)
parser.add_argument(
@@ -430,7 +434,9 @@ class ListSecurityGroupRule(common.NetworkAndComputeLister):
parser.add_argument(
'--project',
metavar='<project>',
- help=self.enhance_help_neutron(_("Owner's project (name or ID)")),
+ help=self.enhance_help_neutron(
+ _("List only rules with the specified project (name or ID)")
+ ),
)
identity_common.add_project_domain_option_to_parser(
parser, enhance_help=self.enhance_help_neutron
diff --git a/openstackclient/network/v2/subnet.py b/openstackclient/network/v2/subnet.py
index 30196bf..3357f89 100644
--- a/openstackclient/network/v2/subnet.py
+++ b/openstackclient/network/v2/subnet.py
@@ -20,11 +20,11 @@ import typing as ty
from cliff import columns as cliff_columns
from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
from osc_lib.utils import tags as _tag
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
from openstackclient.network import common
@@ -44,7 +44,7 @@ def _update_arguments(obj_list, parsed_args_list, option):
raise exceptions.CommandError(msg)
-class AllocationPoolsColumn(cliff_columns.FormattableColumn):
+class AllocationPoolsColumn(cliff_columns.FormattableColumn[ty.Any]):
def human_readable(self):
pool_formatted = [
'{}-{}'.format(pool.get('start', ''), pool.get('end', ''))
@@ -53,7 +53,7 @@ class AllocationPoolsColumn(cliff_columns.FormattableColumn):
return ','.join(pool_formatted)
-class HostRoutesColumn(cliff_columns.FormattableColumn):
+class HostRoutesColumn(cliff_columns.FormattableColumn[ty.Any]):
def human_readable(self):
# Map the host route keys to match --host-route option.
return utils.format_list_of_dicts(
@@ -61,7 +61,7 @@ class HostRoutesColumn(cliff_columns.FormattableColumn):
)
-class UnsortedListColumn(cliff_columns.FormattableColumn):
+class UnsortedListColumn(cliff_columns.FormattableColumn[list[ty.Any]]):
# format_columns.ListColumn sorts the output, but for things like
# DNS server addresses the order matters
def human_readable(self):
@@ -493,7 +493,7 @@ class ListSubnet(command.Lister):
metavar='<ip-version>',
dest='ip_version',
help=_(
- "List only subnets of given IP version in output. "
+ "List only subnets with the specified IP version. "
"Allowed values for IP version are 4 and 6."
),
)
@@ -501,12 +501,12 @@ class ListSubnet(command.Lister):
dhcp_enable_group.add_argument(
'--dhcp',
action='store_true',
- help=_("List subnets which have DHCP enabled"),
+ help=_("List only subnets which have DHCP enabled"),
)
dhcp_enable_group.add_argument(
'--no-dhcp',
action='store_true',
- help=_("List subnets which have DHCP disabled"),
+ help=_("List only subnets which have DHCP disabled"),
)
parser.add_argument(
'--service-type',
@@ -514,7 +514,7 @@ class ListSubnet(command.Lister):
action='append',
dest='service_types',
help=_(
- "List only subnets of a given service type in output, "
+ "List only subnets with the specified service type, "
"for example, network:floatingip_agent_gateway. "
"Must be a valid device owner value for a network port "
"(repeat option to list multiple service types)."
@@ -524,8 +524,7 @@ class ListSubnet(command.Lister):
'--project',
metavar='<project>',
help=_(
- "List only subnets which belong to a given project "
- "in output (name or ID)"
+ "List only subnets with the specified project (name or ID)"
),
)
identity_common.add_project_domain_option_to_parser(parser)
@@ -533,26 +532,26 @@ class ListSubnet(command.Lister):
'--network',
metavar='<network>',
help=_(
- "List only subnets which belong to a given network "
- "in output (name or ID)"
+ "List only subnets which belong to the specified network "
+ "(name or ID)"
),
)
parser.add_argument(
'--gateway',
metavar='<gateway>',
- help=_("List only subnets of given gateway IP in output"),
+ help=_("List only subnets with the specified gateway IP"),
)
parser.add_argument(
'--name',
metavar='<name>',
- help=_("List only subnets of given name in output"),
+ help=_("List only subnets with the specified name"),
)
parser.add_argument(
'--subnet-range',
metavar='<subnet-range>',
help=_(
- "List only subnets of given subnet range "
- "(in CIDR notation) in output. "
+ "List only subnets with the specified subnet range "
+ "(in CIDR notation). "
"For example, --subnet-range 10.10.0.0/16"
),
)
@@ -560,8 +559,8 @@ class ListSubnet(command.Lister):
'--subnet-pool',
metavar='<subnet-pool>',
help=_(
- "List only subnets which belong to a given subnet pool "
- "in output (name or ID)"
+ "List only subnets which belong to the specified subnet pool "
+ "(name or ID)"
),
)
_tag.add_tag_filtering_option_to_parser(parser, _('subnets'))
diff --git a/openstackclient/network/v2/subnet_pool.py b/openstackclient/network/v2/subnet_pool.py
index 2917c40..399ce48 100644
--- a/openstackclient/network/v2/subnet_pool.py
+++ b/openstackclient/network/v2/subnet_pool.py
@@ -17,11 +17,11 @@ import logging
from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
from osc_lib.utils import tags as _tag
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
from openstackclient.network import common
@@ -278,26 +278,27 @@ class ListSubnetPool(command.Lister):
shared_group.add_argument(
'--share',
action='store_true',
- help=_("List subnet pools shared between projects"),
+ help=_("List only subnet pools shared between projects"),
)
shared_group.add_argument(
'--no-share',
action='store_true',
- help=_("List subnet pools not shared between projects"),
+ help=_("List only subnet pools not shared between projects"),
)
default_group = parser.add_mutually_exclusive_group()
default_group.add_argument(
'--default',
action='store_true',
help=_(
- "List subnet pools used as the default external subnet pool"
+ "List only subnet pools used as the default external "
+ "subnet pool"
),
)
default_group.add_argument(
'--no-default',
action='store_true',
help=_(
- "List subnet pools not used as the default external "
+ "List only subnet pools not used as the default external "
"subnet pool"
),
)
@@ -305,21 +306,22 @@ class ListSubnetPool(command.Lister):
'--project',
metavar='<project>',
help=_(
- "List subnet pools according to their project (name or ID)"
+ "List only subnet pools with the specified project "
+ "(name or ID)"
),
)
identity_common.add_project_domain_option_to_parser(parser)
parser.add_argument(
'--name',
metavar='<name>',
- help=_("List only subnet pools of given name in output"),
+ help=_("List only subnet pools with the specified name"),
)
parser.add_argument(
'--address-scope',
metavar='<address-scope>',
help=_(
- "List only subnet pools of given address scope "
- "in output (name or ID)"
+ "List only subnet pools with the specified address scope "
+ "(name or ID)"
),
)
_tag.add_tag_filtering_option_to_parser(parser, _('subnet pools'))
diff --git a/openstackclient/network/v2/taas/__init__.py b/openstackclient/network/v2/taas/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/openstackclient/network/v2/taas/__init__.py
diff --git a/openstackclient/network/v2/taas/tap_flow.py b/openstackclient/network/v2/taas/tap_flow.py
new file mode 100644
index 0000000..206fbde
--- /dev/null
+++ b/openstackclient/network/v2/taas/tap_flow.py
@@ -0,0 +1,245 @@
+# All Rights Reserved 2020
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import logging
+
+from osc_lib.cli import format_columns
+from osc_lib.cli import identity as identity_utils
+from osc_lib import exceptions
+from osc_lib import utils as osc_utils
+from osc_lib.utils import columns as column_util
+
+from openstackclient import command
+from openstackclient.i18n import _
+from openstackclient.identity import common
+from openstackclient.network.v2.taas import tap_service
+
+LOG = logging.getLogger(__name__)
+
+TAP_FLOW = 'tap_flow'
+TAP_FLOWS = f'{TAP_FLOW}s'
+
+_attr_map = [
+ ('id', 'ID', column_util.LIST_BOTH),
+ ('tenant_id', 'Tenant', column_util.LIST_LONG_ONLY),
+ ('name', 'Name', column_util.LIST_BOTH),
+ ('status', 'Status', column_util.LIST_BOTH),
+ ('source_port', 'source_port', column_util.LIST_BOTH),
+ ('tap_service_id', 'tap_service_id', column_util.LIST_BOTH),
+ ('direction', 'Direction', column_util.LIST_BOTH),
+]
+
+_formatters = {
+ 'vlan_filter': format_columns.ListColumn,
+}
+
+
+def _add_updatable_args(parser):
+ parser.add_argument('--name', help=_('Name of the tap flow.'))
+ parser.add_argument(
+ '--description', help=_('Description of the tap flow.')
+ )
+
+
+class CreateTapFlow(command.ShowOne):
+ _description = _("Create a new tap flow.")
+
+ def get_parser(self, prog_name):
+ parser = super().get_parser(prog_name)
+ identity_utils.add_project_owner_option_to_parser(parser)
+ _add_updatable_args(parser)
+ parser.add_argument(
+ '--port',
+ required=True,
+ metavar="SOURCE_PORT",
+ help=_('Source port (name or ID) to monitor.'),
+ )
+ parser.add_argument(
+ '--tap-service',
+ required=True,
+ metavar="TAP_SERVICE",
+ help=_(
+ 'Tap service (name or ID) to associate with this tap flow.'
+ ),
+ )
+ parser.add_argument(
+ '--direction',
+ required=True,
+ metavar="DIRECTION",
+ choices=['IN', 'OUT', 'BOTH'],
+ type=lambda s: s.upper(),
+ help=_(
+ 'Direction of the Tap flow. Valid options are: '
+ 'IN, OUT and BOTH'
+ ),
+ )
+ parser.add_argument(
+ '--vlan-filter',
+ required=False,
+ metavar="VLAN_FILTER",
+ help=_('VLAN IDs to mirror in the form of range string.'),
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ client = self.app.client_manager.network
+ attrs = {}
+ if parsed_args.name is not None:
+ attrs['name'] = parsed_args.name
+ if parsed_args.description is not None:
+ attrs['description'] = parsed_args.description
+ if parsed_args.port is not None:
+ source_port = client.find_port(
+ parsed_args.port, ignore_missing=False
+ ).id
+ attrs['source_port'] = source_port
+ if parsed_args.tap_service is not None:
+ tap_service_id = client.find_tap_service(
+ parsed_args.tap_service, ignore_missing=False
+ ).id
+ attrs['tap_service_id'] = tap_service_id
+ if parsed_args.direction is not None:
+ attrs['direction'] = parsed_args.direction
+ if parsed_args.vlan_filter is not None:
+ attrs['vlan_filter'] = parsed_args.vlan_filter
+ if 'project' in parsed_args and parsed_args.project is not None:
+ attrs['project_id'] = common.find_project(
+ self.app.client_manager.identity,
+ parsed_args.project,
+ parsed_args.project_domain,
+ ).id
+ obj = client.create_tap_flow(**attrs)
+ display_columns, columns = tap_service._get_columns(obj)
+ data = osc_utils.get_dict_properties(obj, columns)
+ return display_columns, data
+
+
+class ListTapFlow(command.Lister):
+ _description = _("List tap flows.")
+
+ def get_parser(self, prog_name):
+ parser = super().get_parser(prog_name)
+ identity_utils.add_project_owner_option_to_parser(parser)
+
+ return parser
+
+ def take_action(self, parsed_args):
+ client = self.app.client_manager.network
+ params = {}
+ if parsed_args.project is not None:
+ params['project_id'] = common.find_project(
+ self.app.client_manager.identity,
+ parsed_args.project,
+ parsed_args.project_domain,
+ ).id
+ objs = client.tap_flows(retrieve_all=True, params=params)
+ headers, columns = column_util.get_column_definitions(
+ _attr_map, long_listing=True
+ )
+ return (
+ headers,
+ (
+ osc_utils.get_dict_properties(
+ s, columns, formatters=_formatters
+ )
+ for s in objs
+ ),
+ )
+
+
+class ShowTapFlow(command.ShowOne):
+ _description = _("Show tap flow details.")
+
+ def get_parser(self, prog_name):
+ parser = super().get_parser(prog_name)
+ parser.add_argument(
+ TAP_FLOW,
+ metavar=f"<{TAP_FLOW}>",
+ help=_("Tap flow to display (name or ID)."),
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ client = self.app.client_manager.network
+ id = client.find_tap_flow(
+ parsed_args.tap_flow, ignore_missing=False
+ ).id
+ obj = client.get_tap_flow(id)
+ display_columns, columns = tap_service._get_columns(obj)
+ data = osc_utils.get_dict_properties(obj, columns)
+ return display_columns, data
+
+
+class DeleteTapFlow(command.Command):
+ _description = _("Delete a tap flow.")
+
+ def get_parser(self, prog_name):
+ parser = super().get_parser(prog_name)
+ parser.add_argument(
+ TAP_FLOW,
+ metavar=f"<{TAP_FLOW}>",
+ nargs="+",
+ help=_("Tap flow to delete (name or ID)."),
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ client = self.app.client_manager.network
+ fails = 0
+ for id_or_name in parsed_args.tap_flow:
+ try:
+ id = client.find_tap_flow(id_or_name, ignore_missing=False).id
+ client.delete_tap_flow(id)
+ except Exception as e:
+ fails += 1
+ LOG.error(
+ "Failed to delete tap flow with name or ID "
+ "'%(id_or_name)s': %(e)s",
+ {'id_or_name': id_or_name, 'e': e},
+ )
+ if fails > 0:
+ msg = _("Failed to delete %(fails)s of %(total)s tap flow.") % {
+ 'fails': fails,
+ 'total': len(parsed_args.tap_flow),
+ }
+ raise exceptions.CommandError(msg)
+
+
+class UpdateTapFlow(command.ShowOne):
+ _description = _("Update a tap flow.")
+
+ def get_parser(self, prog_name):
+ parser = super().get_parser(prog_name)
+ parser.add_argument(
+ TAP_FLOW,
+ metavar=f"<{TAP_FLOW}>",
+ help=_("Tap flow to modify (name or ID)."),
+ )
+ _add_updatable_args(parser)
+ return parser
+
+ def take_action(self, parsed_args):
+ client = self.app.client_manager.network
+ original_t_f = client.find_tap_flow(
+ parsed_args.tap_flow, ignore_missing=False
+ ).id
+ attrs = {}
+ if parsed_args.name is not None:
+ attrs['name'] = parsed_args.name
+ if parsed_args.description is not None:
+ attrs['description'] = parsed_args.description
+ obj = client.update_tap_flow(original_t_f, **attrs)
+ columns, display_columns = column_util.get_columns(obj, _attr_map)
+ data = osc_utils.get_dict_properties(obj, columns)
+ return display_columns, data
diff --git a/openstackclient/network/v2/taas/tap_mirror.py b/openstackclient/network/v2/taas/tap_mirror.py
new file mode 100644
index 0000000..876109d
--- /dev/null
+++ b/openstackclient/network/v2/taas/tap_mirror.py
@@ -0,0 +1,237 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import logging
+
+from osc_lib.cli import identity as identity_utils
+from osc_lib import exceptions
+from osc_lib import utils as osc_utils
+from osc_lib.utils import columns as column_util
+
+from openstackclient import command
+from openstackclient.i18n import _
+from openstackclient.identity import common
+from openstackclient.network.v2 import port as osc_port
+from openstackclient.network.v2.taas import tap_service
+
+LOG = logging.getLogger(__name__)
+
+TAP_MIRROR = 'tap_mirror'
+TAP_MIRRORS = f'{TAP_MIRROR}s'
+
+_attr_map = [
+ ('id', 'ID', column_util.LIST_BOTH),
+ ('tenant_id', 'Tenant', column_util.LIST_LONG_ONLY),
+ ('name', 'Name', column_util.LIST_BOTH),
+ ('port_id', 'Port', column_util.LIST_BOTH),
+ ('directions', 'Directions', column_util.LIST_LONG_ONLY),
+ ('remote_ip', 'Remote IP', column_util.LIST_BOTH),
+ ('mirror_type', 'Mirror Type', column_util.LIST_LONG_ONLY),
+]
+
+
+def _get_columns(item):
+ column_map: dict[str, str] = {}
+ hidden_columns = ['location', 'tenant_id']
+ return osc_utils.get_osc_show_columns_for_sdk_resource(
+ item, column_map, hidden_columns
+ )
+
+
+class CreateTapMirror(command.ShowOne):
+ _description = _("Create a new tap mirror.")
+
+ def get_parser(self, prog_name):
+ parser = super().get_parser(prog_name)
+ identity_utils.add_project_owner_option_to_parser(parser)
+ tap_service._add_updatable_args(parser)
+ parser.add_argument(
+ '--port',
+ dest='port_id',
+ required=True,
+ metavar="PORT",
+ help=_('Port (name or ID) to which the Tap Mirror is connected.'),
+ )
+ parser.add_argument(
+ '--directions',
+ dest='directions',
+ action=osc_port.JSONKeyValueAction,
+ required=True,
+ help=_(
+ 'Dictionary of direction and tunnel_id. Valid directions are: '
+ 'IN and OUT.'
+ ),
+ )
+ parser.add_argument(
+ '--remote-ip',
+ dest='remote_ip',
+ required=True,
+ help=_(
+ 'Remote IP address for the tap mirror (remote end of the '
+ 'GRE or ERSPAN v1 tunnel).'
+ ),
+ )
+ parser.add_argument(
+ '--mirror-type',
+ dest='mirror_type',
+ required=True,
+ help=_('Mirror type. Valid values are: gre and erspanv1.'),
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ client = self.app.client_manager.network
+ attrs = {}
+ if parsed_args.name is not None:
+ attrs['name'] = parsed_args.name
+ if parsed_args.description is not None:
+ attrs['description'] = parsed_args.description
+ if parsed_args.port_id is not None:
+ port_id = client.find_port(
+ parsed_args.port_id, ignore_missing=False
+ ).id
+ attrs['port_id'] = port_id
+ if parsed_args.directions is not None:
+ attrs['directions'] = parsed_args.directions
+ if parsed_args.remote_ip is not None:
+ attrs['remote_ip'] = parsed_args.remote_ip
+ if parsed_args.mirror_type is not None:
+ attrs['mirror_type'] = parsed_args.mirror_type
+ if 'project' in parsed_args and parsed_args.project is not None:
+ attrs['project_id'] = common.find_project(
+ self.app.client_manager.identity,
+ parsed_args.project,
+ parsed_args.project_domain,
+ ).id
+ obj = client.create_tap_mirror(**attrs)
+ display_columns, columns = tap_service._get_columns(obj)
+ data = osc_utils.get_dict_properties(obj, columns)
+ return display_columns, data
+
+
+class ListTapMirror(command.Lister):
+ _description = _("List tap mirrors.")
+
+ def get_parser(self, prog_name):
+ parser = super().get_parser(prog_name)
+ identity_utils.add_project_owner_option_to_parser(parser)
+
+ return parser
+
+ def take_action(self, parsed_args):
+ client = self.app.client_manager.network
+ params = {}
+ if parsed_args.project is not None:
+ params['project_id'] = common.find_project(
+ self.app.client_manager.identity,
+ parsed_args.project,
+ parsed_args.project_domain,
+ ).id
+ objs = client.tap_mirrors(retrieve_all=True, params=params)
+ headers, columns = column_util.get_column_definitions(
+ _attr_map, long_listing=True
+ )
+ return (
+ headers,
+ (osc_utils.get_dict_properties(s, columns) for s in objs),
+ )
+
+
+class ShowTapMirror(command.ShowOne):
+ _description = _("Show tap mirror details.")
+
+ def get_parser(self, prog_name):
+ parser = super().get_parser(prog_name)
+ parser.add_argument(
+ TAP_MIRROR,
+ metavar=f"<{TAP_MIRROR}>",
+ help=_("Tap mirror to display (name or ID)."),
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ client = self.app.client_manager.network
+ id = client.find_tap_mirror(
+ parsed_args.tap_mirror, ignore_missing=False
+ ).id
+ obj = client.get_tap_mirror(id)
+ display_columns, columns = tap_service._get_columns(obj)
+ data = osc_utils.get_dict_properties(obj, columns)
+ return display_columns, data
+
+
+class DeleteTapMirror(command.Command):
+ _description = _("Delete a tap mirror.")
+
+ def get_parser(self, prog_name):
+ parser = super().get_parser(prog_name)
+ parser.add_argument(
+ TAP_MIRROR,
+ metavar=f"<{TAP_MIRROR}>",
+ nargs="+",
+ help=_("Tap mirror to delete (name or ID)."),
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ client = self.app.client_manager.network
+ fails = 0
+ for id_or_name in parsed_args.tap_mirror:
+ try:
+ id = client.find_tap_mirror(
+ id_or_name, ignore_missing=False
+ ).id
+
+ client.delete_tap_mirror(id)
+ LOG.warning("Tap Mirror %(id)s deleted", {'id': id})
+ except Exception as e:
+ fails += 1
+ LOG.error(
+ "Failed to delete Tap Mirror with name or ID "
+ "'%(id_or_name)s': %(e)s",
+ {'id_or_name': id_or_name, 'e': e},
+ )
+ if fails > 0:
+ msg = _("Failed to delete %(fails)s of %(total)s Tap Mirror.") % {
+ 'fails': fails,
+ 'total': len(parsed_args.tap_mirror),
+ }
+ raise exceptions.CommandError(msg)
+
+
+class UpdateTapMirror(command.ShowOne):
+ _description = _("Update a tap mirror.")
+
+ def get_parser(self, prog_name):
+ parser = super().get_parser(prog_name)
+ parser.add_argument(
+ TAP_MIRROR,
+ metavar=f"<{TAP_MIRROR}>",
+ help=_("Tap mirror to modify (name or ID)."),
+ )
+ tap_service._add_updatable_args(parser)
+ return parser
+
+ def take_action(self, parsed_args):
+ client = self.app.client_manager.network
+ original_t_s = client.find_tap_mirror(
+ parsed_args.tap_mirror, ignore_missing=False
+ ).id
+ attrs = {}
+ if parsed_args.name is not None:
+ attrs['name'] = parsed_args.name
+ if parsed_args.description is not None:
+ attrs['description'] = parsed_args.description
+ obj = client.update_tap_mirror(original_t_s, **attrs)
+ display_columns, columns = tap_service._get_columns(obj)
+ data = osc_utils.get_dict_properties(obj, columns)
+ return display_columns, data
diff --git a/openstackclient/network/v2/taas/tap_service.py b/openstackclient/network/v2/taas/tap_service.py
new file mode 100644
index 0000000..df27658
--- /dev/null
+++ b/openstackclient/network/v2/taas/tap_service.py
@@ -0,0 +1,211 @@
+# All Rights Reserved 2020
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import logging
+
+from osc_lib.cli import identity as identity_utils
+from osc_lib import exceptions
+from osc_lib import utils as osc_utils
+from osc_lib.utils import columns as column_util
+
+from openstackclient import command
+from openstackclient.i18n import _
+from openstackclient.identity import common
+
+LOG = logging.getLogger(__name__)
+
+TAP_SERVICE = 'tap_service'
+TAP_SERVICES = f'{TAP_SERVICE}s'
+
+_attr_map = [
+ ('id', 'ID', column_util.LIST_BOTH),
+ ('tenant_id', 'Tenant', column_util.LIST_LONG_ONLY),
+ ('name', 'Name', column_util.LIST_BOTH),
+ ('port_id', 'Port', column_util.LIST_BOTH),
+ ('status', 'Status', column_util.LIST_BOTH),
+]
+
+
+def _add_updatable_args(parser):
+ parser.add_argument('--name', help=_('Name of the tap service.'))
+ parser.add_argument(
+ '--description', help=_('Description of the tap service.')
+ )
+
+
+def _get_columns(item):
+ column_map: dict[str, str] = {}
+ hidden_columns = ['location', 'tenant_id']
+ return osc_utils.get_osc_show_columns_for_sdk_resource(
+ item, column_map, hidden_columns
+ )
+
+
+class CreateTapService(command.ShowOne):
+ _description = _("Create a new tap service.")
+
+ def get_parser(self, prog_name):
+ parser = super().get_parser(prog_name)
+ identity_utils.add_project_owner_option_to_parser(parser)
+ _add_updatable_args(parser)
+ parser.add_argument(
+ '--port',
+ dest='port_id',
+ required=True,
+ metavar="PORT",
+ help=_('Port (name or ID) to connect to the tap service.'),
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ client = self.app.client_manager.network
+ attrs = {}
+ if parsed_args.name is not None:
+ attrs['name'] = parsed_args.name
+ if parsed_args.description is not None:
+ attrs['description'] = parsed_args.description
+ if parsed_args.port_id is not None:
+ port_id = client.find_port(
+ parsed_args.port_id, ignore_missing=False
+ ).id
+ attrs['port_id'] = port_id
+ if 'project' in parsed_args and parsed_args.project is not None:
+ attrs['project_id'] = common.find_project(
+ self.app.client_manager.identity,
+ parsed_args.project,
+ parsed_args.project_domain,
+ ).id
+ obj = client.create_tap_service(**attrs)
+ display_columns, columns = _get_columns(obj)
+ data = osc_utils.get_dict_properties(obj, columns)
+ return display_columns, data
+
+
+class ListTapService(command.Lister):
+ _description = _("List tap services.")
+
+ def get_parser(self, prog_name):
+ parser = super().get_parser(prog_name)
+ identity_utils.add_project_owner_option_to_parser(parser)
+
+ return parser
+
+ def take_action(self, parsed_args):
+ client = self.app.client_manager.network
+ params = {}
+ if parsed_args.project is not None:
+ params['project_id'] = common.find_project(
+ self.app.client_manager.identity,
+ parsed_args.project,
+ parsed_args.project_domain,
+ ).id
+ objs = client.tap_services(retrieve_all=True, params=params)
+ headers, columns = column_util.get_column_definitions(
+ _attr_map, long_listing=True
+ )
+ return (
+ headers,
+ (osc_utils.get_dict_properties(s, columns) for s in objs),
+ )
+
+
+class ShowTapService(command.ShowOne):
+ _description = _("Show tap service details.")
+
+ def get_parser(self, prog_name):
+ parser = super().get_parser(prog_name)
+ parser.add_argument(
+ TAP_SERVICE,
+ metavar=f"<{TAP_SERVICE}>",
+ help=_("Tap service to display (name or ID)."),
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ client = self.app.client_manager.network
+ id = client.find_tap_service(
+ parsed_args.tap_service, ignore_missing=False
+ ).id
+ obj = client.get_tap_service(id)
+ display_columns, columns = _get_columns(obj)
+ data = osc_utils.get_dict_properties(obj, columns)
+ return display_columns, data
+
+
+class DeleteTapService(command.Command):
+ _description = _("Delete a tap service.")
+
+ def get_parser(self, prog_name):
+ parser = super().get_parser(prog_name)
+ parser.add_argument(
+ TAP_SERVICE,
+ metavar=f"<{TAP_SERVICE}>",
+ nargs="+",
+ help=_("Tap service to delete (name or ID)."),
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ client = self.app.client_manager.network
+ fails = 0
+ for id_or_name in parsed_args.tap_service:
+ try:
+ id = client.find_tap_service(
+ id_or_name, ignore_missing=False
+ ).id
+
+ client.delete_tap_service(id)
+ LOG.warning("Tap service %(id)s deleted", {'id': id})
+ except Exception as e:
+ fails += 1
+ LOG.error(
+ "Failed to delete tap service with name or ID "
+ "'%(id_or_name)s': %(e)s",
+ {'id_or_name': id_or_name, 'e': e},
+ )
+ if fails > 0:
+ msg = _("Failed to delete %(fails)s of %(total)s tap service.") % {
+ 'fails': fails,
+ 'total': len(parsed_args.tap_service),
+ }
+ raise exceptions.CommandError(msg)
+
+
+class UpdateTapService(command.ShowOne):
+ _description = _("Update a tap service.")
+
+ def get_parser(self, prog_name):
+ parser = super().get_parser(prog_name)
+ parser.add_argument(
+ TAP_SERVICE,
+ metavar=f"<{TAP_SERVICE}>",
+ help=_("Tap service to modify (name or ID)."),
+ )
+ _add_updatable_args(parser)
+ return parser
+
+ def take_action(self, parsed_args):
+ client = self.app.client_manager.network
+ original_t_s = client.find_tap_service(
+ parsed_args.tap_service, ignore_missing=False
+ ).id
+ attrs = {}
+ if parsed_args.name is not None:
+ attrs['name'] = parsed_args.name
+ if parsed_args.description is not None:
+ attrs['description'] = parsed_args.description
+ obj = client.update_tap_service(original_t_s, **attrs)
+ display_columns, columns = _get_columns(obj)
+ data = osc_utils.get_dict_properties(obj, columns)
+ return display_columns, data
diff --git a/openstackclient/object/v1/account.py b/openstackclient/object/v1/account.py
index 686fdcc..199e522 100644
--- a/openstackclient/object/v1/account.py
+++ b/openstackclient/object/v1/account.py
@@ -15,8 +15,8 @@
from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
-from osc_lib.command import command
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/object/v1/container.py b/openstackclient/object/v1/container.py
index f4250db..b0f92c7 100644
--- a/openstackclient/object/v1/container.py
+++ b/openstackclient/object/v1/container.py
@@ -19,9 +19,9 @@ import logging
from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import utils
+from openstackclient import command
from openstackclient.common import pagination
from openstackclient.i18n import _
diff --git a/openstackclient/object/v1/object.py b/openstackclient/object/v1/object.py
index cb8e4ff..e8ee0fc 100644
--- a/openstackclient/object/v1/object.py
+++ b/openstackclient/object/v1/object.py
@@ -19,10 +19,10 @@ import logging
from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.common import pagination
from openstackclient.i18n import _
diff --git a/openstackclient/shell.py b/openstackclient/shell.py
index 6bbbb5f..743ed2b 100644
--- a/openstackclient/shell.py
+++ b/openstackclient/shell.py
@@ -26,16 +26,27 @@ from osc_lib import shell
import openstackclient
from openstackclient.common import clientmanager
-
DEFAULT_DOMAIN = 'default'
+# list of modules that were originally out-of-tree and are now in
+# core OSC
+IGNORED_MODULES = (
+ 'neutron_taas.taas_client.osc',
+ 'neutronclient.osc.v2.taas',
+)
class OpenStackShell(shell.OpenStackShell):
+ client_manager: clientmanager.ClientManager
+
def __init__(self):
+ command_manager = commandmanager.CommandManager(
+ 'openstack.cli', ignored_modules=IGNORED_MODULES
+ )
+
super().__init__(
description=__doc__.strip(),
version=openstackclient.__version__,
- command_manager=commandmanager.CommandManager('openstack.cli'),
+ command_manager=command_manager,
deferred_help=True,
)
@@ -48,8 +59,10 @@ class OpenStackShell(shell.OpenStackShell):
# about them
warnings.filterwarnings('ignore', module='openstack')
- def build_option_parser(self, description, version):
- parser = super().build_option_parser(description, version)
+ def build_option_parser(self, description, version, argparse_kwargs=None):
+ parser = super().build_option_parser(
+ description, version, argparse_kwargs
+ )
parser = clientmanager.build_plugin_option_parser(parser)
parser = auth.build_auth_plugins_option_parser(parser)
return parser
@@ -65,10 +78,7 @@ class OpenStackShell(shell.OpenStackShell):
self._auth_type = 'password'
def _load_plugins(self):
- """Load plugins via stevedore
-
- osc-lib has no opinion on what plugins should be loaded
- """
+ """Load plugins via stevedore."""
# Loop through extensions to get API versions
for mod in clientmanager.PLUGIN_MODULES:
default_version = getattr(mod, 'DEFAULT_API_VERSION', None)
diff --git a/openstackclient/tests/functional/identity/v3/test_catalog.py b/openstackclient/tests/functional/identity/v3/test_catalog.py
index f4089b7..429f94a 100644
--- a/openstackclient/tests/functional/identity/v3/test_catalog.py
+++ b/openstackclient/tests/functional/identity/v3/test_catalog.py
@@ -10,35 +10,54 @@
# License for the specific language governing permissions and limitations
# under the License.
+
from openstackclient.tests.functional.identity.v3 import common
class CatalogTests(common.IdentityTests):
- def test_catalog_list(self):
+ """Functional tests for catalog commands"""
+
+ def test_catalog(self):
+ """Test catalog list and show functionality"""
+ # Create a test service for isolated testing
+ _dummy_service_name = self._create_dummy_service(add_clean_up=True)
+
+ # list catalogs
raw_output = self.openstack('catalog list')
items = self.parse_listing(raw_output)
self.assert_table_structure(items, ['Name', 'Type', 'Endpoints'])
- def test_catalog_show(self):
- """test catalog show command
-
- The output example:
- +-----------+----------------------------------------+
- | Field | Value |
- +-----------+----------------------------------------+
- | endpoints | test1 |
- | | public: http://localhost:5000/v2.0 |
- | | test1 |
- | | internal: http://localhost:5000/v2.0 |
- | | test1 |
- | | admin: http://localhost:35357/v2.0 |
- | | |
- | id | e1e68b5ba21a43a39ff1cf58e736c3aa |
- | name | keystone |
- | type | identity |
- +-----------+----------------------------------------+
- """
- raw_output = self.openstack('catalog show {}'.format('identity'))
+ # Verify created service appears in catalog
+ service_names = [
+ item.get('Name') for item in items if item.get('Name')
+ ]
+ self.assertIn(
+ _dummy_service_name,
+ service_names,
+ "Created dummy service should be present in catalog",
+ )
+
+ # show service (by name)
+ raw_output = self.openstack(f'catalog show {_dummy_service_name}')
items = self.parse_show(raw_output)
- # items may have multiple endpoint urls with empty key
- self.assert_show_fields(items, ['endpoints', 'name', 'type', '', 'id'])
+ self.assert_show_fields(items, ['endpoints', 'name', 'type', 'id'])
+
+ # Extract the type from the dummy service
+ _dummy_service_type = next(
+ (item['type'] for item in items if 'type' in item), None
+ )
+
+ # show service (by type)
+ raw_output = self.openstack(f'catalog show {_dummy_service_type}')
+ items = self.parse_show(raw_output)
+ self.assert_show_fields(items, ['endpoints', 'name', 'type', 'id'])
+
+ # show service (non-existent)
+ result = self.openstack(
+ 'catalog show nonexistent-service-xyz', fail_ok=True
+ )
+ self.assertEqual(
+ '',
+ result.strip(),
+ "Non-existent service should return empty result",
+ )
diff --git a/openstackclient/tests/functional/identity/v3/test_limit.py b/openstackclient/tests/functional/identity/v3/test_limit.py
index 8c0bbcd..497d33a 100644
--- a/openstackclient/tests/functional/identity/v3/test_limit.py
+++ b/openstackclient/tests/functional/identity/v3/test_limit.py
@@ -100,6 +100,53 @@ class LimitTestCase(common.IdentityTests):
self.assert_show_fields(items, self.LIMIT_FIELDS)
registered_limit_id = self._create_dummy_registered_limit()
+ def test_limit_create_with_project_domain(self):
+ registered_limit_id = self._create_dummy_registered_limit()
+ raw_output = self.openstack(
+ f'registered limit show {registered_limit_id}',
+ cloud=SYSTEM_CLOUD,
+ )
+ items = self.parse_show(raw_output)
+ service_id = self._extract_value_from_items('service_id', items)
+ resource_name = self._extract_value_from_items('resource_name', items)
+
+ raw_output = self.openstack(f'service show {service_id}')
+ items = self.parse_show(raw_output)
+ service_name = self._extract_value_from_items('name', items)
+
+ project_name = self._create_dummy_project()
+ raw_output = self.openstack(
+ f'project show {project_name}',
+ cloud=SYSTEM_CLOUD,
+ )
+ items = self.parse_show(raw_output)
+ domain_id = self._extract_value_from_items('domain_id', items)
+
+ params = {
+ 'project_name': project_name,
+ 'project_domain': domain_id,
+ 'service_name': service_name,
+ 'resource_name': resource_name,
+ 'resource_limit': 15,
+ }
+ raw_output = self.openstack(
+ 'limit create'
+ ' --project {project_name}'
+ ' --project-domain {project_domain}'
+ ' --service {service_name}'
+ ' --resource-limit {resource_limit}'
+ ' {resource_name}'.format(**params),
+ cloud=SYSTEM_CLOUD,
+ )
+ items = self.parse_show(raw_output)
+ limit_id = self._extract_value_from_items('id', items)
+ self.addCleanup(
+ self.openstack, f'limit delete {limit_id}', cloud=SYSTEM_CLOUD
+ )
+
+ self.assert_show_fields(items, self.LIMIT_FIELDS)
+ registered_limit_id = self._create_dummy_registered_limit()
+
def test_limit_create_with_service_id(self):
self._create_dummy_limit()
diff --git a/openstackclient/tests/functional/identity/v3/test_role_assignment.py b/openstackclient/tests/functional/identity/v3/test_role_assignment.py
index 76e33c2..1255841 100644
--- a/openstackclient/tests/functional/identity/v3/test_role_assignment.py
+++ b/openstackclient/tests/functional/identity/v3/test_role_assignment.py
@@ -62,6 +62,47 @@ class RoleAssignmentTests(common.IdentityTests):
items = self.parse_listing(raw_output)
self.assert_table_structure(items, self.ROLE_ASSIGNMENT_LIST_HEADERS)
+ def test_role_assignment_list_group_domain(self):
+ domain_name_A = self._create_dummy_domain()
+ domain_name_B = self._create_dummy_domain()
+ role_name = self._create_dummy_role()
+ group_name = 'group_name'
+ self.openstack(f'group create --domain {domain_name_A} {group_name}')
+ self.addCleanup(
+ self.openstack,
+ f'group delete --domain {domain_name_A} {group_name}',
+ )
+ self.openstack(f'group create --domain {domain_name_B} {group_name}')
+ self.addCleanup(
+ self.openstack,
+ f'group delete --domain {domain_name_B} {group_name}',
+ )
+ raw_output = self.openstack(
+ 'role add '
+ f'--project {self.project_name} '
+ f'--group {group_name} --group-domain {domain_name_A} '
+ f'{role_name}'
+ )
+ self.addCleanup(
+ self.openstack,
+ 'role remove '
+ f'--project {self.project_name} '
+ f'--group {group_name} --group-domain {domain_name_A} '
+ f'{role_name}',
+ )
+ self.assertEqual('', raw_output.strip())
+ raw_output = self.openstack(
+ f'role assignment list '
+ f'--group {group_name} --group-domain {domain_name_A} '
+ )
+ items = self.parse_listing(raw_output)
+ self.assert_table_structure(items, self.ROLE_ASSIGNMENT_LIST_HEADERS)
+ raw_output = self.openstack(
+ f'role assignment list '
+ f'--group {group_name} --group-domain {domain_name_B} '
+ )
+ self.assertEqual('', raw_output.strip())
+
def test_role_assignment_list_domain(self):
role_name = self._create_dummy_role()
username = self._create_dummy_user()
@@ -85,6 +126,89 @@ class RoleAssignmentTests(common.IdentityTests):
items = self.parse_listing(raw_output)
self.assert_table_structure(items, self.ROLE_ASSIGNMENT_LIST_HEADERS)
+ def test_role_assignment_list_user_domain(self):
+ domain_name_A = self._create_dummy_domain()
+ domain_name_B = self._create_dummy_domain()
+ role_name = self._create_dummy_role()
+ username = 'username'
+ self.openstack(f'user create --domain {domain_name_A} {username}')
+ self.addCleanup(
+ self.openstack, f'user delete --domain {domain_name_A} {username}'
+ )
+ self.openstack(f'user create --domain {domain_name_B} {username}')
+ self.addCleanup(
+ self.openstack, f'user delete --domain {domain_name_B} {username}'
+ )
+ raw_output = self.openstack(
+ 'role add '
+ f'--project {self.project_name} '
+ f'--user {username} --user-domain {domain_name_A} '
+ f'{role_name}'
+ )
+ self.addCleanup(
+ self.openstack,
+ 'role remove '
+ f'--project {self.project_name} '
+ f'--user {username} --user-domain {domain_name_A} '
+ f'{role_name}',
+ )
+ self.assertEqual('', raw_output.strip())
+ raw_output = self.openstack(
+ f'role assignment list '
+ f'--user {username} --user-domain {domain_name_A} '
+ )
+ items = self.parse_listing(raw_output)
+ self.assert_table_structure(items, self.ROLE_ASSIGNMENT_LIST_HEADERS)
+ raw_output = self.openstack(
+ f'role assignment list '
+ f'--user {username} --user-domain {domain_name_B} '
+ )
+ self.assertEqual('', raw_output.strip())
+
+ def test_role_assignment_list_role_domain(self):
+ domain_name_A = self._create_dummy_domain()
+ domain_name_B = self._create_dummy_domain()
+ role_name = 'role_name'
+ username = 'username'
+ self.openstack(f'role create --domain {domain_name_A} {role_name}')
+ self.addCleanup(
+ self.openstack, f'role delete --domain {domain_name_A} {role_name}'
+ )
+ self.openstack(f'role create --domain {domain_name_B} {role_name}')
+ self.addCleanup(
+ self.openstack, f'role delete --domain {domain_name_B} {role_name}'
+ )
+ self.openstack(f'user create --domain {domain_name_A} {username}')
+ self.addCleanup(
+ self.openstack, f'user delete --domain {domain_name_A} {username}'
+ )
+ raw_output = self.openstack(
+ 'role add '
+ f'--user {username} --domain {domain_name_A} '
+ f'--role-domain {domain_name_A} '
+ f'{role_name}'
+ )
+ self.addCleanup(
+ self.openstack,
+ 'role remove '
+ f'--user {username} --domain {domain_name_A} '
+ f'--role-domain {domain_name_A} '
+ f'{role_name}',
+ )
+ self.assertEqual('', raw_output.strip())
+ raw_output = self.openstack(
+ f'role assignment list '
+ f'--role {role_name} --role-domain {domain_name_A}'
+ )
+ items = self.parse_listing(raw_output)
+ self.assert_table_structure(items, self.ROLE_ASSIGNMENT_LIST_HEADERS)
+ raw_output = self.openstack(
+ f'role assignment list '
+ f'--role {role_name} --role-domain {domain_name_B}'
+ )
+ items = self.parse_listing(raw_output)
+ self.assertEqual('', raw_output.strip())
+
def test_role_assignment_list_project(self):
role_name = self._create_dummy_role()
username = self._create_dummy_user()
@@ -108,6 +232,56 @@ class RoleAssignmentTests(common.IdentityTests):
items = self.parse_listing(raw_output)
self.assert_table_structure(items, self.ROLE_ASSIGNMENT_LIST_HEADERS)
+ def test_role_assignment_list_project_domain(self):
+ domain_name_A = self._create_dummy_domain()
+ domain_name_B = self._create_dummy_domain()
+ role_name = self._create_dummy_role()
+ project_name = 'project_name'
+ username = 'username'
+ self.openstack(
+ f'project create --domain {domain_name_A} {project_name}'
+ )
+ self.addCleanup(
+ self.openstack,
+ f'project delete --domain {domain_name_A} {project_name}',
+ )
+ self.openstack(
+ f'project create --domain {domain_name_B} {project_name}'
+ )
+ self.addCleanup(
+ self.openstack,
+ f'project delete --domain {domain_name_B} {project_name}',
+ )
+ self.openstack(f'user create --domain {domain_name_A} {username}')
+ self.addCleanup(
+ self.openstack, f'user delete --domain {domain_name_A} {username}'
+ )
+ raw_output = self.openstack(
+ 'role add '
+ f'--project {project_name} --project-domain {domain_name_A} '
+ f'--user {username} --user-domain {domain_name_A} '
+ f'{role_name}'
+ )
+ self.addCleanup(
+ self.openstack,
+ 'role remove '
+ f'--project {project_name} --project-domain {domain_name_A} '
+ f'--user {username} --user-domain {domain_name_A} '
+ f'{role_name}',
+ )
+ self.assertEqual('', raw_output.strip())
+ raw_output = self.openstack(
+ f'role assignment list '
+ f'--project {project_name} --project-domain {domain_name_A} '
+ )
+ items = self.parse_listing(raw_output)
+ self.assert_table_structure(items, self.ROLE_ASSIGNMENT_LIST_HEADERS)
+ raw_output = self.openstack(
+ f'role assignment list '
+ f'--project {project_name} --project-domain {domain_name_B} '
+ )
+ self.assertEqual('', raw_output.strip())
+
def test_role_assignment_list_effective(self):
raw_output = self.openstack('role assignment list --effective')
items = self.parse_listing(raw_output)
diff --git a/openstackclient/tests/functional/image/v2/test_cache.py b/openstackclient/tests/functional/image/v2/test_cache.py
new file mode 100644
index 0000000..58245e5
--- /dev/null
+++ b/openstackclient/tests/functional/image/v2/test_cache.py
@@ -0,0 +1,54 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import uuid
+
+from openstackclient.tests.functional.image import base
+
+
+class CacheTests(base.BaseImageTests):
+ """Functional tests for Cache commands"""
+
+ def test_cached_image(self):
+ """Test cached image operations including queue and clear"""
+ # Create test image
+ name = uuid.uuid4().hex
+ output = self.openstack(
+ f'image create {name}',
+ parse_output=True,
+ )
+ image_id = output["id"]
+ self.assertOutput(name, output['name'])
+
+ # Register cleanup for created image
+ self.addCleanup(
+ self.openstack, 'cached image delete ' + image_id, fail_ok=True
+ )
+ self.addCleanup(self.openstack, 'image delete ' + image_id)
+
+ # Queue image for caching
+ self.openstack('cached image queue ' + image_id)
+
+ # Verify queuing worked
+ cache_output = self.openstack('cached image list', parse_output=True)
+ self.assertIsInstance(cache_output, list)
+ image_ids = [img['ID'] for img in cache_output]
+ self.assertIn(image_id, image_ids)
+
+ # Clear cached images
+ self.openstack('cached image clear')
+
+ # Verify clearing worked
+ output = self.openstack('cached image list', parse_output=True)
+ if output:
+ image_ids = [img['ID'] for img in output]
+ self.assertNotIn(image_id, image_ids)
diff --git a/openstackclient/tests/functional/image/v2/test_metadef_objects.py b/openstackclient/tests/functional/image/v2/test_metadef_objects.py
new file mode 100644
index 0000000..5216c93
--- /dev/null
+++ b/openstackclient/tests/functional/image/v2/test_metadef_objects.py
@@ -0,0 +1,69 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from openstackclient.tests.functional import base
+
+
+class MetadefObjectTests(base.TestCase):
+ def setUp(self):
+ super().setUp()
+ self.obj_name = self.getUniqueString('metadef-obj')
+ self.ns_name = self.getUniqueString('metadef-ns')
+ self.openstack(f"image metadef namespace create {self.ns_name}")
+ self.addCleanup(
+ lambda: self.openstack(
+ f"image metadef namespace delete {self.ns_name}"
+ )
+ )
+
+ def test_metadef_objects(self):
+ # CREATE
+ created = self.openstack(
+ (
+ "image metadef object create "
+ f"--namespace {self.ns_name} "
+ f"{self.obj_name}"
+ ),
+ parse_output=True,
+ )
+ self.addCleanup(
+ lambda: self.openstack(
+ f"image metadef object delete {self.ns_name} {self.obj_name}"
+ )
+ )
+ self.assertEqual(self.obj_name, created["name"])
+ self.assertEqual(self.ns_name, created["namespace_name"])
+
+ # UPDATE
+ new_name = f"{self.obj_name}-updated"
+ self.openstack(
+ "image metadef object update "
+ f"{self.ns_name} {self.obj_name} "
+ f"--name {new_name}"
+ )
+ self.obj_name = new_name
+
+ # READ (get)
+ shown = self.openstack(
+ f"image metadef object show {self.ns_name} {self.obj_name}",
+ parse_output=True,
+ )
+ self.assertEqual(self.obj_name, shown["name"])
+ self.assertEqual(self.ns_name, shown["namespace_name"])
+
+ # READ (list)
+ rows = self.openstack(
+ f"image metadef object list {self.ns_name}",
+ parse_output=True,
+ )
+ names = {row["name"] for row in rows}
+ self.assertIn(self.obj_name, names)
diff --git a/openstackclient/tests/functional/image/v2/test_metadef_resource_type.py b/openstackclient/tests/functional/image/v2/test_metadef_resource_type.py
new file mode 100644
index 0000000..ab8dc13
--- /dev/null
+++ b/openstackclient/tests/functional/image/v2/test_metadef_resource_type.py
@@ -0,0 +1,55 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import uuid
+
+from openstackclient.tests.functional.image import base
+
+
+class ImageMetadefResourceTypeTests(base.BaseImageTests):
+ """Functional tests for image metadef resource type commands."""
+
+ def setUp(self):
+ super().setUp()
+
+ # Create unique namespace name using UUID
+ self.namespace_name = 'test-mdef-ns-' + uuid.uuid4().hex
+ self.resource_type_name = 'test-mdef-rt-' + uuid.uuid4().hex
+
+ # Create namespace
+ self.openstack('image metadef namespace create ' + self.namespace_name)
+ self.addCleanup(
+ self.openstack,
+ 'image metadef namespace delete ' + self.namespace_name,
+ )
+
+ def test_metadef_resource_type(self):
+ """Test image metadef resource type commands"""
+
+ self.openstack(
+ 'image metadef resource type association create '
+ f'{self.namespace_name} {self.resource_type_name}',
+ )
+ self.addCleanup(
+ self.openstack,
+ 'image metadef resource type association delete '
+ f'{self.namespace_name} {self.resource_type_name}',
+ )
+
+ output = self.openstack(
+ 'image metadef resource type list',
+ parse_output=True,
+ )
+
+ self.assertIn(
+ self.resource_type_name, [item['Name'] for item in output]
+ )
diff --git a/openstackclient/tests/functional/volume/v3/test_volume_snapshot.py b/openstackclient/tests/functional/volume/v3/test_volume_snapshot.py
index 2c9b72b..b84bb03 100644
--- a/openstackclient/tests/functional/volume/v3/test_volume_snapshot.py
+++ b/openstackclient/tests/functional/volume/v3/test_volume_snapshot.py
@@ -23,7 +23,7 @@ class VolumeSnapshotTests(common.BaseVolumeTests):
@classmethod
def setUpClass(cls):
super().setUpClass()
- # create a volume for all tests to create snapshot
+ # create a test volume used by all snapshot tests
cmd_output = cls.openstack(
'volume create ' + '--size 1 ' + cls.VOLLY,
parse_output=True,
@@ -40,147 +40,57 @@ class VolumeSnapshotTests(common.BaseVolumeTests):
finally:
super().tearDownClass()
- def test_volume_snapshot_delete(self):
- """Test create, delete multiple"""
- name1 = uuid.uuid4().hex
- cmd_output = self.openstack(
- 'volume snapshot create ' + name1 + ' --volume ' + self.VOLLY,
- parse_output=True,
- )
- self.assertEqual(
- name1,
- cmd_output["name"],
- )
+ def test_volume_snapshot(self):
+ # create volume snapshot
+ name = uuid.uuid4().hex
- name2 = uuid.uuid4().hex
cmd_output = self.openstack(
- 'volume snapshot create ' + name2 + ' --volume ' + self.VOLLY,
+ 'volume snapshot create '
+ + '--volume '
+ + self.VOLLY
+ + ' --description aaaa '
+ + '--property Alpha=a '
+ + name,
parse_output=True,
)
- self.assertEqual(
- name2,
- cmd_output["name"],
- )
-
- self.wait_for_status('volume snapshot', name1, 'available')
- self.wait_for_status('volume snapshot', name2, 'available')
+ snap_id = cmd_output['id']
- del_output = self.openstack(
- 'volume snapshot delete ' + name1 + ' ' + name2
+ self.addCleanup(self.wait_for_delete, 'volume snapshot', snap_id)
+ # delete volume snapshot
+ self.addCleanup(
+ self.openstack,
+ 'volume snapshot delete ' + snap_id,
)
- self.assertOutput('', del_output)
- self.wait_for_delete('volume snapshot', name1)
- self.wait_for_delete('volume snapshot', name2)
+ self.wait_for_status('volume snapshot', snap_id, 'available')
- def test_volume_snapshot_list(self):
- """Test create, list filter"""
- name1 = uuid.uuid4().hex
- cmd_output = self.openstack(
- 'volume snapshot create ' + name1 + ' --volume ' + self.VOLLY,
+ # show volume snapshot
+ snapshot_info = self.openstack(
+ 'volume snapshot show ' + name,
parse_output=True,
)
- self.addCleanup(self.wait_for_delete, 'volume snapshot', name1)
- self.addCleanup(self.openstack, 'volume snapshot delete ' + name1)
- self.assertEqual(
- name1,
- cmd_output["name"],
- )
- self.assertEqual(
- self.VOLUME_ID,
- cmd_output["volume_id"],
- )
- self.assertEqual(
- 1,
- cmd_output["size"],
- )
- self.wait_for_status('volume snapshot', name1, 'available')
- name2 = uuid.uuid4().hex
- cmd_output = self.openstack(
- 'volume snapshot create ' + name2 + ' --volume ' + self.VOLLY,
- parse_output=True,
- )
- self.addCleanup(self.wait_for_delete, 'volume snapshot', name2)
- self.addCleanup(self.openstack, 'volume snapshot delete ' + name2)
- self.assertEqual(
- name2,
- cmd_output["name"],
- )
- self.assertEqual(
- self.VOLUME_ID,
- cmd_output["volume_id"],
- )
- self.assertEqual(
- 1,
- cmd_output["size"],
- )
- self.wait_for_status('volume snapshot', name2, 'available')
- raw_output = self.openstack(
- 'volume snapshot set ' + '--state error ' + name2
- )
- self.assertOutput('', raw_output)
+ self.assertEqual(name, snapshot_info['name'])
+ self.assertEqual('aaaa', snapshot_info["description"])
+ self.assertEqual({'Alpha': 'a'}, snapshot_info["properties"])
- # Test list --long, --status
+ # list volume snapshot --name
cmd_output = self.openstack(
- 'volume snapshot list ' + '--long ' + '--status error',
+ 'volume snapshot list --name ' + name,
parse_output=True,
)
- names = [x["Name"] for x in cmd_output]
- self.assertNotIn(name1, names)
- self.assertIn(name2, names)
+ names = [x['Name'] for x in cmd_output]
+ self.assertIn(name, names)
- # Test list --volume
+ # list volume snapshot --volume
cmd_output = self.openstack(
'volume snapshot list ' + '--volume ' + self.VOLLY,
parse_output=True,
)
names = [x["Name"] for x in cmd_output]
- self.assertIn(name1, names)
- self.assertIn(name2, names)
+ self.assertIn(name, names)
- # Test list --name
- cmd_output = self.openstack(
- 'volume snapshot list ' + '--name ' + name1,
- parse_output=True,
- )
- names = [x["Name"] for x in cmd_output]
- self.assertIn(name1, names)
- self.assertNotIn(name2, names)
-
- def test_volume_snapshot_set(self):
- """Test create, set, unset, show, delete volume snapshot"""
- name = uuid.uuid4().hex
+ # set volume snapshot
new_name = name + "_"
- cmd_output = self.openstack(
- 'volume snapshot create '
- + '--volume '
- + self.VOLLY
- + ' --description aaaa '
- + '--property Alpha=a '
- + name,
- parse_output=True,
- )
- self.addCleanup(self.wait_for_delete, 'volume snapshot', new_name)
- self.addCleanup(self.openstack, 'volume snapshot delete ' + new_name)
- self.assertEqual(
- name,
- cmd_output["name"],
- )
- self.assertEqual(
- 1,
- cmd_output["size"],
- )
- self.assertEqual(
- 'aaaa',
- cmd_output["description"],
- )
- self.assertEqual(
- {'Alpha': 'a'},
- cmd_output["properties"],
- )
- self.wait_for_status('volume snapshot', name, 'available')
-
- # Test volume snapshot set
raw_output = self.openstack(
'volume snapshot set '
+ '--name '
@@ -188,11 +98,10 @@ class VolumeSnapshotTests(common.BaseVolumeTests):
+ ' --description bbbb '
+ '--property Alpha=c '
+ '--property Beta=b '
- + name,
+ + snap_id,
)
self.assertOutput('', raw_output)
- # Show snapshot set result
cmd_output = self.openstack(
'volume snapshot show ' + new_name,
parse_output=True,
@@ -202,10 +111,6 @@ class VolumeSnapshotTests(common.BaseVolumeTests):
cmd_output["name"],
)
self.assertEqual(
- 1,
- cmd_output["size"],
- )
- self.assertEqual(
'bbbb',
cmd_output["description"],
)
@@ -214,7 +119,7 @@ class VolumeSnapshotTests(common.BaseVolumeTests):
cmd_output["properties"],
)
- # Test volume snapshot unset
+ # unset volume snapshot
raw_output = self.openstack(
'volume snapshot unset ' + '--property Alpha ' + new_name,
)
@@ -229,16 +134,25 @@ class VolumeSnapshotTests(common.BaseVolumeTests):
cmd_output["properties"],
)
- # Test volume snapshot set --no-property
+ # set volume snapshot --no-property, --state error
raw_output = self.openstack(
- 'volume snapshot set ' + '--no-property ' + new_name,
+ 'volume snapshot set '
+ + '--no-property '
+ + '--state error '
+ + new_name,
)
self.assertOutput('', raw_output)
+
cmd_output = self.openstack(
'volume snapshot show ' + new_name,
parse_output=True,
)
- self.assertNotIn(
- {'Beta': 'b'},
- cmd_output["properties"],
+ self.assertEqual({}, cmd_output["properties"])
+
+ # list volume snapshot --long --status
+ cmd_output = self.openstack(
+ 'volume snapshot list ' + '--long ' + '--status error',
+ parse_output=True,
)
+ names = [x["Name"] for x in cmd_output]
+ self.assertIn(new_name, names)
diff --git a/openstackclient/tests/unit/common/test_command.py b/openstackclient/tests/unit/common/test_command.py
index 8233f89..1f1efce 100644
--- a/openstackclient/tests/unit/common/test_command.py
+++ b/openstackclient/tests/unit/common/test_command.py
@@ -14,9 +14,9 @@
from unittest import mock
-from osc_lib.command import command
from osc_lib import exceptions
+from openstackclient import command
from openstackclient.tests.unit import fakes as test_fakes
from openstackclient.tests.unit import utils as test_utils
diff --git a/openstackclient/tests/unit/common/test_extension.py b/openstackclient/tests/unit/common/test_extension.py
index 53d9d65..dd68431 100644
--- a/openstackclient/tests/unit/common/test_extension.py
+++ b/openstackclient/tests/unit/common/test_extension.py
@@ -10,7 +10,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-from unittest import mock
from openstackclient.common import extension
from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes
@@ -295,8 +294,8 @@ class TestExtensionShow(TestExtension):
self.cmd = extension.ShowExtension(self.app, None)
- self.app.client_manager.network.find_extension = mock.Mock(
- return_value=self.extension_details
+ self.app.client_manager.network.find_extension.return_value = (
+ self.extension_details
)
def test_show_no_options(self):
diff --git a/openstackclient/tests/unit/common/test_logs.py b/openstackclient/tests/unit/common/test_logs.py
deleted file mode 100644
index 234ba42..0000000
--- a/openstackclient/tests/unit/common/test_logs.py
+++ /dev/null
@@ -1,221 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-#
-
-# NOTE(dtroyer): This file is deprecated in Jun 2016, remove after 4.x release
-# or Jun 2017.
-
-import logging
-from unittest import mock
-
-from osc_lib import logs
-
-from openstackclient.tests.unit import utils
-
-
-class TestContext(utils.TestCase):
- def test_log_level_from_options(self):
- opts = mock.Mock()
- opts.verbose_level = 0
- self.assertEqual(logging.ERROR, logs.log_level_from_options(opts))
- opts.verbose_level = 1
- self.assertEqual(logging.WARNING, logs.log_level_from_options(opts))
- opts.verbose_level = 2
- self.assertEqual(logging.INFO, logs.log_level_from_options(opts))
- opts.verbose_level = 3
- self.assertEqual(logging.DEBUG, logs.log_level_from_options(opts))
-
- def test_log_level_from_config(self):
- cfg = {'verbose_level': 0}
- self.assertEqual(logging.ERROR, logs.log_level_from_config(cfg))
- cfg = {'verbose_level': 1}
- self.assertEqual(logging.WARNING, logs.log_level_from_config(cfg))
- cfg = {'verbose_level': 2}
- self.assertEqual(logging.INFO, logs.log_level_from_config(cfg))
- cfg = {'verbose_level': 3}
- self.assertEqual(logging.DEBUG, logs.log_level_from_config(cfg))
- cfg = {'verbose_level': 1, 'log_level': 'critical'}
- self.assertEqual(logging.CRITICAL, logs.log_level_from_config(cfg))
- cfg = {'verbose_level': 1, 'log_level': 'error'}
- self.assertEqual(logging.ERROR, logs.log_level_from_config(cfg))
- cfg = {'verbose_level': 1, 'log_level': 'warning'}
- self.assertEqual(logging.WARNING, logs.log_level_from_config(cfg))
- cfg = {'verbose_level': 1, 'log_level': 'info'}
- self.assertEqual(logging.INFO, logs.log_level_from_config(cfg))
- cfg = {'verbose_level': 1, 'log_level': 'debug'}
- self.assertEqual(logging.DEBUG, logs.log_level_from_config(cfg))
- cfg = {'verbose_level': 1, 'log_level': 'bogus'}
- self.assertEqual(logging.WARNING, logs.log_level_from_config(cfg))
- cfg = {'verbose_level': 1, 'log_level': 'info', 'debug': True}
- self.assertEqual(logging.DEBUG, logs.log_level_from_config(cfg))
-
- @mock.patch('warnings.simplefilter')
- def test_set_warning_filter(self, simplefilter):
- logs.set_warning_filter(logging.ERROR)
- simplefilter.assert_called_with("ignore")
- logs.set_warning_filter(logging.WARNING)
- simplefilter.assert_called_with("ignore")
- logs.set_warning_filter(logging.INFO)
- simplefilter.assert_called_with("once")
-
-
-class TestFileFormatter(utils.TestCase):
- def test_nothing(self):
- formatter = logs._FileFormatter()
- self.assertEqual(
- (
- '%(asctime)s.%(msecs)03d %(process)d %(levelname)s '
- '%(name)s %(message)s'
- ),
- formatter.fmt,
- )
-
- def test_options(self):
- class Opts:
- cloud = 'cloudy'
- os_project_name = 'projecty'
- username = 'usernamey'
-
- options = Opts()
- formatter = logs._FileFormatter(options=options)
- self.assertEqual(
- (
- '%(asctime)s.%(msecs)03d %(process)d %(levelname)s '
- '%(name)s [cloudy usernamey projecty] %(message)s'
- ),
- formatter.fmt,
- )
-
- def test_config(self):
- config = mock.Mock()
- config.config = {'cloud': 'cloudy'}
- config.auth = {'project_name': 'projecty', 'username': 'usernamey'}
- formatter = logs._FileFormatter(config=config)
- self.assertEqual(
- (
- '%(asctime)s.%(msecs)03d %(process)d %(levelname)s '
- '%(name)s [cloudy usernamey projecty] %(message)s'
- ),
- formatter.fmt,
- )
-
-
-class TestLogConfigurator(utils.TestCase):
- def setUp(self):
- super().setUp()
- self.options = mock.Mock()
- self.options.verbose_level = 1
- self.options.log_file = None
- self.options.debug = False
- self.root_logger = mock.Mock()
- self.root_logger.setLevel = mock.Mock()
- self.root_logger.addHandler = mock.Mock()
- self.requests_log = mock.Mock()
- self.requests_log.setLevel = mock.Mock()
- self.cliff_log = mock.Mock()
- self.cliff_log.setLevel = mock.Mock()
- self.stevedore_log = mock.Mock()
- self.stevedore_log.setLevel = mock.Mock()
- self.iso8601_log = mock.Mock()
- self.iso8601_log.setLevel = mock.Mock()
- self.loggers = [
- self.root_logger,
- self.requests_log,
- self.cliff_log,
- self.stevedore_log,
- self.iso8601_log,
- ]
-
- @mock.patch('logging.StreamHandler')
- @mock.patch('logging.getLogger')
- @mock.patch('osc_lib.logs.set_warning_filter')
- def test_init(self, warning_filter, getLogger, handle):
- getLogger.side_effect = self.loggers
- console_logger = mock.Mock()
- console_logger.setFormatter = mock.Mock()
- console_logger.setLevel = mock.Mock()
- handle.return_value = console_logger
-
- configurator = logs.LogConfigurator(self.options)
-
- getLogger.assert_called_with('iso8601') # last call
- warning_filter.assert_called_with(logging.WARNING)
- self.root_logger.setLevel.assert_called_with(logging.DEBUG)
- self.root_logger.addHandler.assert_called_with(console_logger)
- self.requests_log.setLevel.assert_called_with(logging.ERROR)
- self.cliff_log.setLevel.assert_called_with(logging.ERROR)
- self.stevedore_log.setLevel.assert_called_with(logging.ERROR)
- self.iso8601_log.setLevel.assert_called_with(logging.ERROR)
- self.assertFalse(configurator.dump_trace)
-
- @mock.patch('logging.getLogger')
- @mock.patch('osc_lib.logs.set_warning_filter')
- def test_init_no_debug(self, warning_filter, getLogger):
- getLogger.side_effect = self.loggers
- self.options.debug = True
-
- configurator = logs.LogConfigurator(self.options)
-
- warning_filter.assert_called_with(logging.DEBUG)
- self.requests_log.setLevel.assert_called_with(logging.DEBUG)
- self.assertTrue(configurator.dump_trace)
-
- @mock.patch('logging.FileHandler')
- @mock.patch('logging.getLogger')
- @mock.patch('osc_lib.logs.set_warning_filter')
- @mock.patch('osc_lib.logs._FileFormatter')
- def test_init_log_file(self, formatter, warning_filter, getLogger, handle):
- getLogger.side_effect = self.loggers
- self.options.log_file = '/tmp/log_file'
- file_logger = mock.Mock()
- file_logger.setFormatter = mock.Mock()
- file_logger.setLevel = mock.Mock()
- handle.return_value = file_logger
- mock_formatter = mock.Mock()
- formatter.return_value = mock_formatter
-
- logs.LogConfigurator(self.options)
-
- handle.assert_called_with(filename=self.options.log_file)
- self.root_logger.addHandler.assert_called_with(file_logger)
- file_logger.setFormatter.assert_called_with(mock_formatter)
- file_logger.setLevel.assert_called_with(logging.WARNING)
-
- @mock.patch('logging.FileHandler')
- @mock.patch('logging.getLogger')
- @mock.patch('osc_lib.logs.set_warning_filter')
- @mock.patch('osc_lib.logs._FileFormatter')
- def test_configure(self, formatter, warning_filter, getLogger, handle):
- getLogger.side_effect = self.loggers
- configurator = logs.LogConfigurator(self.options)
- cloud_config = mock.Mock()
- config_log = '/tmp/config_log'
- cloud_config.config = {
- 'log_file': config_log,
- 'verbose_level': 1,
- 'log_level': 'info',
- }
- file_logger = mock.Mock()
- file_logger.setFormatter = mock.Mock()
- file_logger.setLevel = mock.Mock()
- handle.return_value = file_logger
- mock_formatter = mock.Mock()
- formatter.return_value = mock_formatter
-
- configurator.configure(cloud_config)
-
- warning_filter.assert_called_with(logging.INFO)
- handle.assert_called_with(filename=config_log)
- self.root_logger.addHandler.assert_called_with(file_logger)
- file_logger.setFormatter.assert_called_with(mock_formatter)
- file_logger.setLevel.assert_called_with(logging.INFO)
- self.assertFalse(configurator.dump_trace)
diff --git a/openstackclient/tests/unit/common/test_module.py b/openstackclient/tests/unit/common/test_module.py
index 476538a..8396203 100644
--- a/openstackclient/tests/unit/common/test_module.py
+++ b/openstackclient/tests/unit/common/test_module.py
@@ -11,7 +11,6 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
-#
"""Test module module"""
@@ -19,10 +18,18 @@ import sys
from unittest import mock
from openstackclient.common import module as osc_module
-from openstackclient.tests.unit import fakes
from openstackclient.tests.unit import utils
+class FakeModule:
+ def __init__(self, name, version):
+ self.name = name
+ self.__version__ = version
+ # Workaround for openstacksdk case
+ self.version = mock.Mock()
+ self.version.__version__ = version
+
+
# NOTE(dtroyer): module_1 must match the version list filter (not --all)
# currently == '*client*'
module_name_1 = 'fakeclient'
@@ -45,11 +52,11 @@ module_version_5 = '0.0.1'
MODULES = {
'sys': sys,
- module_name_1: fakes.FakeModule(module_name_1, module_version_1),
- module_name_2: fakes.FakeModule(module_name_2, module_version_2),
- module_name_3: fakes.FakeModule(module_name_3, module_version_3),
- module_name_4: fakes.FakeModule(module_name_4, module_version_4),
- module_name_5: fakes.FakeModule(module_name_5, module_version_5),
+ module_name_1: FakeModule(module_name_1, module_version_1),
+ module_name_2: FakeModule(module_name_2, module_version_2),
+ module_name_3: FakeModule(module_name_3, module_version_3),
+ module_name_4: FakeModule(module_name_4, module_version_4),
+ module_name_5: FakeModule(module_name_5, module_version_5),
}
diff --git a/openstackclient/tests/unit/common/test_quota.py b/openstackclient/tests/unit/common/test_quota.py
index 53df4da..7bfb2e7 100644
--- a/openstackclient/tests/unit/common/test_quota.py
+++ b/openstackclient/tests/unit/common/test_quota.py
@@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+import copy
from unittest import mock
from openstack.block_storage.v3 import quota_set as _volume_quota_set
@@ -1041,6 +1042,26 @@ class TestQuotaShow(TestQuota):
)
self.assertNotCalled(self.network_client.get_quota_default)
+ def test_quota_show__missing_services(self):
+ self.app.client_manager.compute_endpoint_enabled = False
+ self.app.client_manager.volume_endpoint_enabled = False
+ self.app.client_manager.network_endpoint_enabled = False
+
+ arglist = [
+ self.projects[0].name,
+ ]
+ verifylist = [
+ ('service', 'all'),
+ ('project', self.projects[0].name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.cmd.take_action(parsed_args)
+
+ self.compute_client.get_quota_set.assert_not_called()
+ self.volume_sdk_client.get_quota_set.assert_not_called()
+ self.network_client.get_quota.assert_not_called()
+
def test_quota_show__with_compute(self):
arglist = [
'--compute',
@@ -1102,6 +1123,64 @@ class TestQuotaShow(TestQuota):
)
self.assertNotCalled(self.network_client.get_quota_default)
+ def test_quota_show__with_network_and_usage(self):
+ # ensure we do not interfere with other tests
+ self._network_quota_details = copy.deepcopy(
+ self._network_quota_details
+ )
+ # set a couple of resources
+ self._network_quota_details["floating_ips"].update(
+ limit=30, reserved=20, used=7
+ )
+ self._network_quota_details["security_group_rules"].update(
+ limit=9, reserved=7, used=5
+ )
+
+ arglist = [
+ '--network',
+ '--usage',
+ self.projects[0].name,
+ ]
+ verifylist = [
+ ('service', 'network'),
+ ('project', self.projects[0].name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ headers, result_gen = self.cmd.take_action(parsed_args)
+
+ self.assertEqual(('Resource', 'Limit', 'In Use', 'Reserved'), headers)
+
+ result = sorted(result_gen)
+
+ self.assertEqual(
+ [
+ ('floating-ips', 30, 7, 20),
+ ('health_monitors', 0, 0, 0),
+ ('l7_policies', 0, 0, 0),
+ ('listeners', 0, 0, 0),
+ ('load_balancers', 0, 0, 0),
+ ('networks', 0, 0, 0),
+ ('pools', 0, 0, 0),
+ ('ports', 0, 0, 0),
+ ('rbac_policies', 0, 0, 0),
+ ('routers', 0, 0, 0),
+ ('secgroup-rules', 9, 5, 7),
+ ('secgroups', 0, 0, 0),
+ ('subnet_pools', 0, 0, 0),
+ ('subnets', 0, 0, 0),
+ ],
+ result,
+ )
+
+ self.compute_client.get_quota_set.assert_not_called()
+ self.volume_sdk_client.get_quota_set.assert_not_called()
+ self.network_client.get_quota.assert_called_once_with(
+ self.projects[0].id,
+ details=True,
+ )
+ self.assertNotCalled(self.network_client.get_quota_default)
+
def test_quota_show__with_default(self):
arglist = [
'--default',
diff --git a/openstackclient/tests/unit/compute/v2/test_aggregate.py b/openstackclient/tests/unit/compute/v2/test_aggregate.py
index 813cbb9..b68e76e 100644
--- a/openstackclient/tests/unit/compute/v2/test_aggregate.py
+++ b/openstackclient/tests/unit/compute/v2/test_aggregate.py
@@ -165,9 +165,11 @@ class TestAggregateDelete(TestAggregate):
sdk_fakes.generate_fake_resources(_aggregate.Aggregate, 2)
)
- self.compute_client.find_aggregate = mock.Mock(
- side_effect=[self.fake_ags[0], self.fake_ags[1]]
- )
+ self.compute_client.find_aggregate.side_effect = [
+ self.fake_ags[0],
+ self.fake_ags[1],
+ ]
+
self.cmd = aggregate.DeleteAggregate(self.app, None)
def test_aggregate_delete(self):
diff --git a/openstackclient/tests/unit/compute/v2/test_console.py b/openstackclient/tests/unit/compute/v2/test_console.py
index 423290c..8d9d36c 100644
--- a/openstackclient/tests/unit/compute/v2/test_console.py
+++ b/openstackclient/tests/unit/compute/v2/test_console.py
@@ -13,7 +13,6 @@
# under the License.
#
-from unittest import mock
from openstack.compute.v2 import server as _server
from openstack.test import fakes as sdk_fakes
@@ -90,9 +89,7 @@ class TestConsoleUrlShow(compute_fakes.TestComputev2):
'protocol': 'fake_protocol',
'type': 'fake_type',
}
- self.compute_client.create_console = mock.Mock(
- return_value=fake_console_data
- )
+ self.compute_client.create_console.return_value = fake_console_data
self.columns = (
'protocol',
diff --git a/openstackclient/tests/unit/compute/v2/test_flavor.py b/openstackclient/tests/unit/compute/v2/test_flavor.py
index 0b3a4ae..25bc8ea 100644
--- a/openstackclient/tests/unit/compute/v2/test_flavor.py
+++ b/openstackclient/tests/unit/compute/v2/test_flavor.py
@@ -680,9 +680,7 @@ class TestFlavorList(TestFlavor):
)
self.compute_client.flavors.side_effect = [[flavor], []]
- self.compute_client.fetch_flavor_extra_specs = mock.Mock(
- return_value=None
- )
+ self.compute_client.fetch_flavor_extra_specs.return_value = None
arglist = [
'--long',
diff --git a/openstackclient/tests/unit/compute/v2/test_hypervisor_stats.py b/openstackclient/tests/unit/compute/v2/test_hypervisor_stats.py
index 045efda..89d4d45 100644
--- a/openstackclient/tests/unit/compute/v2/test_hypervisor_stats.py
+++ b/openstackclient/tests/unit/compute/v2/test_hypervisor_stats.py
@@ -12,20 +12,12 @@
# License for the specific language governing permissions and limitations
# under the License.
#
-from unittest import mock
from openstackclient.compute.v2 import hypervisor_stats
from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes
from openstackclient.tests.unit import fakes
-class TestHypervisorStats(compute_fakes.TestComputev2):
- def setUp(self):
- super().setUp()
-
- self.compute_client.get = mock.Mock()
-
-
# Not in fakes.py because hypervisor stats has been deprecated
@@ -61,7 +53,7 @@ def create_one_hypervisor_stats(attrs=None):
return stats_info
-class TestHypervisorStatsShow(TestHypervisorStats):
+class TestHypervisorStatsShow(compute_fakes.TestComputev2):
_stats = create_one_hypervisor_stats()
def setUp(self):
diff --git a/openstackclient/tests/unit/compute/v2/test_server.py b/openstackclient/tests/unit/compute/v2/test_server.py
index 8695136..8da3516 100644
--- a/openstackclient/tests/unit/compute/v2/test_server.py
+++ b/openstackclient/tests/unit/compute/v2/test_server.py
@@ -13,7 +13,6 @@
# under the License.
import base64
-import collections
import getpass
import json
import tempfile
@@ -21,9 +20,11 @@ from unittest import mock
import uuid
import iso8601
+from openstack.compute.v2 import flavor as _flavor
from openstack.compute.v2 import server as _server
from openstack.compute.v2 import server_group as _server_group
from openstack import exceptions as sdk_exceptions
+from openstack.image.v2 import image as _image
from openstack.test import fakes as sdk_fakes
from osc_lib.cli import format_columns
from osc_lib import exceptions
@@ -1212,7 +1213,6 @@ class TestServerCreate(TestServer):
'locked',
'locked_reason',
'name',
- 'pinned_availability_zone',
'progress',
'project_id',
'properties',
@@ -1261,7 +1261,6 @@ class TestServerCreate(TestServer):
None, # locked
None, # locked_reason
self.server.name,
- None, # pinned_availability_zone
None, # progress
None, # project_id
format_columns.DictColumn({}), # properties
@@ -4450,6 +4449,55 @@ class TestServerDelete(compute_fakes.TestComputev2):
)
self.assertIsNone(result)
+ def test_server_delete_multi_servers_with_exceptions(self):
+ servers = compute_fakes.create_servers(count=2)
+ self.compute_client.find_server.side_effect = [
+ servers[0],
+ sdk_exceptions.ResourceNotFound(),
+ servers[1],
+ ]
+
+ arglist = [servers[0].id, 'unexist_server', servers[1].id]
+
+ verifylist = [
+ ('force', False),
+ ('all_projects', False),
+ ('wait', False),
+ (
+ 'server',
+ [servers[0].id, 'unexist_server', servers[1].id],
+ ),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ exc = self.assertRaises(
+ exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args,
+ )
+ self.assertEqual('1 of 3 servers failed to delete.', str(exc))
+
+ self.compute_client.find_server.assert_has_calls(
+ [
+ mock.call(
+ servers[0].id, ignore_missing=False, all_projects=False
+ ),
+ mock.call(
+ 'unexist_server', ignore_missing=False, all_projects=False
+ ),
+ mock.call(
+ servers[1].id, ignore_missing=False, all_projects=False
+ ),
+ ]
+ )
+
+ self.compute_client.delete_server.assert_has_calls(
+ [
+ mock.call(servers[0], force=False),
+ mock.call(servers[1], force=False),
+ ]
+ )
+
def test_server_delete_with_all_projects(self):
arglist = [
self.server.id,
@@ -4583,10 +4631,8 @@ class _TestServerList(TestServer):
'Flavor Name',
'Flavor ID',
'Availability Zone',
- 'Pinned Availability Zone',
'Host',
'Properties',
- 'Scheduler Hints',
)
columns_all_projects = (
'ID',
@@ -4653,17 +4699,19 @@ class TestServerList(_TestServerList):
def setUp(self):
super().setUp()
- Image = collections.namedtuple('Image', 'id name')
self.image_client.images.return_value = [
- Image(id=s.image['id'], name=self.image.name)
+ sdk_fakes.generate_fake_resource(
+ _image.Image, id=s.image['id'], name=self.image.name
+ )
# Image will be an empty string if boot-from-volume
for s in self.servers
if s.image
]
- Flavor = collections.namedtuple('Flavor', 'id name')
self.compute_client.flavors.return_value = [
- Flavor(id=s.flavor['id'], name=self.flavor.name)
+ sdk_fakes.generate_fake_resource(
+ _flavor.Flavor, id=s.flavor['id'], name=self.flavor.name
+ )
for s in self.servers
]
@@ -4732,10 +4780,8 @@ class TestServerList(_TestServerList):
self.flavor.name,
s.flavor['id'],
getattr(s, 'availability_zone'),
- getattr(s, 'pinned_availability_zone', ''),
server.HostColumn(getattr(s, 'hypervisor_hostname')),
format_columns.DictColumn(s.metadata),
- format_columns.DictListColumn(None),
)
for s in self.servers
)
@@ -4809,13 +4855,9 @@ class TestServerList(_TestServerList):
'-c',
'Availability Zone',
'-c',
- 'Pinned Availability Zone',
- '-c',
'Host',
'-c',
'Properties',
- '-c',
- 'Scheduler Hints',
'--long',
]
verifylist = [
@@ -4835,10 +4877,8 @@ class TestServerList(_TestServerList):
self.assertIn('Image ID', columns)
self.assertIn('Flavor ID', columns)
self.assertIn('Availability Zone', columns)
- self.assertIn('Pinned Availability Zone', columns)
self.assertIn('Host', columns)
self.assertIn('Properties', columns)
- self.assertIn('Scheduler Hints', columns)
self.assertCountEqual(columns, set(columns))
def test_server_list_no_name_lookup_option(self):
@@ -5249,10 +5289,8 @@ class TestServerList(_TestServerList):
self.flavor.name,
s.flavor['id'],
getattr(s, 'availability_zone'),
- getattr(s, 'pinned_availability_zone', ''),
server.HostColumn(getattr(s, 'hypervisor_hostname')),
format_columns.DictColumn(s.metadata),
- format_columns.DictListColumn(s.scheduler_hints),
)
for s in self.servers
)
@@ -5281,9 +5319,10 @@ class TestServerList(_TestServerList):
self.compute_client.servers.return_value = servers
# Make sure the returned image and flavor IDs match the servers.
- Image = collections.namedtuple('Image', 'id name')
self.image_client.images.return_value = [
- Image(id=s.image['id'], name=self.image.name)
+ sdk_fakes.generate_fake_resource(
+ _image.Image, id=s.image['id'], name=self.image.name
+ )
# Image will be an empty string if boot-from-volume
for s in servers
if s.image
@@ -5305,10 +5344,8 @@ class TestServerList(_TestServerList):
self.flavor.name,
s.flavor['id'],
getattr(s, 'availability_zone'),
- getattr(s, 'pinned_availability_zone', ''),
server.HostColumn(getattr(s, 'hypervisor_hostname')),
format_columns.DictColumn(s.metadata),
- format_columns.DictListColumn(s.scheduler_hints),
s.host_status,
)
for s in servers
@@ -5343,7 +5380,6 @@ class TestServerListV273(_TestServerList):
'Image ID',
'Flavor',
'Availability Zone',
- 'Pinned Availability Zone',
'Host',
'Properties',
'Scheduler Hints',
@@ -5368,9 +5404,10 @@ class TestServerListV273(_TestServerList):
self.servers = self.setup_sdk_servers_mock(3)
self.compute_client.servers.return_value = self.servers
- Image = collections.namedtuple('Image', 'id name')
self.image_client.images.return_value = [
- Image(id=s.image['id'], name=self.image.name)
+ sdk_fakes.generate_fake_resource(
+ _image.Image, id=s.image['id'], name=self.image.name
+ )
# Image will be an empty string if boot-from-volume
for s in self.servers
if s.image
@@ -5541,6 +5578,307 @@ class TestServerListV273(_TestServerList):
self.assertEqual(expected_row, partial_server)
+class TestServerListV296(_TestServerList):
+ columns = (
+ 'ID',
+ 'Name',
+ 'Status',
+ 'Networks',
+ 'Image',
+ 'Flavor',
+ )
+ columns_long = (
+ 'ID',
+ 'Name',
+ 'Status',
+ 'Task State',
+ 'Power State',
+ 'Networks',
+ 'Image Name',
+ 'Image ID',
+ 'Flavor',
+ 'Availability Zone',
+ 'Host',
+ 'Properties',
+ 'Pinned Availability Zone',
+ )
+
+ def setUp(self):
+ super().setUp()
+ self.set_compute_api_version('2.96')
+
+ self.image_client.images.return_value = [
+ sdk_fakes.generate_fake_resource(
+ _image.Image, id=s.image['id'], name=self.image.name
+ )
+ # Image will be an empty string if boot-from-volume
+ for s in self.servers
+ if s.image
+ ]
+
+ self.compute_client.flavors.return_value = [
+ sdk_fakes.generate_fake_resource(
+ _flavor.Flavor, id=s.flavor['id'], name=self.flavor.name
+ )
+ for s in self.servers
+ ]
+
+ self.data = tuple(
+ (
+ s.id,
+ s.name,
+ s.status,
+ server.AddressesColumn(s.addresses),
+ # Image will be an empty string if boot-from-volume
+ self.image.name if s.image else server.IMAGE_STRING_FOR_BFV,
+ self.flavor.name,
+ )
+ for s in self.servers
+ )
+
+ def test_server_list_long_option(self):
+ self.data = tuple(
+ (
+ s.id,
+ s.name,
+ s.status,
+ getattr(s, 'task_state'),
+ server.PowerStateColumn(getattr(s, 'power_state')),
+ server.AddressesColumn(s.addresses),
+ # Image will be an empty string if boot-from-volume
+ self.image.name if s.image else server.IMAGE_STRING_FOR_BFV,
+ s.image['id'] if s.image else server.IMAGE_STRING_FOR_BFV,
+ self.flavor.name,
+ getattr(s, 'availability_zone'),
+ server.HostColumn(getattr(s, 'hypervisor_hostname')),
+ format_columns.DictColumn(s.metadata),
+ getattr(s, 'pinned_availability_zone', ''),
+ )
+ for s in self.servers
+ )
+ arglist = [
+ '--long',
+ ]
+ verifylist = [
+ ('all_projects', False),
+ ('long', True),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+ self.compute_client.servers.assert_called_with(**self.kwargs)
+ image_ids = {s.image['id'] for s in self.servers if s.image}
+ self.image_client.images.assert_called_once_with(
+ id=f'in:{",".join(image_ids)}',
+ )
+ self.compute_client.flavors.assert_called_once_with(is_public=None)
+ self.assertEqual(self.columns_long, columns)
+ self.assertEqual(self.data, tuple(data))
+
+ def test_server_list_column_option(self):
+ arglist = [
+ '-c',
+ 'Project ID',
+ '-c',
+ 'User ID',
+ '-c',
+ 'Created At',
+ '-c',
+ 'Security Groups',
+ '-c',
+ 'Task State',
+ '-c',
+ 'Power State',
+ '-c',
+ 'Image ID',
+ '-c',
+ 'Flavor ID',
+ '-c',
+ 'Availability Zone',
+ '-c',
+ 'Host',
+ '-c',
+ 'Properties',
+ '-c',
+ 'Pinned Availability Zone',
+ '--long',
+ ]
+ verifylist = [
+ ('long', True),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.compute_client.servers.assert_called_with(**self.kwargs)
+ self.assertIn('Project ID', columns)
+ self.assertIn('User ID', columns)
+ self.assertIn('Created At', columns)
+ self.assertIn('Security Groups', columns)
+ self.assertIn('Task State', columns)
+ self.assertIn('Power State', columns)
+ self.assertIn('Image ID', columns)
+ self.assertIn('Flavor ID', columns)
+ self.assertIn('Availability Zone', columns)
+ self.assertIn('Pinned Availability Zone', columns)
+ self.assertIn('Host', columns)
+ self.assertIn('Properties', columns)
+ self.assertCountEqual(columns, set(columns))
+
+
+class TestServerListV2100(_TestServerList):
+ columns = (
+ 'ID',
+ 'Name',
+ 'Status',
+ 'Networks',
+ 'Image',
+ 'Flavor',
+ )
+ columns_long = (
+ 'ID',
+ 'Name',
+ 'Status',
+ 'Task State',
+ 'Power State',
+ 'Networks',
+ 'Image Name',
+ 'Image ID',
+ 'Flavor',
+ 'Availability Zone',
+ 'Host',
+ 'Properties',
+ 'Pinned Availability Zone',
+ 'Scheduler Hints',
+ )
+
+ def setUp(self):
+ super().setUp()
+ self.set_compute_api_version('2.100')
+
+ self.image_client.images.return_value = [
+ sdk_fakes.generate_fake_resource(
+ _image.Image, id=s.image['id'], name=self.image.name
+ )
+ # Image will be an empty string if boot-from-volume
+ for s in self.servers
+ if s.image
+ ]
+
+ self.compute_client.flavors.return_value = [
+ sdk_fakes.generate_fake_resource(
+ _flavor.Flavor, id=s.flavor['id'], name=self.flavor.name
+ )
+ for s in self.servers
+ ]
+
+ self.data = tuple(
+ (
+ s.id,
+ s.name,
+ s.status,
+ server.AddressesColumn(s.addresses),
+ # Image will be an empty string if boot-from-volume
+ self.image.name if s.image else server.IMAGE_STRING_FOR_BFV,
+ self.flavor.name,
+ )
+ for s in self.servers
+ )
+
+ def test_server_list_long_option(self):
+ self.data = tuple(
+ (
+ s.id,
+ s.name,
+ s.status,
+ getattr(s, 'task_state'),
+ server.PowerStateColumn(getattr(s, 'power_state')),
+ server.AddressesColumn(s.addresses),
+ # Image will be an empty string if boot-from-volume
+ self.image.name if s.image else server.IMAGE_STRING_FOR_BFV,
+ s.image['id'] if s.image else server.IMAGE_STRING_FOR_BFV,
+ self.flavor.name,
+ getattr(s, 'availability_zone'),
+ server.HostColumn(getattr(s, 'hypervisor_hostname')),
+ format_columns.DictColumn(s.metadata),
+ getattr(s, 'pinned_availability_zone', ''),
+ format_columns.DictListColumn(None),
+ )
+ for s in self.servers
+ )
+ arglist = [
+ '--long',
+ ]
+ verifylist = [
+ ('all_projects', False),
+ ('long', True),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+ self.compute_client.servers.assert_called_with(**self.kwargs)
+ image_ids = {s.image['id'] for s in self.servers if s.image}
+ self.image_client.images.assert_called_once_with(
+ id=f'in:{",".join(image_ids)}',
+ )
+ self.compute_client.flavors.assert_called_once_with(is_public=None)
+ self.assertEqual(self.columns_long, columns)
+ self.assertEqual(self.data, tuple(data))
+
+ def test_server_list_column_option(self):
+ arglist = [
+ '-c',
+ 'Project ID',
+ '-c',
+ 'User ID',
+ '-c',
+ 'Created At',
+ '-c',
+ 'Security Groups',
+ '-c',
+ 'Task State',
+ '-c',
+ 'Power State',
+ '-c',
+ 'Image ID',
+ '-c',
+ 'Flavor ID',
+ '-c',
+ 'Availability Zone',
+ '-c',
+ 'Host',
+ '-c',
+ 'Properties',
+ '-c',
+ 'Pinned Availability Zone',
+ '-c',
+ 'Scheduler Hints',
+ '--long',
+ ]
+ verifylist = [
+ ('long', True),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.compute_client.servers.assert_called_with(**self.kwargs)
+ self.assertIn('Project ID', columns)
+ self.assertIn('User ID', columns)
+ self.assertIn('Created At', columns)
+ self.assertIn('Security Groups', columns)
+ self.assertIn('Task State', columns)
+ self.assertIn('Power State', columns)
+ self.assertIn('Image ID', columns)
+ self.assertIn('Flavor ID', columns)
+ self.assertIn('Availability Zone', columns)
+ self.assertIn('Pinned Availability Zone', columns)
+ self.assertIn('Host', columns)
+ self.assertIn('Properties', columns)
+ self.assertIn('Scheduler Hints', columns)
+ self.assertCountEqual(columns, set(columns))
+
+
class TestServerAction(compute_fakes.TestComputev2):
def run_method_with_sdk_servers(self, method_name, server_count):
servers = compute_fakes.create_servers(count=server_count)
@@ -7558,15 +7896,13 @@ class TestServerResize(compute_fakes.TestComputev2):
('server', self.server.id),
]
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- result = self.cmd.take_action(parsed_args)
-
- self.compute_client.find_server.assert_called_once_with(
- self.server.id, ignore_missing=False
+ self.assertRaises(
+ test_utils.ParserException,
+ self.check_parser,
+ self.cmd,
+ arglist,
+ verifylist,
)
- self.compute_client.find_flavor.assert_not_called()
- self.compute_client.resize_server.assert_not_called()
- self.assertIsNone(result)
def test_server_resize(self):
arglist = [
@@ -8533,7 +8869,6 @@ class TestServerShow(TestServer):
'locked',
'locked_reason',
'name',
- 'pinned_availability_zone',
'progress',
'project_id',
'properties',
@@ -8583,7 +8918,6 @@ class TestServerShow(TestServer):
None, # locked
None, # locked_reason
self.server.name,
- None, # pinned_availability_zone
None, # progress
'tenant-id-xxx', # project_id
format_columns.DictColumn({}), # properties
@@ -9522,7 +9856,6 @@ class TestServerGeneral(TestServer):
'locked': None,
'locked_reason': None,
'name': _server.name,
- 'pinned_availability_zone': None,
'progress': None,
'project_id': 'tenant-id-xxx',
'properties': format_columns.DictColumn({}),
@@ -9609,7 +9942,6 @@ class TestServerGeneral(TestServer):
'locked': None,
'locked_reason': None,
'name': _server.name,
- 'pinned_availability_zone': None,
'progress': None,
'project_id': 'tenant-id-xxx',
'properties': format_columns.DictColumn({}),
diff --git a/openstackclient/tests/unit/compute/v2/test_server_backup.py b/openstackclient/tests/unit/compute/v2/test_server_backup.py
index 0d039d2..cc8acfb 100644
--- a/openstackclient/tests/unit/compute/v2/test_server_backup.py
+++ b/openstackclient/tests/unit/compute/v2/test_server_backup.py
@@ -161,9 +161,7 @@ class TestServerBackupCreate(compute_fakes.TestComputev2):
@mock.patch.object(common_utils, 'wait_for_status', return_value=True)
def test_server_backup_wait_ok(self, mock_wait_for_status):
- self.image_client.get_image = mock.Mock(
- side_effect=self.image,
- )
+ self.image_client.get_image.side_effect = (self.image,)
arglist = [
'--name',
diff --git a/openstackclient/tests/unit/compute/v2/test_service.py b/openstackclient/tests/unit/compute/v2/test_service.py
index c64a2b9..a47ea72 100644
--- a/openstackclient/tests/unit/compute/v2/test_service.py
+++ b/openstackclient/tests/unit/compute/v2/test_service.py
@@ -77,9 +77,7 @@ class TestServiceDelete(compute_fakes.TestComputev2):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
delete_mock_result = [None, exceptions.CommandError]
- self.compute_client.delete_service = mock.Mock(
- side_effect=delete_mock_result
- )
+ self.compute_client.delete_service.side_effect = delete_mock_result
try:
self.cmd.take_action(parsed_args)
diff --git a/openstackclient/tests/unit/fakes.py b/openstackclient/tests/unit/fakes.py
index 0d378ff..be9d7f2 100644
--- a/openstackclient/tests/unit/fakes.py
+++ b/openstackclient/tests/unit/fakes.py
@@ -12,13 +12,43 @@
# License for the specific language governing permissions and limitations
# under the License.
+# TODO(stephenfin): Remove the contents of this module in favour of the osc_lib
+# version once our min version is bumped to 4.3.0
+
import json
-import sys
from unittest import mock
from keystoneauth1 import fixture
+from osc_lib.tests.fakes import (
+ FakeApp,
+ FakeClientManager as BaseFakeClientManager,
+ FakeLog,
+ FakeOptions,
+ FakeResource as BaseFakeResource,
+ FakeStdout,
+)
import requests
+__all__ = [
+ 'AUTH_TOKEN',
+ 'AUTH_URL',
+ 'INTERFACE',
+ 'PASSWORD',
+ 'PROJECT_NAME',
+ 'REGION_NAME',
+ 'TEST_RESPONSE_DICT',
+ 'TEST_RESPONSE_DICT_V3',
+ 'TEST_VERSIONS',
+ 'USERNAME',
+ 'VERSION',
+ 'FakeApp',
+ 'FakeClientManager',
+ 'FakeLog',
+ 'FakeOptions',
+ 'FakeResource',
+ 'FakeResponse',
+ 'FakeStdout',
+]
AUTH_TOKEN = "foobar"
AUTH_URL = "http://0.0.0.0"
@@ -47,79 +77,15 @@ TEST_RESPONSE_DICT_V3.set_project_scope()
TEST_VERSIONS = fixture.DiscoveryList(href=AUTH_URL)
-class FakeStdout:
- def __init__(self):
- self.content = []
-
- def write(self, text):
- self.content.append(text)
-
- def make_string(self):
- result = ''
- for line in self.content:
- result = result + line
- return result
-
-
-class FakeLog:
- def __init__(self):
- self.messages = {}
-
- def debug(self, msg):
- self.messages['debug'] = msg
-
- def info(self, msg):
- self.messages['info'] = msg
-
- def warning(self, msg):
- self.messages['warning'] = msg
-
- def error(self, msg):
- self.messages['error'] = msg
-
- def critical(self, msg):
- self.messages['critical'] = msg
-
-
-class FakeApp:
- def __init__(self, _stdout, _log):
- self.stdout = _stdout
- self.client_manager = None
- self.api_version = {}
- self.stdin = sys.stdin
- self.stdout = _stdout or sys.stdout
- self.stderr = sys.stderr
- self.log = _log
-
-
-class FakeOptions:
- def __init__(self, **kwargs):
- self.os_beta_command = False
-
-
-class FakeClient:
- def __init__(self, **kwargs):
- self.endpoint = kwargs['endpoint']
- self.token = kwargs['token']
-
-
-class FakeClientManager:
+class FakeClientManager(BaseFakeClientManager):
_api_version = {
'image': '2',
}
def __init__(self):
- self.compute = None
- self.identity = None
- self.image = None
- self.object_store = None
- self.volume = None
- self.network = None
- self.sdk_connection = mock.Mock()
+ super().__init__()
- self.session = None
- self.auth_ref = None
- self.auth_plugin_name = None
+ self.sdk_connection = mock.Mock()
self.network_endpoint_enabled = True
self.compute_endpoint_enabled = True
@@ -158,64 +124,7 @@ class FakeClientManager:
return self.volume_endpoint_enabled
-class FakeModule:
- def __init__(self, name, version):
- self.name = name
- self.__version__ = version
- # Workaround for openstacksdk case
- self.version = mock.Mock()
- self.version.__version__ = version
-
-
-class FakeResource:
- def __init__(self, manager=None, info=None, loaded=False, methods=None):
- """Set attributes and methods for a resource.
-
- :param manager:
- The resource manager
- :param Dictionary info:
- A dictionary with all attributes
- :param bool loaded:
- True if the resource is loaded in memory
- :param Dictionary methods:
- A dictionary with all methods
- """
- info = info or {}
- methods = methods or {}
-
- self.__name__ = type(self).__name__
- self.manager = manager
- self._info = info
- self._add_details(info)
- self._add_methods(methods)
- self._loaded = loaded
-
- def _add_details(self, info):
- for k, v in info.items():
- setattr(self, k, v)
-
- def _add_methods(self, methods):
- """Fake methods with MagicMock objects.
-
- For each <@key, @value> pairs in methods, add an callable MagicMock
- object named @key as an attribute, and set the mock's return_value to
- @value. When users access the attribute with (), @value will be
- returned, which looks like a function call.
- """
- for name, ret in methods.items():
- method = mock.Mock(return_value=ret)
- setattr(self, name, method)
-
- def __repr__(self):
- reprkeys = sorted(
- k for k in self.__dict__.keys() if k[0] != '_' and k != 'manager'
- )
- info = ", ".join(f"{k}={getattr(self, k)}" for k in reprkeys)
- return f"<{self.__class__.__name__} {info}>"
-
- def keys(self):
- return self._info.keys()
-
+class FakeResource(BaseFakeResource):
def to_dict(self):
return self._info
@@ -247,11 +156,3 @@ class FakeResponse(requests.Response):
self._content = json.dumps(data)
if not isinstance(self._content, bytes):
self._content = self._content.encode()
-
-
-class FakeModel(dict):
- def __getattr__(self, key):
- try:
- return self[key]
- except KeyError:
- raise AttributeError(key)
diff --git a/openstackclient/tests/unit/identity/test_common.py b/openstackclient/tests/unit/identity/test_common.py
new file mode 100644
index 0000000..ae85262
--- /dev/null
+++ b/openstackclient/tests/unit/identity/test_common.py
@@ -0,0 +1,100 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from unittest import mock
+
+from openstack import exceptions as sdk_exc
+from openstack.identity.v3 import user as _user
+from openstack.test import fakes as sdk_fakes
+from osc_lib import exceptions
+
+from openstackclient.identity import common
+from openstackclient.tests.unit import utils as test_utils
+
+
+class TestFindSDKId(test_utils.TestCase):
+ def setUp(self):
+ super().setUp()
+ self.user = sdk_fakes.generate_fake_resource(_user.User)
+ self.identity_sdk_client = mock.Mock()
+ self.identity_sdk_client.find_user = mock.Mock()
+
+ def test_find_sdk_id_validate(self):
+ self.identity_sdk_client.find_user.side_effect = [self.user]
+
+ result = common._find_sdk_id(
+ self.identity_sdk_client.find_user,
+ name_or_id=self.user.id,
+ validate_actor_existence=True,
+ )
+ self.assertEqual(self.user.id, result)
+
+ def test_find_sdk_id_no_validate(self):
+ self.identity_sdk_client.find_user.side_effect = [self.user]
+
+ result = common._find_sdk_id(
+ self.identity_sdk_client.find_user,
+ name_or_id=self.user.id,
+ validate_actor_existence=False,
+ )
+ self.assertEqual(self.user.id, result)
+
+ def test_find_sdk_id_not_found_validate(self):
+ self.identity_sdk_client.find_user.side_effect = [
+ sdk_exc.ResourceNotFound,
+ ]
+
+ self.assertRaises(
+ exceptions.CommandError,
+ common._find_sdk_id,
+ self.identity_sdk_client.find_user,
+ name_or_id=self.user.id,
+ validate_actor_existence=True,
+ )
+
+ def test_find_sdk_id_not_found_no_validate(self):
+ self.identity_sdk_client.find_user.side_effect = [
+ sdk_exc.ResourceNotFound,
+ ]
+
+ result = common._find_sdk_id(
+ self.identity_sdk_client.find_user,
+ name_or_id=self.user.id,
+ validate_actor_existence=False,
+ )
+ self.assertEqual(self.user.id, result)
+
+ def test_find_sdk_id_forbidden_validate(self):
+ self.identity_sdk_client.find_user.side_effect = [
+ sdk_exc.ForbiddenException,
+ ]
+
+ result = common._find_sdk_id(
+ self.identity_sdk_client.find_user,
+ name_or_id=self.user.id,
+ validate_actor_existence=True,
+ )
+
+ self.assertEqual(self.user.id, result)
+
+ def test_find_sdk_id_forbidden_no_validate(self):
+ self.identity_sdk_client.find_user.side_effect = [
+ sdk_exc.ForbiddenException,
+ ]
+
+ result = common._find_sdk_id(
+ self.identity_sdk_client.find_user,
+ name_or_id=self.user.id,
+ validate_actor_existence=False,
+ )
+
+ self.assertEqual(self.user.id, result)
diff --git a/openstackclient/tests/unit/identity/v2_0/test_project.py b/openstackclient/tests/unit/identity/v2_0/test_project.py
index 9b203b2..bb6a643 100644
--- a/openstackclient/tests/unit/identity/v2_0/test_project.py
+++ b/openstackclient/tests/unit/identity/v2_0/test_project.py
@@ -195,7 +195,7 @@ class TestProjectCreate(TestProject):
self.fake_project.name,
]
verifylist = [
- ('property', {'fee': 'fi', 'fo': 'fum'}),
+ ('properties', {'fee': 'fi', 'fo': 'fum'}),
('name', self.fake_project.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -464,7 +464,7 @@ class TestProjectSet(TestProject):
('description', None),
('enable', False),
('disable', False),
- ('property', None),
+ ('properties', None),
]
self.projects_mock.get.side_effect = exceptions.NotFound(None)
self.projects_mock.find.side_effect = exceptions.NotFound(None)
@@ -588,7 +588,7 @@ class TestProjectSet(TestProject):
self.fake_project.name,
]
verifylist = [
- ('property', {'fee': 'fi', 'fo': 'fum'}),
+ ('properties', {'fee': 'fi', 'fo': 'fum'}),
('project', self.fake_project.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -683,7 +683,7 @@ class TestProjectUnset(TestProject):
self.fake_proj.name,
]
verifylist = [
- ('property', ['fee', 'fo']),
+ ('properties', ['fee', 'fo']),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
diff --git a/openstackclient/tests/unit/identity/v3/fakes.py b/openstackclient/tests/unit/identity/v3/fakes.py
index ad5ceb2..c42ed47 100644
--- a/openstackclient/tests/unit/identity/v3/fakes.py
+++ b/openstackclient/tests/unit/identity/v3/fakes.py
@@ -693,6 +693,14 @@ class TestIdentityv3(
): ...
+class FakeModel(dict):
+ def __getattr__(self, key):
+ try:
+ return self[key]
+ except KeyError:
+ raise AttributeError(key)
+
+
# We don't use FakeClientMixin since we want a different fake legacy client
class TestFederatedIdentity(utils.TestCommand):
def setUp(self):
@@ -1075,7 +1083,7 @@ class FakeEndpoint:
# Overwrite default attributes if there are some attributes set
endpoint_filter_info.update(attrs)
- endpoint_filter = fakes.FakeModel(copy.deepcopy(endpoint_filter_info))
+ endpoint_filter = FakeModel(copy.deepcopy(endpoint_filter_info))
return endpoint_filter
@@ -1133,7 +1141,7 @@ class FakeEndpointGroup:
# Overwrite default attributes if there are some attributes set
endpointgroup_filter_info.update(attrs)
- endpointgroup_filter = fakes.FakeModel(
+ endpointgroup_filter = FakeModel(
copy.deepcopy(endpointgroup_filter_info)
)
diff --git a/openstackclient/tests/unit/identity/v3/test_application_credential.py b/openstackclient/tests/unit/identity/v3/test_application_credential.py
index a5fda7c..3a3a80e 100644
--- a/openstackclient/tests/unit/identity/v3/test_application_credential.py
+++ b/openstackclient/tests/unit/identity/v3/test_application_credential.py
@@ -120,7 +120,7 @@ class TestApplicationCredentialCreate(identity_fakes.TestIdentityv3):
verifylist = [
('name', self.application_credential.name),
('secret', 'moresecuresecret'),
- ('role', [self.roles.id]),
+ ('roles', [self.roles.id]),
('expiration', '2024-01-01T00:00:00'),
('description', 'credential for testing'),
]
@@ -302,7 +302,7 @@ class TestApplicationCredentialDelete(identity_fakes.TestIdentityv3):
calls = []
for a in arglist:
- calls.append(call(user_id, a))
+ calls.append(call(user_id, a, ignore_missing=False))
self.identity_sdk_client.find_application_credential.assert_has_calls(
calls
@@ -457,7 +457,7 @@ class TestApplicationCredentialShow(identity_fakes.TestIdentityv3):
columns, data = self.cmd.take_action(parsed_args)
self.identity_sdk_client.find_application_credential.assert_called_with(
- user_id, self.application_credential.id
+ user_id, self.application_credential.id, ignore_missing=False
)
self.assertEqual(self.columns, columns)
diff --git a/openstackclient/tests/unit/identity/v3/test_domain.py b/openstackclient/tests/unit/identity/v3/test_domain.py
index abe8076..cc0593d 100644
--- a/openstackclient/tests/unit/identity/v3/test_domain.py
+++ b/openstackclient/tests/unit/identity/v3/test_domain.py
@@ -520,7 +520,7 @@ class TestDomainShow(identity_fakes.TestIdentityv3):
# data to be shown.
columns, data = self.cmd.take_action(parsed_args)
self.identity_sdk_client.find_domain.assert_called_with(
- self.domain.id,
+ self.domain.id, ignore_missing=False
)
self.assertEqual(self.columns, columns)
diff --git a/openstackclient/tests/unit/identity/v3/test_endpoint.py b/openstackclient/tests/unit/identity/v3/test_endpoint.py
index 84e10e5..ba69317 100644
--- a/openstackclient/tests/unit/identity/v3/test_endpoint.py
+++ b/openstackclient/tests/unit/identity/v3/test_endpoint.py
@@ -678,7 +678,7 @@ class TestEndpointShow(identity_fakes.TestIdentityv3):
# data to be shown.
columns, data = self.cmd.take_action(parsed_args)
self.identity_sdk_client.find_endpoint.assert_called_with(
- self.endpoint.id,
+ self.endpoint.id, ignore_missing=False
)
collist = (
diff --git a/openstackclient/tests/unit/identity/v3/test_group.py b/openstackclient/tests/unit/identity/v3/test_group.py
index d212e45..598402e 100644
--- a/openstackclient/tests/unit/identity/v3/test_group.py
+++ b/openstackclient/tests/unit/identity/v3/test_group.py
@@ -253,7 +253,7 @@ class TestGroupCreate(identity_fakes.TestIdentityv3):
columns, data = self.cmd.take_action(parsed_args)
self.identity_sdk_client.find_group.assert_called_once_with(
- self.group.name
+ self.group.name, ignore_missing=False
)
self.assertEqual(self.columns, columns)
datalist = (
@@ -286,7 +286,9 @@ class TestGroupCreate(identity_fakes.TestIdentityv3):
columns, data = self.cmd.take_action(parsed_args)
self.identity_sdk_client.find_group.assert_called_once_with(
- self.group_with_options.name, domain_id=self.domain.id
+ self.group_with_options.name,
+ domain_id=self.domain.id,
+ ignore_missing=False,
)
self.assertEqual(self.columns, columns)
datalist = (
diff --git a/openstackclient/tests/unit/identity/v3/test_identity_provider.py b/openstackclient/tests/unit/identity/v3/test_identity_provider.py
index 20e7f49..c65e947 100644
--- a/openstackclient/tests/unit/identity/v3/test_identity_provider.py
+++ b/openstackclient/tests/unit/identity/v3/test_identity_provider.py
@@ -127,7 +127,7 @@ class TestIdentityProviderCreate(TestIdentityProvider):
]
verifylist = [
('identity_provider_id', identity_fakes.idp_id),
- ('remote_id', identity_fakes.idp_remote_ids[:1]),
+ ('remote_ids', identity_fakes.idp_remote_ids[:1]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
@@ -157,7 +157,7 @@ class TestIdentityProviderCreate(TestIdentityProvider):
]
verifylist = [
('identity_provider_id', identity_fakes.idp_id),
- ('remote_id', identity_fakes.idp_remote_ids),
+ ('remote_ids', identity_fakes.idp_remote_ids),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
@@ -561,7 +561,7 @@ class TestIdentityProviderSet(TestIdentityProvider):
('description', new_description),
('enable', False),
('disable', False),
- ('remote_id', None),
+ ('remote_ids', None),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
@@ -597,7 +597,7 @@ class TestIdentityProviderSet(TestIdentityProvider):
('description', None),
('enable', False),
('disable', True),
- ('remote_id', identity_fakes.idp_remote_ids),
+ ('remote_ids', identity_fakes.idp_remote_ids),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -637,7 +637,7 @@ class TestIdentityProviderSet(TestIdentityProvider):
('description', None),
('enable', True),
('disable', False),
- ('remote_id', identity_fakes.idp_remote_ids),
+ ('remote_ids', identity_fakes.idp_remote_ids),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -675,7 +675,7 @@ class TestIdentityProviderSet(TestIdentityProvider):
('description', None),
('enable', True),
('disable', False),
- ('remote_id', [self.new_remote_id]),
+ ('remote_ids', [self.new_remote_id]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -756,7 +756,7 @@ class TestIdentityProviderSet(TestIdentityProvider):
('identity_provider', identity_fakes.idp_id),
('enable', False),
('disable', False),
- ('remote_id', None),
+ ('remote_ids', None),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -776,7 +776,7 @@ class TestIdentityProviderSet(TestIdentityProvider):
('identity_provider', identity_fakes.idp_id),
('enable', False),
('disable', False),
- ('remote_id', None),
+ ('remote_ids', None),
('authorization_ttl', 60),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -800,7 +800,7 @@ class TestIdentityProviderSet(TestIdentityProvider):
('identity_provider', identity_fakes.idp_id),
('enable', False),
('disable', False),
- ('remote_id', None),
+ ('remote_ids', None),
('authorization_ttl', 0),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -816,7 +816,7 @@ class TestIdentityProviderSet(TestIdentityProvider):
('identity_provider', identity_fakes.idp_id),
('enable', False),
('disable', False),
- ('remote_id', None),
+ ('remote_ids', None),
('authorization_ttl', -1),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
diff --git a/openstackclient/tests/unit/identity/v3/test_limit.py b/openstackclient/tests/unit/identity/v3/test_limit.py
index a1d180b..4c2184c 100644
--- a/openstackclient/tests/unit/identity/v3/test_limit.py
+++ b/openstackclient/tests/unit/identity/v3/test_limit.py
@@ -10,87 +10,85 @@
# License for the specific language governing permissions and limitations
# under the License.
-import copy
-
-from keystoneauth1.exceptions import http as ksa_exceptions
+from openstack import exceptions as sdk_exc
+from openstack.identity.v3 import domain as _domain
+from openstack.identity.v3 import limit as _limit
+from openstack.identity.v3 import project as _project
+from openstack.identity.v3 import region as _region
+from openstack.identity.v3 import service as _service
+from openstack.test import fakes as sdk_fakes
from osc_lib import exceptions
from openstackclient.identity.v3 import limit
-from openstackclient.tests.unit import fakes
from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes
-class TestLimit(identity_fakes.TestIdentityv3):
+class TestLimitCreate(identity_fakes.TestIdentityv3):
def setUp(self):
super().setUp()
- identity_manager = self.identity_client
-
- self.limit_mock = identity_manager.limits
-
- self.services_mock = identity_manager.services
- self.services_mock.reset_mock()
-
- self.projects_mock = identity_manager.projects
- self.projects_mock.reset_mock()
-
- self.regions_mock = identity_manager.regions
- self.regions_mock.reset_mock()
+ self.domain = sdk_fakes.generate_fake_resource(_domain.Domain)
+ self.project = sdk_fakes.generate_fake_resource(
+ _project.Project, domain_id=self.domain.id
+ )
+ self.region = sdk_fakes.generate_fake_resource(_region.Region)
+ self.service = sdk_fakes.generate_fake_resource(_service.Service)
+ self.resource_limit = 15
-class TestLimitCreate(TestLimit):
- def setUp(self):
- super().setUp()
-
- self.service = fakes.FakeResource(
- None, copy.deepcopy(identity_fakes.SERVICE), loaded=True
- )
- self.services_mock.get.return_value = self.service
+ self.identity_sdk_client.find_service.return_value = self.service
+ self.identity_sdk_client.get_region.return_value = self.region
+ self.identity_sdk_client.find_project.return_value = self.project
+ self.identity_sdk_client.find_domain.return_value = self.domain
- self.project = fakes.FakeResource(
- None, copy.deepcopy(identity_fakes.PROJECT), loaded=True
+ self.limit = sdk_fakes.generate_fake_resource(
+ resource_type=_limit.Limit,
+ project_id=self.project.id,
+ service_id=self.service.id,
+ resource_name='foobars',
+ description=None,
+ resource_limit=self.resource_limit,
+ region_id=None,
)
- self.projects_mock.get.return_value = self.project
-
- self.region = fakes.FakeResource(
- None, copy.deepcopy(identity_fakes.REGION), loaded=True
+ self.limit_with_options = sdk_fakes.generate_fake_resource(
+ resource_type=_limit.Limit,
+ project_id=self.project.id,
+ service_id=self.service.id,
+ resource_limit=self.resource_limit,
+ resource_name='foobars',
+ description='test description',
+ region_id=self.region.id,
)
- self.regions_mock.get.return_value = self.region
self.cmd = limit.CreateLimit(self.app, None)
def test_limit_create_without_options(self):
- self.limit_mock.create.return_value = fakes.FakeResource(
- None, copy.deepcopy(identity_fakes.LIMIT), loaded=True
- )
+ self.identity_sdk_client.create_limit.return_value = self.limit
- resource_limit = 15
arglist = [
'--project',
- identity_fakes.project_id,
+ self.project.id,
'--service',
- identity_fakes.service_id,
+ self.service.id,
'--resource-limit',
- str(resource_limit),
- identity_fakes.limit_resource_name,
+ str(self.resource_limit),
+ self.limit.resource_name,
]
verifylist = [
- ('project', identity_fakes.project_id),
- ('service', identity_fakes.service_id),
- ('resource_name', identity_fakes.limit_resource_name),
- ('resource_limit', resource_limit),
+ ('project', self.project.id),
+ ('service', self.service.id),
+ ('resource_name', self.limit.resource_name),
+ ('resource_limit', self.resource_limit),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- kwargs = {'description': None, 'region': None}
- self.limit_mock.create.assert_called_with(
- self.project,
- self.service,
- identity_fakes.limit_resource_name,
- resource_limit,
- **kwargs,
+ self.identity_sdk_client.create_limit.assert_called_with(
+ project_id=self.project.id,
+ service_id=self.service.id,
+ resource_name=self.limit.resource_name,
+ resource_limit=self.resource_limit,
)
collist = (
@@ -105,55 +103,58 @@ class TestLimitCreate(TestLimit):
self.assertEqual(collist, columns)
datalist = (
None,
- identity_fakes.limit_id,
- identity_fakes.project_id,
+ self.limit.id,
+ self.project.id,
None,
- resource_limit,
- identity_fakes.limit_resource_name,
- identity_fakes.service_id,
+ self.resource_limit,
+ self.limit.resource_name,
+ self.service.id,
)
self.assertEqual(datalist, data)
def test_limit_create_with_options(self):
- self.limit_mock.create.return_value = fakes.FakeResource(
- None, copy.deepcopy(identity_fakes.LIMIT_OPTIONS), loaded=True
+ self.identity_sdk_client.create_limit.return_value = (
+ self.limit_with_options
)
resource_limit = 15
arglist = [
'--project',
- identity_fakes.project_id,
+ self.project.id,
+ '--project-domain',
+ self.domain.name,
'--service',
- identity_fakes.service_id,
+ self.service.id,
'--resource-limit',
str(resource_limit),
'--region',
- identity_fakes.region_id,
+ self.region.id,
'--description',
- identity_fakes.limit_description,
- identity_fakes.limit_resource_name,
+ self.limit_with_options.description,
+ self.limit_with_options.resource_name,
]
verifylist = [
- ('project', identity_fakes.project_id),
- ('service', identity_fakes.service_id),
- ('resource_name', identity_fakes.limit_resource_name),
+ ('project', self.project.id),
+ ('project_domain', self.domain.name),
+ ('service', self.service.id),
+ ('resource_name', self.limit_with_options.resource_name),
('resource_limit', resource_limit),
- ('region', identity_fakes.region_id),
- ('description', identity_fakes.limit_description),
+ ('region', self.region.id),
+ ('description', self.limit_with_options.description),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
kwargs = {
- 'description': identity_fakes.limit_description,
- 'region': self.region,
+ 'project_id': self.project.id,
+ 'service_id': self.service.id,
+ 'region_id': self.region.id,
+ 'resource_name': self.limit_with_options.resource_name,
+ 'resource_limit': resource_limit,
+ 'description': self.limit_with_options.description,
}
- self.limit_mock.create.assert_called_with(
- self.project,
- self.service,
- identity_fakes.limit_resource_name,
- resource_limit,
+ self.identity_sdk_client.create_limit.assert_called_with(
**kwargs,
)
@@ -168,37 +169,41 @@ class TestLimitCreate(TestLimit):
)
self.assertEqual(collist, columns)
datalist = (
- identity_fakes.limit_description,
- identity_fakes.limit_id,
- identity_fakes.project_id,
- identity_fakes.region_id,
+ self.limit_with_options.description,
+ self.limit_with_options.id,
+ self.project.id,
+ self.region.id,
resource_limit,
- identity_fakes.limit_resource_name,
- identity_fakes.service_id,
+ self.limit_with_options.resource_name,
+ self.service.id,
)
self.assertEqual(datalist, data)
-class TestLimitDelete(TestLimit):
+class TestLimitDelete(identity_fakes.TestIdentityv3):
def setUp(self):
super().setUp()
self.cmd = limit.DeleteLimit(self.app, None)
def test_limit_delete(self):
- self.limit_mock.delete.return_value = None
+ self.limit = sdk_fakes.generate_fake_resource(
+ resource_type=_limit.Limit
+ )
+ self.identity_sdk_client.delete_limit.return_value = None
- arglist = [identity_fakes.limit_id]
- verifylist = [('limit_id', [identity_fakes.limit_id])]
+ arglist = [self.limit.id]
+ verifylist = [('limit_id', [self.limit.id])]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
- self.limit_mock.delete.assert_called_with(identity_fakes.limit_id)
+ self.identity_sdk_client.delete_limit.assert_called_with(self.limit.id)
self.assertIsNone(result)
def test_limit_delete_with_exception(self):
- return_value = ksa_exceptions.NotFound()
- self.limit_mock.delete.side_effect = return_value
+ self.identity_sdk_client.delete_limit.side_effect = (
+ sdk_exc.ResourceNotFound
+ )
arglist = ['fake-limit-id']
verifylist = [('limit_id', ['fake-limit-id'])]
@@ -211,24 +216,42 @@ class TestLimitDelete(TestLimit):
self.assertEqual('1 of 1 limits failed to delete.', str(e))
-class TestLimitShow(TestLimit):
+class TestLimitShow(identity_fakes.TestIdentityv3):
def setUp(self):
super().setUp()
- self.limit_mock.get.return_value = fakes.FakeResource(
- None, copy.deepcopy(identity_fakes.LIMIT), loaded=True
+ self.project = sdk_fakes.generate_fake_resource(_project.Project)
+ self.region = sdk_fakes.generate_fake_resource(_region.Region)
+ self.service = sdk_fakes.generate_fake_resource(_service.Service)
+
+ self.resource_limit = 15
+
+ self.identity_sdk_client.find_service.return_value = self.service
+ self.identity_sdk_client.get_region.return_value = self.region
+ self.identity_sdk_client.find_project.return_value = self.project
+
+ self.limit = sdk_fakes.generate_fake_resource(
+ resource_type=_limit.Limit,
+ project_id=self.project.id,
+ service_id=self.service.id,
+ resource_name='foobars',
+ description=None,
+ resource_limit=self.resource_limit,
+ region_id=None,
)
+ self.identity_sdk_client.get_limit.return_value = self.limit
+
self.cmd = limit.ShowLimit(self.app, None)
def test_limit_show(self):
- arglist = [identity_fakes.limit_id]
- verifylist = [('limit_id', identity_fakes.limit_id)]
+ arglist = [self.limit.id]
+ verifylist = [('limit_id', self.limit.id)]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- self.limit_mock.get.assert_called_with(identity_fakes.limit_id)
+ self.identity_sdk_client.get_limit.assert_called_with(self.limit.id)
collist = (
'description',
@@ -242,45 +265,61 @@ class TestLimitShow(TestLimit):
self.assertEqual(collist, columns)
datalist = (
None,
- identity_fakes.limit_id,
- identity_fakes.project_id,
+ self.limit.id,
+ self.project.id,
None,
- identity_fakes.limit_resource_limit,
- identity_fakes.limit_resource_name,
- identity_fakes.service_id,
+ self.resource_limit,
+ self.limit.resource_name,
+ self.service.id,
)
self.assertEqual(datalist, data)
-class TestLimitSet(TestLimit):
+class TestLimitSet(identity_fakes.TestIdentityv3):
def setUp(self):
super().setUp()
+
+ self.project = sdk_fakes.generate_fake_resource(_project.Project)
+ self.region = sdk_fakes.generate_fake_resource(_region.Region)
+ self.service = sdk_fakes.generate_fake_resource(_service.Service)
+
+ self.resource_limit = 15
+
+ self.identity_sdk_client.find_service.return_value = self.service
+ self.identity_sdk_client.get_region.return_value = self.region
+ self.identity_sdk_client.find_project.return_value = self.project
+
self.cmd = limit.SetLimit(self.app, None)
def test_limit_set_description(self):
- limit = copy.deepcopy(identity_fakes.LIMIT)
- limit['description'] = identity_fakes.limit_description
- self.limit_mock.update.return_value = fakes.FakeResource(
- None, limit, loaded=True
+ description = 'limit of foobars'
+ limit = sdk_fakes.generate_fake_resource(
+ resource_type=_limit.Limit,
+ project_id=self.project.id,
+ service_id=self.service.id,
+ resource_name='foobars',
+ description=description,
+ resource_limit=self.resource_limit,
+ region_id=None,
)
+ self.identity_sdk_client.update_limit.return_value = limit
arglist = [
'--description',
- identity_fakes.limit_description,
- identity_fakes.limit_id,
+ description,
+ limit.id,
]
verifylist = [
- ('description', identity_fakes.limit_description),
- ('limit_id', identity_fakes.limit_id),
+ ('description', description),
+ ('limit_id', limit.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- self.limit_mock.update.assert_called_with(
- identity_fakes.limit_id,
- description=identity_fakes.limit_description,
- resource_limit=None,
+ self.identity_sdk_client.update_limit.assert_called_with(
+ limit.id,
+ description=description,
)
collist = (
@@ -294,40 +333,44 @@ class TestLimitSet(TestLimit):
)
self.assertEqual(collist, columns)
datalist = (
- identity_fakes.limit_description,
- identity_fakes.limit_id,
- identity_fakes.project_id,
+ description,
+ limit.id,
+ self.project.id,
None,
- identity_fakes.limit_resource_limit,
- identity_fakes.limit_resource_name,
- identity_fakes.service_id,
+ limit.resource_limit,
+ limit.resource_name,
+ self.service.id,
)
self.assertEqual(datalist, data)
def test_limit_set_resource_limit(self):
resource_limit = 20
- limit = copy.deepcopy(identity_fakes.LIMIT)
- limit['resource_limit'] = resource_limit
- self.limit_mock.update.return_value = fakes.FakeResource(
- None, limit, loaded=True
+ limit = sdk_fakes.generate_fake_resource(
+ resource_type=_limit.Limit,
+ project_id=self.project.id,
+ service_id=self.service.id,
+ resource_name='foobars',
+ description=None,
+ resource_limit=resource_limit,
+ region_id=None,
)
+ self.identity_sdk_client.update_limit.return_value = limit
arglist = [
'--resource-limit',
str(resource_limit),
- identity_fakes.limit_id,
+ limit.id,
]
verifylist = [
('resource_limit', resource_limit),
- ('limit_id', identity_fakes.limit_id),
+ ('limit_id', limit.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- self.limit_mock.update.assert_called_with(
- identity_fakes.limit_id,
- description=None,
+ self.identity_sdk_client.update_limit.assert_called_with(
+ limit.id,
resource_limit=resource_limit,
)
@@ -343,25 +386,36 @@ class TestLimitSet(TestLimit):
self.assertEqual(collist, columns)
datalist = (
None,
- identity_fakes.limit_id,
- identity_fakes.project_id,
+ limit.id,
+ self.project.id,
None,
resource_limit,
- identity_fakes.limit_resource_name,
- identity_fakes.service_id,
+ limit.resource_name,
+ self.service.id,
)
self.assertEqual(datalist, data)
-class TestLimitList(TestLimit):
+class TestLimitList(identity_fakes.TestIdentityv3):
def setUp(self):
super().setUp()
- self.limit_mock.list.return_value = [
- fakes.FakeResource(
- None, copy.deepcopy(identity_fakes.LIMIT), loaded=True
- )
- ]
+ self.project = sdk_fakes.generate_fake_resource(_project.Project)
+ self.region = sdk_fakes.generate_fake_resource(_region.Region)
+ self.service = sdk_fakes.generate_fake_resource(_service.Service)
+
+ self.resource_limit = 15
+
+ self.limit = sdk_fakes.generate_fake_resource(
+ resource_type=_limit.Limit,
+ project_id=self.project.id,
+ service_id=self.service.id,
+ resource_name='foobars',
+ description=None,
+ resource_limit=self.resource_limit,
+ region_id=None,
+ )
+ self.identity_sdk_client.limits.return_value = [self.limit]
self.cmd = limit.ListLimit(self.app, None)
@@ -372,9 +426,7 @@ class TestLimitList(TestLimit):
columns, data = self.cmd.take_action(parsed_args)
- self.limit_mock.list.assert_called_with(
- service=None, resource_name=None, region=None, project=None
- )
+ self.identity_sdk_client.limits.assert_called_with()
collist = (
'ID',
@@ -388,11 +440,11 @@ class TestLimitList(TestLimit):
self.assertEqual(collist, columns)
datalist = (
(
- identity_fakes.limit_id,
- identity_fakes.project_id,
- identity_fakes.service_id,
- identity_fakes.limit_resource_name,
- identity_fakes.limit_resource_limit,
+ self.limit.id,
+ self.project.id,
+ self.service.id,
+ self.limit.resource_name,
+ self.limit.resource_limit,
None,
None,
),
diff --git a/openstackclient/tests/unit/identity/v3/test_oauth.py b/openstackclient/tests/unit/identity/v3/test_oauth.py
index 576f8b2..9dcf0be 100644
--- a/openstackclient/tests/unit/identity/v3/test_oauth.py
+++ b/openstackclient/tests/unit/identity/v3/test_oauth.py
@@ -109,7 +109,7 @@ class TestRequestTokenAuthorize(TestOAuth1):
]
verifylist = [
('request_key', identity_fakes.request_token_id),
- ('role', [identity_fakes.role_name]),
+ ('roles', [identity_fakes.role_name]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
diff --git a/openstackclient/tests/unit/identity/v3/test_project.py b/openstackclient/tests/unit/identity/v3/test_project.py
index 024b74f..dae1aeb 100644
--- a/openstackclient/tests/unit/identity/v3/test_project.py
+++ b/openstackclient/tests/unit/identity/v3/test_project.py
@@ -13,31 +13,20 @@
# under the License.
from unittest import mock
-from unittest.mock import call
+from openstack import exceptions as sdk_exc
+from openstack.identity.v3 import domain as _domain
+from openstack.identity.v3 import project as _project
+from openstack.identity.v3 import user as _user
+from openstack.test import fakes as sdk_fakes
from osc_lib import exceptions
-from osc_lib import utils
-from openstackclient.identity import common
from openstackclient.identity.v3 import project
from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes
-class TestProject(identity_fakes.TestIdentityv3):
- def setUp(self):
- super().setUp()
-
- # Get a shortcut to the DomainManager Mock
- self.domains_mock = self.identity_client.domains
- self.domains_mock.reset_mock()
-
- # Get a shortcut to the ProjectManager Mock
- self.projects_mock = self.identity_client.projects
- self.projects_mock.reset_mock()
-
-
-class TestProjectCreate(TestProject):
- domain = identity_fakes.FakeDomain.create_one_domain()
+class TestProjectCreate(identity_fakes.TestIdentityv3):
+ domain = sdk_fakes.generate_fake_resource(_domain.Domain)
columns = (
'description',
@@ -46,39 +35,41 @@ class TestProjectCreate(TestProject):
'id',
'is_domain',
'name',
+ 'options',
'parent_id',
'tags',
)
+ project_kwargs_no_options = {
+ 'description': None,
+ 'domain_id': None,
+ 'enabled': True,
+ 'is_domain': False,
+ 'parent_id': None,
+ 'tags': [],
+ }
+
def setUp(self):
super().setUp()
- self.project = identity_fakes.FakeProject.create_one_project(
- attrs={'domain_id': self.domain.id}
- )
- self.domains_mock.get.return_value = self.domain
- self.projects_mock.create.return_value = self.project
- self.datalist = (
- self.project.description,
- self.project.domain_id,
- True,
- self.project.id,
- False,
- self.project.name,
- self.project.parent_id,
- self.project.tags,
- )
+ self.identity_sdk_client.find_domain.return_value = self.domain
+
# Get the command object to test
self.cmd = project.CreateProject(self.app, None)
def test_project_create_no_options(self):
+ project = sdk_fakes.generate_fake_resource(
+ _project.Project, **self.project_kwargs_no_options
+ )
+ self.identity_sdk_client.create_project.return_value = project
+
arglist = [
- self.project.name,
+ project.name,
]
verifylist = [
('parent', None),
('enabled', True),
- ('name', self.project.name),
+ ('name', project.name),
('tags', []),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -88,53 +79,43 @@ class TestProjectCreate(TestProject):
# data to be shown.
columns, data = self.cmd.take_action(parsed_args)
- # Set expected values
kwargs = {
- 'name': self.project.name,
- 'domain': None,
- 'description': None,
- 'enabled': True,
- 'parent': None,
- 'tags': [],
- 'options': {},
+ 'name': project.name,
+ 'is_enabled': True,
}
- # ProjectManager.create(name=, domain=, description=,
- # enabled=, **kwargs)
- self.projects_mock.create.assert_called_with(**kwargs)
+ self.identity_sdk_client.create_project.assert_called_with(**kwargs)
+
+ self.assertEqual(self.columns, columns)
- collist = (
- 'description',
- 'domain_id',
- 'enabled',
- 'id',
- 'is_domain',
- 'name',
- 'parent_id',
- 'tags',
- )
- self.assertEqual(collist, columns)
datalist = (
- self.project.description,
- self.project.domain_id,
+ None,
+ None,
True,
- self.project.id,
+ project.id,
False,
- self.project.name,
- self.project.parent_id,
- self.project.tags,
+ project.name,
+ {},
+ None,
+ [],
)
self.assertEqual(datalist, data)
def test_project_create_description(self):
+ project = sdk_fakes.generate_fake_resource(
+ _project.Project,
+ **dict(self.project_kwargs_no_options, description='new desc'),
+ )
+ self.identity_sdk_client.create_project.return_value = project
+
arglist = [
'--description',
'new desc',
- self.project.name,
+ project.name,
]
verifylist = [
('description', 'new desc'),
('enabled', True),
- ('name', self.project.name),
+ ('name', project.name),
('parent', None),
('tags', []),
]
@@ -145,33 +126,43 @@ class TestProjectCreate(TestProject):
# data to be shown.
columns, data = self.cmd.take_action(parsed_args)
- # Set expected values
kwargs = {
- 'name': self.project.name,
- 'domain': None,
+ 'name': project.name,
'description': 'new desc',
- 'enabled': True,
- 'parent': None,
- 'tags': [],
- 'options': {},
+ 'is_enabled': True,
}
- # ProjectManager.create(name=, domain=, description=,
- # enabled=, **kwargs)
- self.projects_mock.create.assert_called_with(**kwargs)
+ self.identity_sdk_client.create_project.assert_called_with(**kwargs)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ datalist = (
+ 'new desc',
+ None,
+ True,
+ project.id,
+ False,
+ project.name,
+ {},
+ None,
+ [],
+ )
+ self.assertEqual(datalist, data)
def test_project_create_domain(self):
+ project = sdk_fakes.generate_fake_resource(
+ _project.Project,
+ **dict(self.project_kwargs_no_options, domain_id=self.domain.id),
+ )
+ self.identity_sdk_client.create_project.return_value = project
+
arglist = [
'--domain',
- self.project.domain_id,
- self.project.name,
+ project.domain_id,
+ project.name,
]
verifylist = [
- ('domain', self.project.domain_id),
+ ('domain', project.domain_id),
('enabled', True),
- ('name', self.project.name),
+ ('name', project.name),
('parent', None),
('tags', []),
]
@@ -184,63 +175,90 @@ class TestProjectCreate(TestProject):
# Set expected values
kwargs = {
- 'name': self.project.name,
- 'domain': self.project.domain_id,
- 'description': None,
- 'enabled': True,
- 'parent': None,
- 'tags': [],
- 'options': {},
+ 'name': project.name,
+ 'domain_id': project.domain_id,
+ 'is_enabled': True,
}
- # ProjectManager.create(name=, domain=, description=,
- # enabled=, **kwargs)
- self.projects_mock.create.assert_called_with(**kwargs)
+ self.identity_sdk_client.create_project.assert_called_with(**kwargs)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ datalist = (
+ None,
+ self.domain.id,
+ True,
+ project.id,
+ False,
+ project.name,
+ {},
+ None,
+ [],
+ )
+ self.assertEqual(datalist, data)
def test_project_create_domain_no_perms(self):
+ project = sdk_fakes.generate_fake_resource(
+ _project.Project,
+ **dict(self.project_kwargs_no_options, domain_id=self.domain.id),
+ )
+ self.identity_sdk_client.create_project.return_value = project
+
arglist = [
'--domain',
- self.project.domain_id,
- self.project.name,
+ project.domain_id,
+ project.name,
]
verifylist = [
- ('domain', self.project.domain_id),
+ ('domain', project.domain_id),
('enabled', True),
- ('name', self.project.name),
+ ('name', project.name),
('parent', None),
('tags', []),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- mocker = mock.Mock()
- mocker.return_value = None
- with mock.patch("osc_lib.utils.find_resource", mocker):
- columns, data = self.cmd.take_action(parsed_args)
+ self.identity_sdk_client.find_domain.side_effect = (
+ sdk_exc.ForbiddenException
+ )
+ self.identity_sdk_client.find_domain.return_value = None
+
+ columns, data = self.cmd.take_action(parsed_args)
# Set expected values
kwargs = {
- 'name': self.project.name,
- 'domain': self.project.domain_id,
- 'description': None,
- 'enabled': True,
- 'parent': None,
- 'tags': [],
- 'options': {},
+ 'name': project.name,
+ 'domain_id': project.domain_id,
+ 'is_enabled': True,
}
- self.projects_mock.create.assert_called_with(**kwargs)
+ self.identity_sdk_client.create_project.assert_called_with(**kwargs)
+
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ datalist = (
+ None,
+ self.domain.id,
+ True,
+ project.id,
+ False,
+ project.name,
+ {},
+ None,
+ [],
+ )
+ self.assertEqual(datalist, data)
def test_project_create_enable(self):
+ project = sdk_fakes.generate_fake_resource(
+ _project.Project,
+ **dict(self.project_kwargs_no_options, enabled=True),
+ )
+ self.identity_sdk_client.create_project.return_value = project
+
arglist = [
'--enable',
- self.project.name,
+ project.name,
]
verifylist = [
('enabled', True),
- ('name', self.project.name),
+ ('name', project.name),
('parent', None),
('tags', []),
]
@@ -253,29 +271,39 @@ class TestProjectCreate(TestProject):
# Set expected values
kwargs = {
- 'name': self.project.name,
- 'domain': None,
- 'description': None,
- 'enabled': True,
- 'parent': None,
- 'tags': [],
- 'options': {},
+ 'name': project.name,
+ 'is_enabled': True,
}
- # ProjectManager.create(name=, domain=, description=,
- # enabled=, **kwargs)
- self.projects_mock.create.assert_called_with(**kwargs)
+ self.identity_sdk_client.create_project.assert_called_with(**kwargs)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ datalist = (
+ None,
+ None,
+ True,
+ project.id,
+ False,
+ project.name,
+ {},
+ None,
+ [],
+ )
+ self.assertEqual(datalist, data)
def test_project_create_disable(self):
+ project = sdk_fakes.generate_fake_resource(
+ _project.Project,
+ **dict(self.project_kwargs_no_options, enabled=False),
+ )
+ self.identity_sdk_client.create_project.return_value = project
+
arglist = [
'--disable',
- self.project.name,
+ project.name,
]
verifylist = [
('enabled', False),
- ('name', self.project.name),
+ ('name', project.name),
('parent', None),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -287,32 +315,42 @@ class TestProjectCreate(TestProject):
# Set expected values
kwargs = {
- 'name': self.project.name,
- 'domain': None,
- 'description': None,
- 'enabled': False,
- 'parent': None,
- 'tags': [],
- 'options': {},
+ 'name': project.name,
+ 'is_enabled': False,
}
- # ProjectManager.create(name=, domain=,
- # description=, enabled=, **kwargs)
- self.projects_mock.create.assert_called_with(**kwargs)
+ self.identity_sdk_client.create_project.assert_called_with(**kwargs)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ datalist = (
+ None,
+ None,
+ False,
+ project.id,
+ False,
+ project.name,
+ {},
+ None,
+ [],
+ )
+ self.assertEqual(datalist, data)
def test_project_create_property(self):
+ project = sdk_fakes.generate_fake_resource(
+ _project.Project,
+ **dict(self.project_kwargs_no_options, fee='fi', fo='fum'),
+ )
+ self.identity_sdk_client.create_project.return_value = project
+
arglist = [
'--property',
'fee=fi',
'--property',
'fo=fum',
- self.project.name,
+ project.name,
]
verifylist = [
+ ('name', project.name),
('properties', {'fee': 'fi', 'fo': 'fum'}),
- ('name', self.project.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -323,36 +361,62 @@ class TestProjectCreate(TestProject):
# Set expected values
kwargs = {
- 'name': self.project.name,
- 'domain': None,
- 'description': None,
- 'enabled': True,
- 'parent': None,
+ 'name': project.name,
+ 'is_enabled': True,
'fee': 'fi',
'fo': 'fum',
- 'tags': [],
- 'options': {},
}
- # ProjectManager.create(name=, domain=, description=,
- # enabled=, **kwargs)
- self.projects_mock.create.assert_called_with(**kwargs)
+ self.identity_sdk_client.create_project.assert_called_with(**kwargs)
- self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertEqual(
+ (
+ 'description',
+ 'domain_id',
+ 'enabled',
+ 'fee',
+ 'fo',
+ 'id',
+ 'is_domain',
+ 'name',
+ 'options',
+ 'parent_id',
+ 'tags',
+ ),
+ columns,
+ )
+ datalist = (
+ None,
+ None,
+ True,
+ 'fi',
+ 'fum',
+ project.id,
+ False,
+ project.name,
+ {},
+ None,
+ [],
+ )
+ self.assertEqual(datalist, data)
def test_project_create_is_domain_false_property(self):
+ project = sdk_fakes.generate_fake_resource(
+ _project.Project,
+ **dict(self.project_kwargs_no_options, is_domain=False),
+ )
+ self.identity_sdk_client.create_project.return_value = project
+
arglist = [
'--property',
'is_domain=false',
- self.project.name,
+ project.name,
]
verifylist = [
('parent', None),
('enabled', True),
- ('name', self.project.name),
+ ('name', project.name),
('tags', []),
('properties', {'is_domain': 'false'}),
- ('name', self.project.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -364,33 +428,44 @@ class TestProjectCreate(TestProject):
# Set expected values
kwargs = {
- 'name': self.project.name,
- 'domain': None,
- 'description': None,
- 'enabled': True,
- 'parent': None,
+ 'name': project.name,
+ 'is_enabled': True,
'is_domain': False,
- 'tags': [],
- 'options': {},
}
- self.projects_mock.create.assert_called_with(**kwargs)
+ self.identity_sdk_client.create_project.assert_called_with(**kwargs)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ datalist = (
+ None,
+ None,
+ True,
+ project.id,
+ False,
+ project.name,
+ {},
+ None,
+ [],
+ )
+ self.assertEqual(datalist, data)
def test_project_create_is_domain_true_property(self):
+ project = sdk_fakes.generate_fake_resource(
+ _project.Project,
+ **dict(self.project_kwargs_no_options, is_domain=True),
+ )
+ self.identity_sdk_client.create_project.return_value = project
+
arglist = [
'--property',
'is_domain=true',
- self.project.name,
+ project.name,
]
verifylist = [
('parent', None),
('enabled', True),
- ('name', self.project.name),
+ ('name', project.name),
('tags', []),
('properties', {'is_domain': 'true'}),
- ('name', self.project.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -402,33 +477,44 @@ class TestProjectCreate(TestProject):
# Set expected values
kwargs = {
- 'name': self.project.name,
- 'domain': None,
- 'description': None,
- 'enabled': True,
- 'parent': None,
+ 'name': project.name,
+ 'is_enabled': True,
'is_domain': True,
- 'tags': [],
- 'options': {},
}
- self.projects_mock.create.assert_called_with(**kwargs)
+ self.identity_sdk_client.create_project.assert_called_with(**kwargs)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ datalist = (
+ None,
+ None,
+ True,
+ project.id,
+ True,
+ project.name,
+ {},
+ None,
+ [],
+ )
+ self.assertEqual(datalist, data)
def test_project_create_is_domain_none_property(self):
+ project = sdk_fakes.generate_fake_resource(
+ _project.Project,
+ **dict(self.project_kwargs_no_options, is_domain=None),
+ )
+ self.identity_sdk_client.create_project.return_value = project
+
arglist = [
'--property',
'is_domain=none',
- self.project.name,
+ project.name,
]
verifylist = [
('parent', None),
('enabled', True),
- ('name', self.project.name),
+ ('name', project.name),
('tags', []),
('properties', {'is_domain': 'none'}),
- ('name', self.project.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -440,40 +526,51 @@ class TestProjectCreate(TestProject):
# Set expected values
kwargs = {
- 'name': self.project.name,
- 'domain': None,
- 'description': None,
- 'enabled': True,
- 'parent': None,
+ 'name': project.name,
+ 'is_enabled': True,
'is_domain': None,
- 'tags': [],
- 'options': {},
}
- self.projects_mock.create.assert_called_with(**kwargs)
+ self.identity_sdk_client.create_project.assert_called_with(**kwargs)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ datalist = (
+ None,
+ None,
+ True,
+ project.id,
+ None,
+ project.name,
+ {},
+ None,
+ [],
+ )
+ self.assertEqual(datalist, data)
def test_project_create_parent(self):
- self.parent = identity_fakes.FakeProject.create_one_project()
- self.project = identity_fakes.FakeProject.create_one_project(
- attrs={'domain_id': self.domain.id, 'parent_id': self.parent.id}
+ parent = sdk_fakes.generate_fake_resource(_project.Project)
+ project = sdk_fakes.generate_fake_resource(
+ _project.Project,
+ **dict(
+ self.project_kwargs_no_options,
+ domain_id=self.domain.id,
+ parent_id=parent.id,
+ ),
)
- self.projects_mock.get.return_value = self.parent
- self.projects_mock.create.return_value = self.project
+ self.identity_sdk_client.find_project.return_value = parent
+ self.identity_sdk_client.create_project.return_value = project
arglist = [
'--domain',
- self.project.domain_id,
+ project.domain_id,
'--parent',
- self.parent.name,
- self.project.name,
+ parent.name,
+ project.name,
]
verifylist = [
- ('domain', self.project.domain_id),
- ('parent', self.parent.name),
+ ('domain', project.domain_id),
+ ('parent', parent.name),
('enabled', True),
- ('name', self.project.name),
+ ('name', project.name),
('tags', []),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -481,61 +578,52 @@ class TestProjectCreate(TestProject):
columns, data = self.cmd.take_action(parsed_args)
kwargs = {
- 'name': self.project.name,
- 'domain': self.project.domain_id,
- 'parent': self.parent.id,
- 'description': None,
- 'enabled': True,
- 'tags': [],
- 'options': {},
+ 'name': project.name,
+ 'domain_id': project.domain_id,
+ 'parent_id': parent.id,
+ 'is_enabled': True,
}
+ self.identity_sdk_client.create_project.assert_called_with(**kwargs)
- self.projects_mock.create.assert_called_with(**kwargs)
-
- collist = (
- 'description',
- 'domain_id',
- 'enabled',
- 'id',
- 'is_domain',
- 'name',
- 'parent_id',
- 'tags',
- )
- self.assertEqual(columns, collist)
+ self.assertEqual(self.columns, columns)
datalist = (
- self.project.description,
- self.project.domain_id,
- self.project.enabled,
- self.project.id,
- self.project.is_domain,
- self.project.name,
- self.parent.id,
- self.project.tags,
+ None,
+ self.domain.id,
+ True,
+ project.id,
+ False,
+ project.name,
+ {},
+ parent.id,
+ [],
)
self.assertEqual(data, datalist)
def test_project_create_invalid_parent(self):
- self.projects_mock.resource_class.__name__ = 'Project'
- self.projects_mock.get.side_effect = exceptions.NotFound(
- 'Invalid parent'
+ self.identity_sdk_client.find_project.side_effect = (
+ sdk_exc.ResourceNotFound
)
- self.projects_mock.find.side_effect = exceptions.NotFound(
- 'Invalid parent'
+ project = sdk_fakes.generate_fake_resource(
+ _project.Project,
+ **dict(
+ self.project_kwargs_no_options,
+ domain_id=self.domain.id,
+ parent_id='invalid',
+ ),
)
arglist = [
'--domain',
- self.project.domain_id,
+ project.domain_id,
'--parent',
'invalid',
- self.project.name,
+ project.name,
]
verifylist = [
- ('domain', self.project.domain_id),
+ ('domain', project.domain_id),
('parent', 'invalid'),
('enabled', True),
- ('name', self.project.name),
+ ('name', project.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -546,17 +634,27 @@ class TestProjectCreate(TestProject):
)
def test_project_create_with_tags(self):
+ project = sdk_fakes.generate_fake_resource(
+ _project.Project,
+ **dict(
+ self.project_kwargs_no_options,
+ domain_id=self.domain.id,
+ tags=['foo'],
+ ),
+ )
+ self.identity_sdk_client.create_project.return_value = project
+
arglist = [
'--domain',
- self.project.domain_id,
+ project.domain_id,
'--tag',
'foo',
- self.project.name,
+ project.name,
]
verifylist = [
- ('domain', self.project.domain_id),
+ ('domain', project.domain_id),
('enabled', True),
- ('name', self.project.name),
+ ('name', project.name),
('parent', None),
('tags', ['foo']),
]
@@ -569,29 +667,45 @@ class TestProjectCreate(TestProject):
# Set expected values
kwargs = {
- 'name': self.project.name,
- 'domain': self.project.domain_id,
- 'description': None,
- 'enabled': True,
- 'parent': None,
+ 'name': project.name,
+ 'domain_id': project.domain_id,
+ 'is_enabled': True,
'tags': ['foo'],
- 'options': {},
}
- self.projects_mock.create.assert_called_with(**kwargs)
+ self.identity_sdk_client.create_project.assert_called_with(**kwargs)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ datalist = (
+ None,
+ self.domain.id,
+ True,
+ project.id,
+ False,
+ project.name,
+ {},
+ None,
+ ['foo'],
+ )
+ self.assertEqual(datalist, data)
def test_project_create_with_immutable_option(self):
+ project = sdk_fakes.generate_fake_resource(
+ _project.Project,
+ **dict(
+ self.project_kwargs_no_options, options={'immutable': True}
+ ),
+ )
+ self.identity_sdk_client.create_project.return_value = project
+
arglist = [
'--immutable',
- self.project.name,
+ project.name,
]
verifylist = [
('immutable', True),
('description', None),
('enabled', True),
- ('name', self.project.name),
+ ('name', project.name),
('parent', None),
('tags', []),
]
@@ -604,31 +718,44 @@ class TestProjectCreate(TestProject):
# Set expected values
kwargs = {
- 'name': self.project.name,
- 'domain': None,
- 'description': None,
- 'enabled': True,
- 'parent': None,
- 'tags': [],
+ 'name': project.name,
+ 'is_enabled': True,
'options': {'immutable': True},
}
- # ProjectManager.create(name=, domain=, description=,
- # enabled=, **kwargs)
- self.projects_mock.create.assert_called_with(**kwargs)
+ self.identity_sdk_client.create_project.assert_called_with(**kwargs)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ datalist = (
+ None,
+ None,
+ True,
+ project.id,
+ False,
+ project.name,
+ {'immutable': True},
+ None,
+ [],
+ )
+ self.assertEqual(datalist, data)
def test_project_create_with_no_immutable_option(self):
+ project = sdk_fakes.generate_fake_resource(
+ _project.Project,
+ **dict(
+ self.project_kwargs_no_options, options={'immutable': False}
+ ),
+ )
+ self.identity_sdk_client.create_project.return_value = project
+
arglist = [
'--no-immutable',
- self.project.name,
+ project.name,
]
verifylist = [
('immutable', False),
('description', None),
('enabled', True),
- ('name', self.project.name),
+ ('name', project.name),
('parent', None),
('tags', []),
]
@@ -641,36 +768,121 @@ class TestProjectCreate(TestProject):
# Set expected values
kwargs = {
- 'name': self.project.name,
- 'domain': None,
- 'description': None,
- 'enabled': True,
- 'parent': None,
- 'tags': [],
+ 'name': project.name,
+ 'is_enabled': True,
'options': {'immutable': False},
}
- # ProjectManager.create(name=, domain=, description=,
- # enabled=, **kwargs)
- self.projects_mock.create.assert_called_with(**kwargs)
+ self.identity_sdk_client.create_project.assert_called_with(**kwargs)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ datalist = (
+ None,
+ None,
+ True,
+ project.id,
+ False,
+ project.name,
+ {'immutable': False},
+ None,
+ [],
+ )
+ self.assertEqual(datalist, data)
+ def test_project_create_conflict_with_or_show(self):
+ project = sdk_fakes.generate_fake_resource(
+ _project.Project, **self.project_kwargs_no_options
+ )
+ self.identity_sdk_client.create_project.side_effect = (
+ sdk_exc.ConflictException
+ )
+ self.identity_sdk_client.find_project.return_value = project
+
+ arglist = [
+ '--or-show',
+ project.name,
+ ]
+ verifylist = [
+ ('or_show', True),
+ ('description', None),
+ ('enabled', True),
+ ('name', project.name),
+ ('parent', None),
+ ('tags', []),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ kwargs = {
+ 'name': project.name,
+ 'is_enabled': True,
+ }
+ self.identity_sdk_client.create_project.assert_called_with(**kwargs)
+
+ self.assertEqual(self.columns, columns)
+ datalist = (
+ None,
+ None,
+ True,
+ project.id,
+ False,
+ project.name,
+ {},
+ None,
+ [],
+ )
+ self.assertEqual(datalist, data)
+
+ def test_project_create_conflict_without_or_show(self):
+ self.identity_sdk_client.create_project.side_effect = (
+ sdk_exc.ConflictException
+ )
+ project = sdk_fakes.generate_fake_resource(
+ _project.Project, **self.project_kwargs_no_options
+ )
-class TestProjectDelete(TestProject):
- project = identity_fakes.FakeProject.create_one_project()
+ arglist = [
+ project.name,
+ ]
+ verifylist = [
+ ('or_show', False),
+ ('description', None),
+ ('enabled', True),
+ ('name', project.name),
+ ('parent', None),
+ ('tags', []),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.assertRaises(
+ sdk_exc.ConflictException,
+ self.cmd.take_action,
+ parsed_args,
+ )
+
+
+class TestProjectDelete(identity_fakes.TestIdentityv3):
+ domain = sdk_fakes.generate_fake_resource(_domain.Domain)
def setUp(self):
super().setUp()
- # This is the return value for utils.find_resource()
- self.projects_mock.get.return_value = self.project
- self.projects_mock.delete.return_value = None
+ self.project = sdk_fakes.generate_fake_resource(_project.Project)
+ self.project_with_domain = sdk_fakes.generate_fake_resource(
+ _project.Project,
+ name=self.project.name,
+ domain_id=self.domain.id,
+ )
+ self.identity_sdk_client.delete_project.return_value = None
# Get the command object to test
self.cmd = project.DeleteProject(self.app, None)
def test_project_delete_no_options(self):
+ self.identity_sdk_client.find_project.return_value = self.project
+
arglist = [
self.project.id,
]
@@ -681,16 +893,72 @@ class TestProjectDelete(TestProject):
result = self.cmd.take_action(parsed_args)
- self.projects_mock.delete.assert_called_with(
+ self.identity_sdk_client.delete_project.assert_called_with(
self.project.id,
)
self.assertIsNone(result)
- @mock.patch.object(utils, 'find_resource')
- def test_delete_multi_projects_with_exception(self, find_mock):
- find_mock.side_effect = [self.project, exceptions.CommandError]
+ def test_project_multi_delete(self):
+ self.identity_sdk_client.find_project.side_effect = [
+ self.project,
+ self.project_with_domain,
+ ]
+ arglist = [self.project.id, self.project_with_domain.id]
+ verifylist = [
+ ('projects', arglist),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ self.identity_sdk_client.delete_project.assert_has_calls(
+ [
+ mock.call(self.project.id),
+ mock.call(self.project_with_domain.id),
+ ]
+ )
+ self.assertIsNone(result)
+
+ def test_project_delete_with_forbidden_domain(self):
+ self.identity_sdk_client.find_domain.side_effect = [
+ sdk_exc.ForbiddenException
+ ]
+ self.identity_sdk_client.find_project.return_value = (
+ self.project_with_domain
+ )
+
+ arglist = [
+ '--domain',
+ self.project_with_domain.domain_id,
+ self.project_with_domain.name,
+ ]
+ verifylist = [
+ ('domain', self.domain.id),
+ ('projects', [self.project_with_domain.name]),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+ self.identity_sdk_client.find_project.assert_called_with(
+ name_or_id=self.project_with_domain.name,
+ ignore_missing=False,
+ domain_id=self.domain.id,
+ )
+ self.identity_sdk_client.delete_project.assert_called_once_with(
+ self.project_with_domain.id
+ )
+ self.assertIsNone(result)
+
+ def test_delete_multi_projects_with_exception(self):
+ self.identity_sdk_client.find_project.side_effect = [
+ self.project,
+ self.project_with_domain,
+ sdk_exc.NotFoundException,
+ ]
+
arglist = [
self.project.id,
+ self.project_with_domain.id,
'unexist_project',
]
verifylist = [
@@ -702,21 +970,36 @@ class TestProjectDelete(TestProject):
self.cmd.take_action(parsed_args)
self.fail('CommandError should be raised.')
except exceptions.CommandError as e:
- self.assertEqual('1 of 2 projects failed to delete.', str(e))
+ self.assertEqual('1 of 3 projects failed to delete.', str(e))
- find_mock.assert_any_call(self.projects_mock, self.project.id)
- find_mock.assert_any_call(self.projects_mock, 'unexist_project')
+ self.identity_sdk_client.find_project.assert_has_calls(
+ [
+ mock.call(name_or_id=self.project.id, ignore_missing=False),
+ mock.call(
+ name_or_id=self.project_with_domain.id,
+ ignore_missing=False,
+ ),
+ mock.call(name_or_id='unexist_project', ignore_missing=False),
+ ]
+ )
- self.assertEqual(2, find_mock.call_count)
- self.projects_mock.delete.assert_called_once_with(self.project.id)
+ self.assertEqual(3, self.identity_sdk_client.find_project.call_count)
+ self.identity_sdk_client.delete_project.assert_has_calls(
+ [
+ mock.call(self.project.id),
+ mock.call(self.project_with_domain.id),
+ ]
+ )
-class TestProjectList(TestProject):
- domain = identity_fakes.FakeDomain.create_one_domain()
- project = identity_fakes.FakeProject.create_one_project(
- attrs={'domain_id': domain.id}
+class TestProjectList(identity_fakes.TestIdentityv3):
+ domain = sdk_fakes.generate_fake_resource(_domain.Domain)
+ project = sdk_fakes.generate_fake_resource(
+ _project.Project, domain_id=domain.id
+ )
+ projects = list(
+ sdk_fakes.generate_fake_resources(_project.Project, count=2)
)
- projects = identity_fakes.FakeProject.create_projects()
columns = (
'ID',
@@ -746,12 +1029,12 @@ class TestProjectList(TestProject):
def setUp(self):
super().setUp()
- self.projects_mock.list.return_value = [self.project]
-
# Get the command object to test
self.cmd = project.ListProject(self.app, None)
def test_project_list_no_options(self):
+ self.identity_sdk_client.projects.return_value = [self.project]
+
arglist = []
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -760,12 +1043,14 @@ class TestProjectList(TestProject):
# returns a tuple containing the column names and an iterable
# containing the data to be listed.
columns, data = self.cmd.take_action(parsed_args)
- self.projects_mock.list.assert_called_with()
+ self.identity_sdk_client.projects.assert_called_with()
self.assertEqual(self.columns, columns)
self.assertEqual(self.datalist, tuple(data))
def test_project_list_long(self):
+ self.identity_sdk_client.projects.return_value = [self.project]
+
arglist = [
'--long',
]
@@ -778,7 +1063,7 @@ class TestProjectList(TestProject):
# returns a tuple containing the column names and an iterable
# containing the data to be listed.
columns, data = self.cmd.take_action(parsed_args)
- self.projects_mock.list.assert_called_with()
+ self.identity_sdk_client.projects.assert_called_with()
collist = ('ID', 'Name', 'Domain ID', 'Description', 'Enabled')
self.assertEqual(collist, columns)
@@ -794,6 +1079,8 @@ class TestProjectList(TestProject):
self.assertEqual(datalist, tuple(data))
def test_project_list_domain(self):
+ self.identity_sdk_client.projects.return_value = [self.project]
+
arglist = [
'--domain',
self.project.domain_id,
@@ -802,7 +1089,7 @@ class TestProjectList(TestProject):
('domain', self.project.domain_id),
]
- self.domains_mock.get.return_value = self.domain
+ self.identity_sdk_client.find_domain.return_value = self.domain
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -810,14 +1097,16 @@ class TestProjectList(TestProject):
# returns a tuple containing the column names and an iterable
# containing the data to be listed.
columns, data = self.cmd.take_action(parsed_args)
- self.projects_mock.list.assert_called_with(
- domain=self.project.domain_id
+ self.identity_sdk_client.projects.assert_called_with(
+ domain_id=self.project.domain_id
)
self.assertEqual(self.columns, columns)
self.assertEqual(self.datalist, tuple(data))
def test_project_list_domain_no_perms(self):
+ self.identity_sdk_client.projects.return_value = [self.project]
+
arglist = [
'--domain',
self.project.domain_id,
@@ -826,23 +1115,30 @@ class TestProjectList(TestProject):
('domain', self.project.domain_id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- mocker = mock.Mock()
- mocker.return_value = None
- with mock.patch("osc_lib.utils.find_resource", mocker):
- columns, data = self.cmd.take_action(parsed_args)
+ self.identity_sdk_client.find_project.side_effect = (
+ sdk_exc.ResourceNotFound
+ )
+ self.identity_sdk_client.find_domain.return_value = self.domain
+
+ columns, data = self.cmd.take_action(parsed_args)
- self.projects_mock.list.assert_called_with(
- domain=self.project.domain_id
+ self.identity_sdk_client.projects.assert_called_with(
+ domain_id=self.project.domain_id
)
self.assertEqual(self.columns, columns)
self.assertEqual(self.datalist, tuple(data))
def test_project_list_parent(self):
- self.parent = identity_fakes.FakeProject.create_one_project()
- self.project = identity_fakes.FakeProject.create_one_project(
- attrs={'domain_id': self.domain.id, 'parent_id': self.parent.id}
+ self.parent = sdk_fakes.generate_fake_resource(_project.Project)
+ self.project = sdk_fakes.generate_fake_resource(
+ _project.Project,
+ id=self.project.id,
+ name=self.project.name,
+ domain_id=self.domain.id,
+ parent_id=self.parent.id,
)
+ self.identity_sdk_client.projects.return_value = [self.project]
arglist = [
'--parent',
@@ -852,18 +1148,48 @@ class TestProjectList(TestProject):
('parent', self.parent.id),
]
- self.projects_mock.get.return_value = self.parent
+ self.identity_sdk_client.find_project.return_value = self.parent
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+ self.identity_sdk_client.projects.assert_called_with(
+ parent_id=self.parent.id
+ )
+
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.datalist, tuple(data))
+
+ def test_project_list_user(self):
+ self.user = sdk_fakes.generate_fake_resource(_user.User)
+ self.project = sdk_fakes.generate_fake_resource(
+ _project.UserProject,
+ id=self.project.id,
+ name=self.project.name,
+ user_id=self.user.id,
+ )
+ self.identity_sdk_client.user_projects.return_value = [self.project]
+
+ arglist = [
+ '--user',
+ self.user.id,
+ ]
+ verifylist = [
+ ('user', self.user.id),
+ ]
+
+ self.identity_sdk_client.find_user.return_value = self.user
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- self.projects_mock.list.assert_called_with(parent=self.parent.id)
+ self.identity_sdk_client.user_projects.assert_called_with(self.user.id)
self.assertEqual(self.columns, columns)
self.assertEqual(self.datalist, tuple(data))
def test_project_list_sort(self):
- self.projects_mock.list.return_value = self.projects
+ self.identity_sdk_client.projects.return_value = self.projects
arglist = [
'--sort',
@@ -877,7 +1203,7 @@ class TestProjectList(TestProject):
# returns a tuple containing the column names and an iterable
# containing the data to be listed.
(columns, data) = self.cmd.take_action(parsed_args)
- self.projects_mock.list.assert_called_with()
+ self.identity_sdk_client.projects.assert_called_with()
collist = ('ID', 'Name')
self.assertEqual(collist, columns)
@@ -896,6 +1222,8 @@ class TestProjectList(TestProject):
self.assertEqual(datalists, tuple(data))
def test_project_list_my_projects(self):
+ self.identity_sdk_client.user_projects.return_value = [self.project]
+
auth_ref = identity_fakes.fake_auth_ref(
identity_fakes.TOKEN_WITH_PROJECT_ID,
)
@@ -913,8 +1241,8 @@ class TestProjectList(TestProject):
# returns a tuple containing the column names and an iterable
# containing the data to be listed.
columns, data = self.cmd.take_action(parsed_args)
- self.projects_mock.list.assert_called_with(
- user=self.app.client_manager.auth_ref.user_id
+ self.identity_sdk_client.user_projects.assert_called_with(
+ self.app.client_manager.auth_ref.user_id
)
collist = ('ID', 'Name')
@@ -928,6 +1256,8 @@ class TestProjectList(TestProject):
self.assertEqual(datalist, tuple(data))
def test_project_list_with_option_enabled(self):
+ self.identity_sdk_client.projects.return_value = [self.project]
+
arglist = ['--enabled']
verifylist = [('is_enabled', True)]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -938,25 +1268,28 @@ class TestProjectList(TestProject):
columns, data = self.cmd.take_action(parsed_args)
kwargs = {'is_enabled': True}
- self.projects_mock.list.assert_called_with(**kwargs)
+ self.identity_sdk_client.projects.assert_called_with(**kwargs)
self.assertEqual(self.columns, columns)
self.assertEqual(self.datalist, tuple(data))
-class TestProjectSet(TestProject):
- domain = identity_fakes.FakeDomain.create_one_domain()
- project = identity_fakes.FakeProject.create_one_project(
- attrs={'domain_id': domain.id, 'tags': ['tag1', 'tag2', 'tag3']}
+class TestProjectSet(identity_fakes.TestIdentityv3):
+ domain = sdk_fakes.generate_fake_resource(_domain.Domain)
+
+ project_kwargs_no_options = {
+ 'domain_id': domain.id,
+ 'tags': ['tag1', 'tag2', 'tag3'],
+ }
+ project = sdk_fakes.generate_fake_resource(
+ _project.Project, **project_kwargs_no_options
)
def setUp(self):
super().setUp()
- self.domains_mock.get.return_value = self.domain
-
- self.projects_mock.get.return_value = self.project
- self.projects_mock.update.return_value = self.project
+ self.identity_sdk_client.find_domain.return_value = self.domain
+ self.identity_sdk_client.find_project.return_value = self.project
# Get the command object to test
self.cmd = project.SetProject(self.app, None)
@@ -997,9 +1330,10 @@ class TestProjectSet(TestProject):
kwargs = {
'name': 'qwerty',
}
- # ProjectManager.update(project, name=, domain=, description=,
- # enabled=, **kwargs)
- self.projects_mock.update.assert_called_with(self.project.id, **kwargs)
+
+ self.identity_sdk_client.update_project.assert_called_with(
+ self.project.id, **kwargs
+ )
self.assertIsNone(result)
def test_project_set_description(self):
@@ -1024,7 +1358,9 @@ class TestProjectSet(TestProject):
kwargs = {
'description': 'new desc',
}
- self.projects_mock.update.assert_called_with(self.project.id, **kwargs)
+ self.identity_sdk_client.update_project.assert_called_with(
+ self.project.id, **kwargs
+ )
self.assertIsNone(result)
def test_project_set_enable(self):
@@ -1047,7 +1383,9 @@ class TestProjectSet(TestProject):
kwargs = {
'enabled': True,
}
- self.projects_mock.update.assert_called_with(self.project.id, **kwargs)
+ self.identity_sdk_client.update_project.assert_called_with(
+ self.project.id, **kwargs
+ )
self.assertIsNone(result)
def test_project_set_disable(self):
@@ -1070,7 +1408,9 @@ class TestProjectSet(TestProject):
kwargs = {
'enabled': False,
}
- self.projects_mock.update.assert_called_with(self.project.id, **kwargs)
+ self.identity_sdk_client.update_project.assert_called_with(
+ self.project.id, **kwargs
+ )
self.assertIsNone(result)
def test_project_set_property(self):
@@ -1097,7 +1437,9 @@ class TestProjectSet(TestProject):
'fee': 'fi',
'fo': 'fum',
}
- self.projects_mock.update.assert_called_with(self.project.id, **kwargs)
+ self.identity_sdk_client.update_project.assert_called_with(
+ self.project.id, **kwargs
+ )
self.assertIsNone(result)
def test_project_set_tags(self):
@@ -1112,7 +1454,7 @@ class TestProjectSet(TestProject):
]
verifylist = [
('name', 'qwerty'),
- ('domain', self.project.domain_id),
+ ('domain', self.domain.id),
('enabled', None),
('project', self.project.name),
('tags', ['foo']),
@@ -1126,9 +1468,9 @@ class TestProjectSet(TestProject):
'name': 'qwerty',
'tags': sorted({'tag1', 'tag2', 'tag3', 'foo'}),
}
- # ProjectManager.update(project, name=, domain=, description=,
- # enabled=, **kwargs)
- self.projects_mock.update.assert_called_with(self.project.id, **kwargs)
+ self.identity_sdk_client.update_project.assert_called_with(
+ self.project.id, **kwargs
+ )
self.assertIsNone(result)
def test_project_remove_tags(self):
@@ -1142,14 +1484,16 @@ class TestProjectSet(TestProject):
verifylist = [
('enabled', None),
('project', self.project.name),
- ('remove_tag', ['tag1', 'tag2']),
+ ('remove_tags', ['tag1', 'tag2']),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
kwargs = {'tags': list({'tag3'})}
- self.projects_mock.update.assert_called_with(self.project.id, **kwargs)
+ self.identity_sdk_client.update_project.assert_called_with(
+ self.project.id, **kwargs
+ )
self.assertIsNone(result)
def test_project_set_with_immutable_option(self):
@@ -1173,7 +1517,9 @@ class TestProjectSet(TestProject):
kwargs = {
'options': {'immutable': True},
}
- self.projects_mock.update.assert_called_with(self.project.id, **kwargs)
+ self.identity_sdk_client.update_project.assert_called_with(
+ self.project.id, **kwargs
+ )
self.assertIsNone(result)
def test_project_set_with_no_immutable_option(self):
@@ -1197,114 +1543,108 @@ class TestProjectSet(TestProject):
kwargs = {
'options': {'immutable': False},
}
- self.projects_mock.update.assert_called_with(self.project.id, **kwargs)
+ self.identity_sdk_client.update_project.assert_called_with(
+ self.project.id, **kwargs
+ )
self.assertIsNone(result)
-class TestProjectShow(TestProject):
- domain = identity_fakes.FakeDomain.create_one_domain()
+class TestProjectShow(identity_fakes.TestIdentityv3):
+ domain = sdk_fakes.generate_fake_resource(_domain.Domain)
+
+ columns = (
+ 'description',
+ 'domain_id',
+ 'enabled',
+ 'id',
+ 'is_domain',
+ 'name',
+ 'options',
+ 'parent_id',
+ 'tags',
+ )
+
+ project_kwargs_no_options = {
+ 'description': None,
+ 'domain_id': None,
+ 'enabled': True,
+ 'is_domain': False,
+ 'parent_id': None,
+ 'tags': [],
+ }
def setUp(self):
super().setUp()
- self.project = identity_fakes.FakeProject.create_one_project(
- attrs={'domain_id': self.domain.id}
- )
-
# Get the command object to test
self.cmd = project.ShowProject(self.app, None)
def test_project_show(self):
- self.projects_mock.get.return_value = self.project
+ project = sdk_fakes.generate_fake_resource(
+ _project.Project, **self.project_kwargs_no_options
+ )
+ self.identity_sdk_client.find_project.return_value = project
arglist = [
- self.project.id,
+ project.id,
]
verifylist = [
- ('project', self.project.id),
+ ('project', project.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- self.identity_client.tokens.get_token_data.return_value = {
- 'token': {
- 'project': {
- 'domain': {},
- 'name': parsed_args.project,
- 'id': parsed_args.project,
- }
- }
- }
-
# In base command class ShowOne in cliff, abstract method take_action()
# returns a two-part tuple with a tuple of column names and a tuple of
# data to be shown.
columns, data = self.cmd.take_action(parsed_args)
- self.projects_mock.get.assert_called_once_with(self.project.id)
-
- collist = (
- 'description',
- 'domain_id',
- 'enabled',
- 'id',
- 'is_domain',
- 'name',
- 'parent_id',
- 'tags',
+ self.identity_sdk_client.find_project.assert_called_with(
+ project.id, ignore_missing=False
)
- self.assertEqual(collist, columns)
+
+ self.assertEqual(self.columns, columns)
datalist = (
- self.project.description,
- self.project.domain_id,
+ None,
+ None,
True,
- self.project.id,
+ project.id,
False,
- self.project.name,
- self.project.parent_id,
- self.project.tags,
+ project.name,
+ {},
+ None,
+ [],
)
self.assertEqual(datalist, data)
def test_project_show_parents(self):
- self.project = identity_fakes.FakeProject.create_one_project(
- attrs={
- 'parent_id': self.project.parent_id,
- 'parents': [{'project': {'id': self.project.parent_id}}],
- }
+ parent = sdk_fakes.generate_fake_resource(
+ _project.Project, parent_id='default'
+ )
+ project = sdk_fakes.generate_fake_resource(
+ _project.Project,
+ **dict(
+ self.project_kwargs_no_options,
+ parent_id=parent.id,
+ parents={parent.id: {parent.parent_id: None}},
+ ),
)
- self.projects_mock.get.return_value = self.project
+ self.identity_sdk_client.find_project.return_value = project
arglist = [
- self.project.id,
+ project.id,
'--parents',
]
verifylist = [
- ('project', self.project.id),
+ ('project', project.id),
('parents', True),
('children', False),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- self.identity_client.tokens.get_token_data.return_value = {
- 'token': {
- 'project': {
- 'domain': {},
- 'name': parsed_args.project,
- 'id': parsed_args.project,
- }
- }
- }
columns, data = self.cmd.take_action(parsed_args)
- self.projects_mock.get.assert_has_calls(
- [
- call(self.project.id),
- call(
- self.project.id,
- parents_as_ids=True,
- subtree_as_ids=False,
- ),
- ]
+ self.identity_sdk_client.find_project.assert_called_with(
+ project.id, parents_as_ids=True, ignore_missing=False
)
collist = (
@@ -1314,63 +1654,51 @@ class TestProjectShow(TestProject):
'id',
'is_domain',
'name',
+ 'options',
'parent_id',
'parents',
'tags',
)
- self.assertEqual(columns, collist)
+ self.assertEqual(collist, columns)
datalist = (
- self.project.description,
- self.project.domain_id,
- self.project.enabled,
- self.project.id,
- self.project.is_domain,
- self.project.name,
- self.project.parent_id,
- [{'project': {'id': self.project.parent_id}}],
- self.project.tags,
+ None,
+ None,
+ True,
+ project.id,
+ False,
+ project.name,
+ {},
+ parent.id,
+ {parent.id: {'default': None}},
+ [],
)
- self.assertEqual(data, datalist)
+ self.assertEqual(datalist, data)
def test_project_show_subtree(self):
- self.project = identity_fakes.FakeProject.create_one_project(
- attrs={
- 'parent_id': self.project.parent_id,
- 'subtree': [{'project': {'id': 'children-id'}}],
- }
+ child = sdk_fakes.generate_fake_resource(
+ _project.Project, subtree=None
+ )
+ project = sdk_fakes.generate_fake_resource(
+ _project.Project,
+ **dict(self.project_kwargs_no_options, subtree={child.id: None}),
)
- self.projects_mock.get.return_value = self.project
+ self.identity_sdk_client.find_project.return_value = project
arglist = [
- self.project.id,
+ project.id,
'--children',
]
verifylist = [
- ('project', self.project.id),
+ ('project', project.id),
('parents', False),
('children', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- self.identity_client.tokens.get_token_data.return_value = {
- 'token': {
- 'project': {
- 'domain': {},
- 'name': parsed_args.project,
- 'id': parsed_args.project,
- }
- }
- }
columns, data = self.cmd.take_action(parsed_args)
- self.projects_mock.get.assert_has_calls(
- [
- call(self.project.id),
- call(
- self.project.id,
- parents_as_ids=False,
- subtree_as_ids=True,
- ),
- ]
+
+ self.identity_sdk_client.find_project.assert_called_with(
+ project.id, subtree_as_ids=True, ignore_missing=False
)
collist = (
@@ -1380,65 +1708,63 @@ class TestProjectShow(TestProject):
'id',
'is_domain',
'name',
+ 'options',
'parent_id',
'subtree',
'tags',
)
- self.assertEqual(columns, collist)
+ self.assertEqual(collist, columns)
datalist = (
- self.project.description,
- self.project.domain_id,
- self.project.enabled,
- self.project.id,
- self.project.is_domain,
- self.project.name,
- self.project.parent_id,
- [{'project': {'id': 'children-id'}}],
- self.project.tags,
+ None,
+ None,
+ True,
+ project.id,
+ False,
+ project.name,
+ {},
+ None,
+ {child.id: None},
+ [],
)
- self.assertEqual(data, datalist)
+ self.assertEqual(datalist, data)
def test_project_show_parents_and_children(self):
- self.project = identity_fakes.FakeProject.create_one_project(
- attrs={
- 'parent_id': self.project.parent_id,
- 'parents': [{'project': {'id': self.project.parent_id}}],
- 'subtree': [{'project': {'id': 'children-id'}}],
- }
+ parent = sdk_fakes.generate_fake_resource(
+ _project.Project, parent_id='default'
+ )
+ child = sdk_fakes.generate_fake_resource(
+ _project.Project, subtree=None
)
- self.projects_mock.get.return_value = self.project
+ project = sdk_fakes.generate_fake_resource(
+ _project.Project,
+ **dict(
+ self.project_kwargs_no_options,
+ parent_id=parent.id,
+ parents={parent.id: {parent.parent_id: None}},
+ subtree={child.id: None},
+ ),
+ )
+ self.identity_sdk_client.find_project.return_value = project
arglist = [
- self.project.id,
+ project.id,
'--parents',
'--children',
]
verifylist = [
- ('project', self.project.id),
+ ('project', project.id),
('parents', True),
('children', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- self.identity_client.tokens.get_token_data.return_value = {
- 'token': {
- 'project': {
- 'domain': {},
- 'name': parsed_args.project,
- 'id': parsed_args.project,
- }
- }
- }
columns, data = self.cmd.take_action(parsed_args)
- self.projects_mock.get.assert_has_calls(
- [
- call(self.project.id),
- call(
- self.project.id,
- parents_as_ids=True,
- subtree_as_ids=True,
- ),
- ]
+
+ self.identity_sdk_client.find_project.assert_called_with(
+ project.id,
+ parents_as_ids=True,
+ subtree_as_ids=True,
+ ignore_missing=False,
)
collist = (
@@ -1448,42 +1774,36 @@ class TestProjectShow(TestProject):
'id',
'is_domain',
'name',
+ 'options',
'parent_id',
'parents',
'subtree',
'tags',
)
- self.assertEqual(columns, collist)
+ self.assertEqual(collist, columns)
datalist = (
- self.project.description,
- self.project.domain_id,
- self.project.enabled,
- self.project.id,
- self.project.is_domain,
- self.project.name,
- self.project.parent_id,
- [{'project': {'id': self.project.parent_id}}],
- [{'project': {'id': 'children-id'}}],
- self.project.tags,
+ None,
+ None,
+ True,
+ project.id,
+ False,
+ project.name,
+ {},
+ parent.id,
+ {parent.id: {'default': None}},
+ {child.id: None},
+ [],
)
- self.assertEqual(data, datalist)
+ self.assertEqual(datalist, data)
def test_project_show_with_domain(self):
- project = identity_fakes.FakeProject.create_one_project(
- {"name": self.project.name}
- )
-
- self.identity_client.tokens.get_token_data.return_value = {
- 'token': {
- 'project': {
- 'domain': {"id": self.project.domain_id},
- 'name': self.project.name,
- 'id': self.project.id,
- }
- }
- }
+ project = sdk_fakes.generate_fake_resource(
+ _project.Project,
+ **dict(self.project_kwargs_no_options, domain_id=self.domain.id),
+ )
+ self.identity_sdk_client.find_domain.return_value = self.domain
+ self.identity_sdk_client.find_project.return_value = project
- identity_client = self.identity_client
arglist = [
"--domain",
self.domain.id,
@@ -1495,23 +1815,22 @@ class TestProjectShow(TestProject):
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- project_str = common._get_token_resource(
- identity_client, 'project', parsed_args.project, parsed_args.domain
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.identity_sdk_client.find_project.assert_called_with(
+ project.id, domain_id=self.domain.id, ignore_missing=False
)
- self.assertEqual(self.project.id, project_str)
- arglist = [
- "--domain",
- project.domain_id,
+ self.assertEqual(self.columns, columns)
+ datalist = (
+ None,
+ self.domain.id,
+ True,
+ project.id,
+ False,
project.name,
- ]
- verifylist = [
- ('domain', project.domain_id),
- ('project', project.name),
- ]
- parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-
- project_str = common._get_token_resource(
- identity_client, 'project', parsed_args.project, parsed_args.domain
+ {},
+ None,
+ [],
)
- self.assertEqual(project.name, project_str)
+ self.assertEqual(datalist, data)
diff --git a/openstackclient/tests/unit/identity/v3/test_protocol.py b/openstackclient/tests/unit/identity/v3/test_protocol.py
index c856996..4ac77d6 100644
--- a/openstackclient/tests/unit/identity/v3/test_protocol.py
+++ b/openstackclient/tests/unit/identity/v3/test_protocol.py
@@ -12,202 +12,211 @@
# License for the specific language governing permissions and limitations
# under the License.
-import copy
-
+from openstack.identity.v3 import federation_protocol as _federation_protocol
+from openstack.identity.v3 import mapping as _mapping
+from openstack.test import fakes as sdk_fakes
from openstackclient.identity.v3 import federation_protocol
-from openstackclient.tests.unit import fakes
from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes
-class TestProtocol(identity_fakes.TestFederatedIdentity):
- def setUp(self):
- super().setUp()
-
- federation_lib = self.identity_client.federation
- self.protocols_mock = federation_lib.protocols
- self.protocols_mock.reset_mock()
-
-
-class TestProtocolCreate(TestProtocol):
+class TestProtocolCreate(identity_fakes.TestFederatedIdentity):
def setUp(self):
super().setUp()
- proto = copy.deepcopy(identity_fakes.PROTOCOL_OUTPUT)
- resource = fakes.FakeResource(None, proto, loaded=True)
- self.protocols_mock.create.return_value = resource
+ self.proto = sdk_fakes.generate_fake_resource(
+ _federation_protocol.FederationProtocol
+ )
+ self.identity_sdk_client.create_federation_protocol.return_value = (
+ self.proto
+ )
self.cmd = federation_protocol.CreateProtocol(self.app, None)
def test_create_protocol(self):
argslist = [
- identity_fakes.protocol_id,
+ self.proto.name,
'--identity-provider',
- identity_fakes.idp_id,
+ self.proto.idp_id,
'--mapping',
- identity_fakes.mapping_id,
+ self.proto.mapping_id,
]
verifylist = [
- ('federation_protocol', identity_fakes.protocol_id),
- ('identity_provider', identity_fakes.idp_id),
- ('mapping', identity_fakes.mapping_id),
+ ('federation_protocol', self.proto.name),
+ ('identity_provider', self.proto.idp_id),
+ ('mapping', self.proto.mapping_id),
]
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- self.protocols_mock.create.assert_called_with(
- protocol_id=identity_fakes.protocol_id,
- identity_provider=identity_fakes.idp_id,
- mapping=identity_fakes.mapping_id,
+ self.identity_sdk_client.create_federation_protocol.assert_called_with(
+ name=self.proto.id,
+ idp_id=self.proto.idp_id,
+ mapping_id=self.proto.mapping_id,
)
collist = ('id', 'identity_provider', 'mapping')
self.assertEqual(collist, columns)
datalist = (
- identity_fakes.protocol_id,
- identity_fakes.idp_id,
- identity_fakes.mapping_id,
+ self.proto.id,
+ self.proto.idp_id,
+ self.proto.mapping_id,
)
self.assertEqual(datalist, data)
-class TestProtocolDelete(TestProtocol):
+class TestProtocolDelete(identity_fakes.TestFederatedIdentity):
def setUp(self):
super().setUp()
- # This is the return value for utils.find_resource()
- self.protocols_mock.get.return_value = fakes.FakeResource(
- None,
- copy.deepcopy(identity_fakes.PROTOCOL_OUTPUT),
- loaded=True,
+ self.proto = sdk_fakes.generate_fake_resource(
+ _federation_protocol.FederationProtocol
)
-
- self.protocols_mock.delete.return_value = None
+ self.identity_sdk_client.delete_federation_protocol.return_value = None
self.cmd = federation_protocol.DeleteProtocol(self.app, None)
- def test_delete_identity_provider(self):
+ def test_delete_protocol(self):
arglist = [
'--identity-provider',
- identity_fakes.idp_id,
- identity_fakes.protocol_id,
+ self.proto.idp_id,
+ self.proto.name,
]
verifylist = [
- ('federation_protocol', [identity_fakes.protocol_id]),
- ('identity_provider', identity_fakes.idp_id),
+ ('federation_protocol', [self.proto.id]),
+ ('identity_provider', self.proto.idp_id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
- self.protocols_mock.delete.assert_called_with(
- identity_fakes.idp_id, identity_fakes.protocol_id
+ self.identity_sdk_client.delete_federation_protocol.assert_called_with(
+ idp_id=self.proto.idp_id,
+ protocol=self.proto.id,
+ ignore_missing=False,
)
self.assertIsNone(result)
-class TestProtocolList(TestProtocol):
+class TestProtocolList(identity_fakes.TestFederatedIdentity):
def setUp(self):
super().setUp()
- self.protocols_mock.get.return_value = fakes.FakeResource(
- None, identity_fakes.PROTOCOL_ID_MAPPING, loaded=True
+ self.proto1 = sdk_fakes.generate_fake_resource(
+ _federation_protocol.FederationProtocol
)
-
- self.protocols_mock.list.return_value = [
- fakes.FakeResource(
- None, identity_fakes.PROTOCOL_ID_MAPPING, loaded=True
- )
+ self.proto2 = sdk_fakes.generate_fake_resource(
+ _federation_protocol.FederationProtocol, idp_id=self.proto1
+ )
+ self.identity_sdk_client.federation_protocols.return_value = [
+ self.proto1,
+ self.proto2,
]
-
self.cmd = federation_protocol.ListProtocols(self.app, None)
def test_list_protocols(self):
- arglist = ['--identity-provider', identity_fakes.idp_id]
- verifylist = [('identity_provider', identity_fakes.idp_id)]
+ arglist = ['--identity-provider', self.proto1.idp_id]
+ verifylist = [('identity_provider', self.proto1.idp_id)]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- self.protocols_mock.list.assert_called_with(identity_fakes.idp_id)
+ self.identity_sdk_client.federation_protocols.assert_called_with(
+ self.proto1.idp_id
+ )
+ self.assertEqual(columns, ('id', 'mapping'))
+ datalist = (
+ (
+ self.proto1.name,
+ self.proto1.mapping_id,
+ ),
+ (
+ self.proto2.name,
+ self.proto2.mapping_id,
+ ),
+ )
+ self.assertEqual(datalist, tuple(data))
-class TestProtocolSet(TestProtocol):
+
+class TestProtocolSet(identity_fakes.TestFederatedIdentity):
def setUp(self):
super().setUp()
- self.protocols_mock.get.return_value = fakes.FakeResource(
- None, identity_fakes.PROTOCOL_OUTPUT, loaded=True
+ self.proto = sdk_fakes.generate_fake_resource(
+ _federation_protocol.FederationProtocol
)
- self.protocols_mock.update.return_value = fakes.FakeResource(
- None, identity_fakes.PROTOCOL_OUTPUT_UPDATED, loaded=True
+ self.mapping = sdk_fakes.generate_fake_resource(_mapping.Mapping)
+ self.identity_sdk_client.update_federation_protocol.return_value = (
+ self.proto
)
-
self.cmd = federation_protocol.SetProtocol(self.app, None)
def test_set_new_mapping(self):
arglist = [
- identity_fakes.protocol_id,
+ self.proto.name,
'--identity-provider',
- identity_fakes.idp_id,
+ self.proto.idp_id,
'--mapping',
- identity_fakes.mapping_id,
+ self.mapping.name,
]
verifylist = [
- ('identity_provider', identity_fakes.idp_id),
- ('federation_protocol', identity_fakes.protocol_id),
- ('mapping', identity_fakes.mapping_id),
+ ('identity_provider', self.proto.idp_id),
+ ('federation_protocol', self.proto.name),
+ ('mapping', self.mapping.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- self.protocols_mock.update.assert_called_with(
- identity_fakes.idp_id,
- identity_fakes.protocol_id,
- identity_fakes.mapping_id,
+ self.identity_sdk_client.update_federation_protocol.assert_called_with(
+ idp_id=self.proto.idp_id,
+ name=self.proto.name,
+ mapping_id=self.mapping.id,
)
collist = ('id', 'identity_provider', 'mapping')
self.assertEqual(collist, columns)
datalist = (
- identity_fakes.protocol_id,
- identity_fakes.idp_id,
- identity_fakes.mapping_id_updated,
+ self.proto.name,
+ self.proto.idp_id,
+ self.proto.mapping_id,
)
self.assertEqual(datalist, data)
-class TestProtocolShow(TestProtocol):
+class TestProtocolShow(identity_fakes.TestFederatedIdentity):
def setUp(self):
super().setUp()
- self.protocols_mock.get.return_value = fakes.FakeResource(
- None, identity_fakes.PROTOCOL_OUTPUT, loaded=False
+ self.proto = sdk_fakes.generate_fake_resource(
+ _federation_protocol.FederationProtocol
+ )
+ self.identity_sdk_client.get_federation_protocol.return_value = (
+ self.proto
)
-
self.cmd = federation_protocol.ShowProtocol(self.app, None)
def test_show_protocol(self):
arglist = [
- identity_fakes.protocol_id,
+ self.proto.name,
'--identity-provider',
- identity_fakes.idp_id,
+ self.proto.idp_id,
]
verifylist = [
- ('federation_protocol', identity_fakes.protocol_id),
- ('identity_provider', identity_fakes.idp_id),
+ ('federation_protocol', self.proto.name),
+ ('identity_provider', self.proto.idp_id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- self.protocols_mock.get.assert_called_with(
- identity_fakes.idp_id, identity_fakes.protocol_id
+ self.identity_sdk_client.get_federation_protocol.assert_called_with(
+ idp_id=self.proto.idp_id, protocol=self.proto.name
)
collist = ('id', 'identity_provider', 'mapping')
self.assertEqual(collist, columns)
datalist = (
- identity_fakes.protocol_id,
- identity_fakes.idp_id,
- identity_fakes.mapping_id,
+ self.proto.name,
+ self.proto.idp_id,
+ self.proto.mapping_id,
)
self.assertEqual(datalist, data)
diff --git a/openstackclient/tests/unit/identity/v3/test_registered_limit.py b/openstackclient/tests/unit/identity/v3/test_registered_limit.py
index 792096c..1864914 100644
--- a/openstackclient/tests/unit/identity/v3/test_registered_limit.py
+++ b/openstackclient/tests/unit/identity/v3/test_registered_limit.py
@@ -10,72 +10,79 @@
# License for the specific language governing permissions and limitations
# under the License.
-import copy
-
-from keystoneauth1.exceptions import http as ksa_exceptions
+from openstack import exceptions as sdk_exc
+from openstack.identity.v3 import region as _region
+from openstack.identity.v3 import registered_limit as _registered_limit
+from openstack.identity.v3 import service as _service
+from openstack.test import fakes as sdk_fakes
from osc_lib import exceptions
from openstackclient.identity.v3 import registered_limit
-from openstackclient.tests.unit import fakes
from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes
-class TestRegisteredLimit(identity_fakes.TestIdentityv3):
+class TestRegisteredLimitCreate(identity_fakes.TestIdentityv3):
def setUp(self):
super().setUp()
- self.registered_limit_mock = self.identity_client.registered_limits
-
- self.services_mock = self.identity_client.services
- self.services_mock.reset_mock()
-
- self.regions_mock = self.identity_client.regions
- self.regions_mock.reset_mock()
+ self.service = sdk_fakes.generate_fake_resource(_service.Service)
+ self.region = sdk_fakes.generate_fake_resource(_region.Region)
+ self.description = 'default limit of foobars'
+ self.default_limit = 10
+ self.resource_name = 'foobars'
-class TestRegisteredLimitCreate(TestRegisteredLimit):
- def setUp(self):
- super().setUp()
+ self.identity_sdk_client.find_service.return_value = self.service
+ self.identity_sdk_client.get_region.return_value = self.region
- self.service = fakes.FakeResource(
- None, copy.deepcopy(identity_fakes.SERVICE), loaded=True
+ self.registered_limit = sdk_fakes.generate_fake_resource(
+ resource_type=_registered_limit.RegisteredLimit,
+ description=None,
+ region_id=None,
+ service_id=self.service.id,
+ default_limit=self.default_limit,
+ resource_name=self.resource_name,
)
- self.services_mock.get.return_value = self.service
-
- self.region = fakes.FakeResource(
- None, copy.deepcopy(identity_fakes.REGION), loaded=True
+ self.registered_limit_with_options = sdk_fakes.generate_fake_resource(
+ resource_type=_registered_limit.RegisteredLimit,
+ description=self.description,
+ region_id=self.region.id,
+ service_id=self.service.id,
+ default_limit=self.default_limit,
+ resource_name=self.resource_name,
)
- self.regions_mock.get.return_value = self.region
self.cmd = registered_limit.CreateRegisteredLimit(self.app, None)
def test_registered_limit_create_without_options(self):
- self.registered_limit_mock.create.return_value = fakes.FakeResource(
- None, copy.deepcopy(identity_fakes.REGISTERED_LIMIT), loaded=True
+ self.identity_sdk_client.create_registered_limit.return_value = (
+ self.registered_limit
)
- resource_name = identity_fakes.registered_limit_resource_name
- default_limit = identity_fakes.registered_limit_default_limit
arglist = [
'--service',
- identity_fakes.service_id,
+ self.service.id,
'--default-limit',
- '10',
- resource_name,
+ str(self.default_limit),
+ self.resource_name,
]
verifylist = [
- ('service', identity_fakes.service_id),
- ('default_limit', default_limit),
- ('resource_name', resource_name),
+ ('service', self.service.id),
+ ('default_limit', self.default_limit),
+ ('resource_name', self.resource_name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- kwargs = {'description': None, 'region': None}
- self.registered_limit_mock.create.assert_called_with(
- self.service, resource_name, default_limit, **kwargs
+ kwargs = {
+ 'service_id': self.service.id,
+ 'default_limit': self.default_limit,
+ 'resource_name': self.resource_name,
+ }
+ self.identity_sdk_client.create_registered_limit.assert_called_with(
+ **kwargs
)
collist = (
@@ -89,51 +96,52 @@ class TestRegisteredLimitCreate(TestRegisteredLimit):
self.assertEqual(collist, columns)
datalist = (
- identity_fakes.registered_limit_default_limit,
+ self.default_limit,
None,
- identity_fakes.registered_limit_id,
+ self.registered_limit.id,
None,
- identity_fakes.registered_limit_resource_name,
- identity_fakes.service_id,
+ self.resource_name,
+ self.service.id,
)
self.assertEqual(datalist, data)
def test_registered_limit_create_with_options(self):
- self.registered_limit_mock.create.return_value = fakes.FakeResource(
- None,
- copy.deepcopy(identity_fakes.REGISTERED_LIMIT_OPTIONS),
- loaded=True,
+ self.identity_sdk_client.create_registered_limit.return_value = (
+ self.registered_limit_with_options
)
- resource_name = identity_fakes.registered_limit_resource_name
- default_limit = identity_fakes.registered_limit_default_limit
- description = identity_fakes.registered_limit_description
arglist = [
'--region',
- identity_fakes.region_id,
+ self.region.id,
'--description',
- description,
+ self.description,
'--service',
- identity_fakes.service_id,
+ self.service.id,
'--default-limit',
- '10',
- resource_name,
+ str(self.default_limit),
+ self.resource_name,
]
verifylist = [
- ('region', identity_fakes.region_id),
- ('description', description),
- ('service', identity_fakes.service_id),
- ('default_limit', default_limit),
- ('resource_name', resource_name),
+ ('region', self.region.id),
+ ('description', self.description),
+ ('service', self.service.id),
+ ('default_limit', self.default_limit),
+ ('resource_name', self.resource_name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- kwargs = {'description': description, 'region': self.region}
- self.registered_limit_mock.create.assert_called_with(
- self.service, resource_name, default_limit, **kwargs
+ kwargs = {
+ 'description': self.description,
+ 'region_id': self.region.id,
+ 'service_id': self.service.id,
+ 'default_limit': self.default_limit,
+ 'resource_name': self.resource_name,
+ }
+ self.identity_sdk_client.create_registered_limit.assert_called_with(
+ **kwargs
)
collist = (
@@ -147,44 +155,47 @@ class TestRegisteredLimitCreate(TestRegisteredLimit):
self.assertEqual(collist, columns)
datalist = (
- identity_fakes.registered_limit_default_limit,
- description,
- identity_fakes.registered_limit_id,
- identity_fakes.region_id,
- identity_fakes.registered_limit_resource_name,
- identity_fakes.service_id,
+ self.default_limit,
+ self.description,
+ self.registered_limit_with_options.id,
+ self.region.id,
+ self.resource_name,
+ self.service.id,
)
self.assertEqual(datalist, data)
-class TestRegisteredLimitDelete(TestRegisteredLimit):
+class TestRegisteredLimitDelete(identity_fakes.TestIdentityv3):
def setUp(self):
super().setUp()
self.cmd = registered_limit.DeleteRegisteredLimit(self.app, None)
def test_registered_limit_delete(self):
- self.registered_limit_mock.delete.return_value = None
+ self.registered_limit = sdk_fakes.generate_fake_resource(
+ resource_type=_registered_limit.RegisteredLimit,
+ )
+ self.identity_sdk_client.delete_registered_limit.return_value = None
- arglist = [identity_fakes.registered_limit_id]
- verifylist = [
- ('registered_limit_id', [identity_fakes.registered_limit_id])
- ]
+ arglist = [self.registered_limit.id]
+ verifylist = [('registered_limits', [self.registered_limit.id])]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
- self.registered_limit_mock.delete.assert_called_with(
- identity_fakes.registered_limit_id
+ self.identity_sdk_client.delete_registered_limit.assert_called_with(
+ self.registered_limit.id,
+ ignore_missing=False,
)
self.assertIsNone(result)
def test_registered_limit_delete_with_exception(self):
- return_value = ksa_exceptions.NotFound()
- self.registered_limit_mock.delete.side_effect = return_value
+ self.identity_sdk_client.delete_registered_limit.side_effect = (
+ sdk_exc.ResourceNotFound
+ )
arglist = ['fake-registered-limit-id']
- verifylist = [('registered_limit_id', ['fake-registered-limit-id'])]
+ verifylist = [('registered_limits', ['fake-registered-limit-id'])]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
try:
@@ -196,27 +207,52 @@ class TestRegisteredLimitDelete(TestRegisteredLimit):
)
-class TestRegisteredLimitShow(TestRegisteredLimit):
+class TestRegisteredLimitShow(identity_fakes.TestIdentityv3):
def setUp(self):
super().setUp()
- self.registered_limit_mock.get.return_value = fakes.FakeResource(
- None, copy.deepcopy(identity_fakes.REGISTERED_LIMIT), loaded=True
+ self.service = sdk_fakes.generate_fake_resource(_service.Service)
+ self.region = sdk_fakes.generate_fake_resource(_region.Region)
+
+ self.description = 'default limit of foobars'
+ self.default_limit = 10
+ self.resource_name = 'foobars'
+
+ self.identity_sdk_client.find_service.return_value = self.service
+ self.identity_sdk_client.get_region.return_value = self.region
+
+ self.registered_limit = sdk_fakes.generate_fake_resource(
+ resource_type=_registered_limit.RegisteredLimit,
+ description=None,
+ region_id=None,
+ service_id=self.service.id,
+ default_limit=self.default_limit,
+ resource_name=self.resource_name,
+ )
+ self.registered_limit_with_options = sdk_fakes.generate_fake_resource(
+ resource_type=_registered_limit.RegisteredLimit,
+ description=self.description,
+ region_id=self.region.id,
+ service_id=self.service.id,
+ default_limit=self.default_limit,
+ resource_name=self.resource_name,
)
self.cmd = registered_limit.ShowRegisteredLimit(self.app, None)
def test_registered_limit_show(self):
- arglist = [identity_fakes.registered_limit_id]
- verifylist = [
- ('registered_limit_id', identity_fakes.registered_limit_id)
- ]
+ self.identity_sdk_client.get_registered_limit.return_value = (
+ self.registered_limit
+ )
+
+ arglist = [self.registered_limit.id]
+ verifylist = [('registered_limit_id', self.registered_limit.id)]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- self.registered_limit_mock.get.assert_called_with(
- identity_fakes.registered_limit_id
+ self.identity_sdk_client.get_registered_limit.assert_called_with(
+ self.registered_limit.id
)
collist = (
@@ -229,50 +265,107 @@ class TestRegisteredLimitShow(TestRegisteredLimit):
)
self.assertEqual(collist, columns)
datalist = (
- identity_fakes.registered_limit_default_limit,
+ self.default_limit,
None,
- identity_fakes.registered_limit_id,
+ self.registered_limit.id,
None,
- identity_fakes.registered_limit_resource_name,
- identity_fakes.service_id,
+ self.resource_name,
+ self.service.id,
+ )
+ self.assertEqual(datalist, data)
+
+ def test_registered_limit_show_with_options(self):
+ self.identity_sdk_client.get_registered_limit.return_value = (
+ self.registered_limit_with_options
+ )
+
+ arglist = [self.registered_limit_with_options.id]
+ verifylist = [
+ ('registered_limit_id', self.registered_limit_with_options.id)
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.identity_sdk_client.get_registered_limit.assert_called_with(
+ self.registered_limit_with_options.id
+ )
+
+ collist = (
+ 'default_limit',
+ 'description',
+ 'id',
+ 'region_id',
+ 'resource_name',
+ 'service_id',
+ )
+ self.assertEqual(collist, columns)
+ datalist = (
+ self.default_limit,
+ self.description,
+ self.registered_limit_with_options.id,
+ self.region.id,
+ self.resource_name,
+ self.service.id,
)
self.assertEqual(datalist, data)
-class TestRegisteredLimitSet(TestRegisteredLimit):
+class TestRegisteredLimitSet(identity_fakes.TestIdentityv3):
def setUp(self):
super().setUp()
+
+ self.service = sdk_fakes.generate_fake_resource(_service.Service)
+ self.region = sdk_fakes.generate_fake_resource(_region.Region)
+
+ self.default_limit = 10
+ self.resource_name = 'foobars'
+
+ self.identity_sdk_client.find_service.return_value = self.service
+ self.identity_sdk_client.get_region.return_value = self.region
+
+ self.registered_limit = sdk_fakes.generate_fake_resource(
+ resource_type=_registered_limit.RegisteredLimit,
+ description=None,
+ region_id=None,
+ service_id=self.service.id,
+ default_limit=self.default_limit,
+ resource_name=self.resource_name,
+ )
+
self.cmd = registered_limit.SetRegisteredLimit(self.app, None)
def test_registered_limit_set_description(self):
- registered_limit = copy.deepcopy(identity_fakes.REGISTERED_LIMIT)
- registered_limit['description'] = (
- identity_fakes.registered_limit_description
+ updated_description = 'default limit of foobars'
+ updated_registered_limit = sdk_fakes.generate_fake_resource(
+ resource_type=_registered_limit.RegisteredLimit,
+ id=self.registered_limit.id,
+ description=updated_description,
+ region_id=None,
+ service_id=self.service.id,
+ default_limit=self.default_limit,
+ resource_name=self.resource_name,
)
- self.registered_limit_mock.update.return_value = fakes.FakeResource(
- None, registered_limit, loaded=True
+ self.identity_sdk_client.update_registered_limit.return_value = (
+ updated_registered_limit
)
arglist = [
'--description',
- identity_fakes.registered_limit_description,
- identity_fakes.registered_limit_id,
+ updated_description,
+ self.registered_limit.id,
]
verifylist = [
- ('description', identity_fakes.registered_limit_description),
- ('registered_limit_id', identity_fakes.registered_limit_id),
+ ('description', updated_description),
+ ('registered_limit_id', self.registered_limit.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- self.registered_limit_mock.update.assert_called_with(
- identity_fakes.registered_limit_id,
- service=None,
- resource_name=None,
- default_limit=None,
- description=identity_fakes.registered_limit_description,
- region=None,
+ self.identity_sdk_client.update_registered_limit.assert_called_with(
+ self.registered_limit.id,
+ description=updated_description,
)
collist = (
@@ -285,43 +378,46 @@ class TestRegisteredLimitSet(TestRegisteredLimit):
)
self.assertEqual(collist, columns)
datalist = (
- identity_fakes.registered_limit_default_limit,
- identity_fakes.registered_limit_description,
- identity_fakes.registered_limit_id,
+ self.default_limit,
+ updated_description,
+ self.registered_limit.id,
None,
- identity_fakes.registered_limit_resource_name,
- identity_fakes.service_id,
+ self.resource_name,
+ self.service.id,
)
self.assertEqual(datalist, data)
def test_registered_limit_set_default_limit(self):
- registered_limit = copy.deepcopy(identity_fakes.REGISTERED_LIMIT)
- default_limit = 20
- registered_limit['default_limit'] = default_limit
- self.registered_limit_mock.update.return_value = fakes.FakeResource(
- None, registered_limit, loaded=True
+ updated_default_limit = 20
+ updated_registered_limit = sdk_fakes.generate_fake_resource(
+ resource_type=_registered_limit.RegisteredLimit,
+ id=self.registered_limit.id,
+ description=None,
+ region_id=None,
+ service_id=self.service.id,
+ default_limit=updated_default_limit,
+ resource_name=self.resource_name,
+ )
+ self.identity_sdk_client.update_registered_limit.return_value = (
+ updated_registered_limit
)
arglist = [
'--default-limit',
- str(default_limit),
- identity_fakes.registered_limit_id,
+ str(updated_default_limit),
+ self.registered_limit.id,
]
verifylist = [
- ('default_limit', default_limit),
- ('registered_limit_id', identity_fakes.registered_limit_id),
+ ('default_limit', updated_default_limit),
+ ('registered_limit_id', self.registered_limit.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- self.registered_limit_mock.update.assert_called_with(
- identity_fakes.registered_limit_id,
- service=None,
- resource_name=None,
- default_limit=default_limit,
- description=None,
- region=None,
+ self.identity_sdk_client.update_registered_limit.assert_called_with(
+ self.registered_limit.id,
+ default_limit=updated_default_limit,
)
collist = (
@@ -334,43 +430,46 @@ class TestRegisteredLimitSet(TestRegisteredLimit):
)
self.assertEqual(collist, columns)
datalist = (
- default_limit,
+ updated_default_limit,
None,
- identity_fakes.registered_limit_id,
+ self.registered_limit.id,
None,
- identity_fakes.registered_limit_resource_name,
- identity_fakes.service_id,
+ self.resource_name,
+ self.service.id,
)
self.assertEqual(datalist, data)
def test_registered_limit_set_resource_name(self):
- registered_limit = copy.deepcopy(identity_fakes.REGISTERED_LIMIT)
- resource_name = 'volumes'
- registered_limit['resource_name'] = resource_name
- self.registered_limit_mock.update.return_value = fakes.FakeResource(
- None, registered_limit, loaded=True
+ updated_resource_name = 'volumes'
+ updated_registered_limit = sdk_fakes.generate_fake_resource(
+ resource_type=_registered_limit.RegisteredLimit,
+ id=self.registered_limit.id,
+ description=None,
+ region_id=None,
+ service_id=self.service.id,
+ default_limit=self.default_limit,
+ resource_name=updated_resource_name,
+ )
+ self.identity_sdk_client.update_registered_limit.return_value = (
+ updated_registered_limit
)
arglist = [
'--resource-name',
- resource_name,
- identity_fakes.registered_limit_id,
+ updated_resource_name,
+ self.registered_limit.id,
]
verifylist = [
- ('resource_name', resource_name),
- ('registered_limit_id', identity_fakes.registered_limit_id),
+ ('resource_name', updated_resource_name),
+ ('registered_limit_id', self.registered_limit.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- self.registered_limit_mock.update.assert_called_with(
- identity_fakes.registered_limit_id,
- service=None,
- resource_name=resource_name,
- default_limit=None,
- description=None,
- region=None,
+ self.identity_sdk_client.update_registered_limit.assert_called_with(
+ self.registered_limit.id,
+ resource_name=updated_resource_name,
)
collist = (
@@ -383,40 +482,43 @@ class TestRegisteredLimitSet(TestRegisteredLimit):
)
self.assertEqual(collist, columns)
datalist = (
- identity_fakes.registered_limit_default_limit,
+ self.default_limit,
None,
- identity_fakes.registered_limit_id,
+ self.registered_limit.id,
None,
- resource_name,
- identity_fakes.service_id,
+ updated_resource_name,
+ self.service.id,
)
self.assertEqual(datalist, data)
def test_registered_limit_set_service(self):
- registered_limit = copy.deepcopy(identity_fakes.REGISTERED_LIMIT)
- service = identity_fakes.FakeService.create_one_service()
- registered_limit['service_id'] = service.id
- self.registered_limit_mock.update.return_value = fakes.FakeResource(
- None, registered_limit, loaded=True
+ updated_service = sdk_fakes.generate_fake_resource(_service.Service)
+ self.identity_sdk_client.find_service.return_value = updated_service
+ updated_registered_limit = sdk_fakes.generate_fake_resource(
+ resource_type=_registered_limit.RegisteredLimit,
+ id=self.registered_limit.id,
+ description=None,
+ region_id=None,
+ service_id=updated_service.id,
+ default_limit=self.default_limit,
+ resource_name=self.resource_name,
+ )
+ self.identity_sdk_client.update_registered_limit.return_value = (
+ updated_registered_limit
)
- self.services_mock.get.return_value = service
- arglist = ['--service', service.id, identity_fakes.registered_limit_id]
+ arglist = ['--service', updated_service.id, self.registered_limit.id]
verifylist = [
- ('service', service.id),
- ('registered_limit_id', identity_fakes.registered_limit_id),
+ ('service', updated_service.id),
+ ('registered_limit_id', self.registered_limit.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- self.registered_limit_mock.update.assert_called_with(
- identity_fakes.registered_limit_id,
- service=service,
- resource_name=None,
- default_limit=None,
- description=None,
- region=None,
+ self.identity_sdk_client.update_registered_limit.assert_called_with(
+ self.registered_limit.id,
+ service_id=updated_service.id,
)
collist = (
@@ -429,42 +531,43 @@ class TestRegisteredLimitSet(TestRegisteredLimit):
)
self.assertEqual(collist, columns)
datalist = (
- identity_fakes.registered_limit_default_limit,
+ self.default_limit,
None,
- identity_fakes.registered_limit_id,
+ self.registered_limit.id,
None,
- identity_fakes.registered_limit_resource_name,
- service.id,
+ self.resource_name,
+ updated_service.id,
)
self.assertEqual(datalist, data)
def test_registered_limit_set_region(self):
- registered_limit = copy.deepcopy(identity_fakes.REGISTERED_LIMIT)
- region = identity_fakes.REGION
- region['id'] = 'RegionTwo'
- region = fakes.FakeResource(None, copy.deepcopy(region), loaded=True)
- registered_limit['region_id'] = region.id
- self.registered_limit_mock.update.return_value = fakes.FakeResource(
- None, registered_limit, loaded=True
+ updated_region = sdk_fakes.generate_fake_resource(_region.Region)
+ self.identity_sdk_client.get_region.return_value = updated_region
+ updated_registered_limit = sdk_fakes.generate_fake_resource(
+ resource_type=_registered_limit.RegisteredLimit,
+ id=self.registered_limit.id,
+ description=None,
+ region_id=updated_region.id,
+ service_id=self.service.id,
+ default_limit=self.default_limit,
+ resource_name=self.resource_name,
+ )
+ self.identity_sdk_client.update_registered_limit.return_value = (
+ updated_registered_limit
)
- self.regions_mock.get.return_value = region
- arglist = ['--region', region.id, identity_fakes.registered_limit_id]
+ arglist = ['--region', updated_region.id, self.registered_limit.id]
verifylist = [
- ('region', region.id),
- ('registered_limit_id', identity_fakes.registered_limit_id),
+ ('region', updated_region.id),
+ ('registered_limit_id', self.registered_limit.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- self.registered_limit_mock.update.assert_called_with(
- identity_fakes.registered_limit_id,
- service=None,
- resource_name=None,
- default_limit=None,
- description=None,
- region=region,
+ self.identity_sdk_client.update_registered_limit.assert_called_with(
+ self.registered_limit.id,
+ region_id=updated_region.id,
)
collist = (
@@ -477,54 +580,86 @@ class TestRegisteredLimitSet(TestRegisteredLimit):
)
self.assertEqual(collist, columns)
datalist = (
- identity_fakes.registered_limit_default_limit,
+ self.default_limit,
None,
- identity_fakes.registered_limit_id,
- region.id,
- identity_fakes.registered_limit_resource_name,
- identity_fakes.service_id,
+ self.registered_limit.id,
+ updated_region.id,
+ self.resource_name,
+ self.service.id,
)
self.assertEqual(datalist, data)
-class TestRegisteredLimitList(TestRegisteredLimit):
+class TestRegisteredLimitList(identity_fakes.TestIdentityv3):
def setUp(self):
super().setUp()
- self.registered_limit_mock.get.return_value = fakes.FakeResource(
- None, copy.deepcopy(identity_fakes.REGISTERED_LIMIT), loaded=True
- )
+ self.service = sdk_fakes.generate_fake_resource(_service.Service)
+ self.region = sdk_fakes.generate_fake_resource(_region.Region)
- self.cmd = registered_limit.ShowRegisteredLimit(self.app, None)
+ self.description = 'default limit of foobars'
+ self.default_limit = 10
+ self.resource_name = 'foobars'
- def test_limit_show(self):
- arglist = [identity_fakes.registered_limit_id]
- verifylist = [
- ('registered_limit_id', identity_fakes.registered_limit_id)
+ self.identity_sdk_client.find_service.return_value = self.service
+ self.identity_sdk_client.get_region.return_value = self.region
+
+ self.registered_limit = sdk_fakes.generate_fake_resource(
+ resource_type=_registered_limit.RegisteredLimit,
+ description=None,
+ region_id=None,
+ service_id=self.service.id,
+ default_limit=self.default_limit,
+ resource_name=self.resource_name,
+ )
+ self.registered_limit_with_options = sdk_fakes.generate_fake_resource(
+ resource_type=_registered_limit.RegisteredLimit,
+ description=self.description,
+ region_id=self.region.id,
+ service_id=self.service.id,
+ default_limit=self.default_limit,
+ resource_name=self.resource_name,
+ )
+ self.identity_sdk_client.registered_limits.return_value = [
+ self.registered_limit,
+ self.registered_limit_with_options,
]
+
+ self.cmd = registered_limit.ListRegisteredLimit(self.app, None)
+
+ def test_registered_limit_list(self):
+ arglist = []
+ verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- self.registered_limit_mock.get.assert_called_with(
- identity_fakes.registered_limit_id
- )
-
+ self.identity_sdk_client.registered_limits.assert_called_with()
collist = (
- 'default_limit',
- 'description',
- 'id',
- 'region_id',
- 'resource_name',
- 'service_id',
+ "ID",
+ "Service ID",
+ "Resource Name",
+ "Default Limit",
+ "Description",
+ "Region ID",
)
self.assertEqual(collist, columns)
datalist = (
- identity_fakes.registered_limit_default_limit,
- None,
- identity_fakes.registered_limit_id,
- None,
- identity_fakes.registered_limit_resource_name,
- identity_fakes.service_id,
- )
- self.assertEqual(datalist, data)
+ (
+ self.registered_limit.id,
+ self.service.id,
+ self.resource_name,
+ self.default_limit,
+ None,
+ None,
+ ),
+ (
+ self.registered_limit_with_options.id,
+ self.service.id,
+ self.resource_name,
+ self.default_limit,
+ self.description,
+ self.region.id,
+ ),
+ )
+ self.assertEqual(datalist, tuple(data))
diff --git a/openstackclient/tests/unit/identity/v3/test_role.py b/openstackclient/tests/unit/identity/v3/test_role.py
index 3ed1d44..90b2d71 100644
--- a/openstackclient/tests/unit/identity/v3/test_role.py
+++ b/openstackclient/tests/unit/identity/v3/test_role.py
@@ -15,8 +15,6 @@
from unittest import mock
-from osc_lib import exceptions
-
from openstack import exceptions as sdk_exc
from openstack.identity.v3 import domain as _domain
from openstack.identity.v3 import group as _group
@@ -25,10 +23,10 @@ from openstack.identity.v3 import role as _role
from openstack.identity.v3 import system as _system
from openstack.identity.v3 import user as _user
from openstack.test import fakes as sdk_fakes
+from osc_lib import exceptions
from openstackclient.identity.v3 import role
from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes
-from openstackclient.tests.unit import utils as test_utils
class TestRoleInherited(identity_fakes.TestIdentityv3):
@@ -36,85 +34,6 @@ class TestRoleInherited(identity_fakes.TestIdentityv3):
return True
-class TestFindSDKId(test_utils.TestCase):
- def setUp(self):
- super().setUp()
- self.user = sdk_fakes.generate_fake_resource(_user.User)
- self.identity_sdk_client = mock.Mock()
- self.identity_sdk_client.find_user = mock.Mock()
-
- def test_find_sdk_id_validate(self):
- self.identity_sdk_client.find_user.side_effect = [self.user]
-
- result = role._find_sdk_id(
- self.identity_sdk_client.find_user,
- name_or_id=self.user.id,
- validate_actor_existence=True,
- )
- self.assertEqual(self.user.id, result)
-
- def test_find_sdk_id_no_validate(self):
- self.identity_sdk_client.find_user.side_effect = [self.user]
-
- result = role._find_sdk_id(
- self.identity_sdk_client.find_user,
- name_or_id=self.user.id,
- validate_actor_existence=False,
- )
- self.assertEqual(self.user.id, result)
-
- def test_find_sdk_id_not_found_validate(self):
- self.identity_sdk_client.find_user.side_effect = [
- sdk_exc.ResourceNotFound,
- ]
-
- self.assertRaises(
- exceptions.CommandError,
- role._find_sdk_id,
- self.identity_sdk_client.find_user,
- name_or_id=self.user.id,
- validate_actor_existence=True,
- )
-
- def test_find_sdk_id_not_found_no_validate(self):
- self.identity_sdk_client.find_user.side_effect = [
- sdk_exc.ResourceNotFound,
- ]
-
- result = role._find_sdk_id(
- self.identity_sdk_client.find_user,
- name_or_id=self.user.id,
- validate_actor_existence=False,
- )
- self.assertEqual(self.user.id, result)
-
- def test_find_sdk_id_forbidden_validate(self):
- self.identity_sdk_client.find_user.side_effect = [
- sdk_exc.ForbiddenException,
- ]
-
- result = role._find_sdk_id(
- self.identity_sdk_client.find_user,
- name_or_id=self.user.id,
- validate_actor_existence=True,
- )
-
- self.assertEqual(self.user.id, result)
-
- def test_find_sdk_id_forbidden_no_validate(self):
- self.identity_sdk_client.find_user.side_effect = [
- sdk_exc.ForbiddenException,
- ]
-
- result = role._find_sdk_id(
- self.identity_sdk_client.find_user,
- name_or_id=self.user.id,
- validate_actor_existence=False,
- )
-
- self.assertEqual(self.user.id, result)
-
-
class TestRoleAdd(identity_fakes.TestIdentityv3):
def _is_inheritance_testcase(self):
return False
diff --git a/openstackclient/tests/unit/identity/v3/test_user.py b/openstackclient/tests/unit/identity/v3/test_user.py
index 1236b86..134ba5a 100644
--- a/openstackclient/tests/unit/identity/v3/test_user.py
+++ b/openstackclient/tests/unit/identity/v3/test_user.py
@@ -94,7 +94,6 @@ class TestUserCreate(identity_fakes.TestIdentityv3):
kwargs = {
'name': self.user.name,
'is_enabled': True,
- 'password': None,
}
self.identity_sdk_client.create_user.assert_called_with(**kwargs)
@@ -138,7 +137,6 @@ class TestUserCreate(identity_fakes.TestIdentityv3):
self.user.name,
]
verifylist = [
- ('password', None),
('password_prompt', True),
('enable', False),
('disable', False),
@@ -171,7 +169,6 @@ class TestUserCreate(identity_fakes.TestIdentityv3):
self.user.name,
]
verifylist = [
- ('password', None),
('password_prompt', True),
('enable', False),
('disable', False),
@@ -236,7 +233,6 @@ class TestUserCreate(identity_fakes.TestIdentityv3):
'name': self.user.name,
'email': 'barney@example.com',
'is_enabled': True,
- 'password': None,
}
self.identity_sdk_client.create_user.assert_called_with(**kwargs)
@@ -267,7 +263,6 @@ class TestUserCreate(identity_fakes.TestIdentityv3):
'name': self.user.name,
'default_project_id': self.project.id,
'is_enabled': True,
- 'password': None,
}
self.identity_sdk_client.create_user.assert_called_with(**kwargs)
@@ -312,7 +307,6 @@ class TestUserCreate(identity_fakes.TestIdentityv3):
'name': self.user.name,
'default_project_id': self.project.id,
'is_enabled': True,
- 'password': None,
}
self.identity_sdk_client.create_user.assert_called_once_with(**kwargs)
self.identity_sdk_client.find_domain.assert_called_once_with(
@@ -357,7 +351,6 @@ class TestUserCreate(identity_fakes.TestIdentityv3):
'name': self.user.name,
'domain_id': self.domain.id,
'is_enabled': True,
- 'password': None,
}
self.identity_sdk_client.create_user.assert_called_with(**kwargs)
@@ -385,7 +378,6 @@ class TestUserCreate(identity_fakes.TestIdentityv3):
kwargs = {
'name': self.user.name,
'is_enabled': True,
- 'password': None,
}
self.identity_sdk_client.create_user.assert_called_with(**kwargs)
@@ -413,7 +405,6 @@ class TestUserCreate(identity_fakes.TestIdentityv3):
kwargs = {
'name': self.user.name,
'is_enabled': False,
- 'password': None,
}
self.identity_sdk_client.create_user.assert_called_with(**kwargs)
@@ -443,7 +434,6 @@ class TestUserCreate(identity_fakes.TestIdentityv3):
'name': self.user.name,
'is_enabled': True,
'options': {'ignore_lockout_failure_attempts': True},
- 'password': None,
}
self.identity_sdk_client.create_user.assert_called_with(**kwargs)
@@ -473,7 +463,6 @@ class TestUserCreate(identity_fakes.TestIdentityv3):
'name': self.user.name,
'is_enabled': True,
'options': {'ignore_lockout_failure_attempts': False},
- 'password': None,
}
self.identity_sdk_client.create_user.assert_called_with(**kwargs)
@@ -503,7 +492,6 @@ class TestUserCreate(identity_fakes.TestIdentityv3):
'name': self.user.name,
'is_enabled': True,
'options': {'ignore_password_expiry': True},
- 'password': None,
}
self.identity_sdk_client.create_user.assert_called_with(**kwargs)
@@ -533,7 +521,6 @@ class TestUserCreate(identity_fakes.TestIdentityv3):
'name': self.user.name,
'is_enabled': True,
'options': {'ignore_password_expiry': False},
- 'password': None,
}
self.identity_sdk_client.create_user.assert_called_with(**kwargs)
@@ -563,7 +550,6 @@ class TestUserCreate(identity_fakes.TestIdentityv3):
'name': self.user.name,
'is_enabled': True,
'options': {'ignore_change_password_upon_first_use': True},
- 'password': None,
}
self.identity_sdk_client.create_user.assert_called_with(**kwargs)
@@ -593,7 +579,6 @@ class TestUserCreate(identity_fakes.TestIdentityv3):
'name': self.user.name,
'is_enabled': True,
'options': {'ignore_change_password_upon_first_use': False},
- 'password': None,
}
self.identity_sdk_client.create_user.assert_called_with(**kwargs)
@@ -623,7 +608,6 @@ class TestUserCreate(identity_fakes.TestIdentityv3):
'name': self.user.name,
'is_enabled': True,
'options': {'lock_password': True},
- 'password': None,
}
self.identity_sdk_client.create_user.assert_called_with(**kwargs)
@@ -653,7 +637,6 @@ class TestUserCreate(identity_fakes.TestIdentityv3):
'name': self.user.name,
'is_enabled': True,
'options': {'lock_password': False},
- 'password': None,
}
self.identity_sdk_client.create_user.assert_called_with(**kwargs)
@@ -683,7 +666,6 @@ class TestUserCreate(identity_fakes.TestIdentityv3):
'name': self.user.name,
'is_enabled': True,
'options': {'multi_factor_auth_enabled': True},
- 'password': None,
}
self.identity_sdk_client.create_user.assert_called_with(**kwargs)
@@ -713,7 +695,6 @@ class TestUserCreate(identity_fakes.TestIdentityv3):
'name': self.user.name,
'is_enabled': True,
'options': {'multi_factor_auth_enabled': False},
- 'password': None,
}
self.identity_sdk_client.create_user.assert_called_with(**kwargs)
@@ -730,7 +711,7 @@ class TestUserCreate(identity_fakes.TestIdentityv3):
]
verifylist = [
(
- 'multi_factor_auth_rule',
+ 'multi_factor_auth_rules',
[identity_fakes.mfa_opt1, identity_fakes.mfa_opt2],
),
('enable', False),
@@ -751,7 +732,6 @@ class TestUserCreate(identity_fakes.TestIdentityv3):
'options': {
'multi_factor_auth_rules': [["password", "totp"], ["password"]]
},
- 'password': None,
}
self.identity_sdk_client.create_user.assert_called_with(**kwargs)
@@ -769,7 +749,7 @@ class TestUserCreate(identity_fakes.TestIdentityv3):
verifylist = [
('ignore_password_expiry', True),
('disable_multi_factor_auth', True),
- ('multi_factor_auth_rule', [identity_fakes.mfa_opt1]),
+ ('multi_factor_auth_rules', [identity_fakes.mfa_opt1]),
('enable', False),
('disable', False),
('name', self.user.name),
@@ -790,7 +770,6 @@ class TestUserCreate(identity_fakes.TestIdentityv3):
'multi_factor_auth_enabled': False,
'multi_factor_auth_rules': [["password", "totp"]],
},
- 'password': None,
}
self.identity_sdk_client.create_user.assert_called_with(**kwargs)
@@ -891,7 +870,7 @@ class TestUserList(identity_fakes.TestIdentityv3):
self.identity_sdk_client.find_domain.return_value = self.domain
self.identity_sdk_client.find_group.return_value = self.group
self.identity_sdk_client.find_project.return_value = self.project
- self.identity_sdk_client.role_assignments_filter.return_value = [
+ self.identity_sdk_client.role_assignments.return_value = [
self.role_assignment
]
@@ -1029,12 +1008,10 @@ class TestUserList(identity_fakes.TestIdentityv3):
columns, data = self.cmd.take_action(parsed_args)
kwargs = {
- 'project': self.project.id,
+ 'scope_project_id': self.project.id,
}
- self.identity_sdk_client.role_assignments_filter.assert_called_with(
- **kwargs
- )
+ self.identity_sdk_client.role_assignments.assert_called_with(**kwargs)
self.assertEqual(self.columns, columns)
self.assertEqual(self.datalist, tuple(data))
@@ -1086,7 +1063,6 @@ class TestUserSet(identity_fakes.TestIdentityv3):
]
verifylist = [
('name', None),
- ('password', None),
('email', None),
('project', None),
('enable', False),
@@ -1107,7 +1083,6 @@ class TestUserSet(identity_fakes.TestIdentityv3):
]
verifylist = [
('name', 'qwerty'),
- ('password', None),
('email', None),
('project', None),
('enable', False),
@@ -1138,7 +1113,6 @@ class TestUserSet(identity_fakes.TestIdentityv3):
]
verifylist = [
('name', 'qwerty'),
- ('password', None),
('domain', self.domain.id),
('email', None),
('project', None),
@@ -1194,7 +1168,6 @@ class TestUserSet(identity_fakes.TestIdentityv3):
]
verifylist = [
('name', None),
- ('password', None),
('password_prompt', True),
('email', None),
('project', None),
@@ -1227,7 +1200,6 @@ class TestUserSet(identity_fakes.TestIdentityv3):
]
verifylist = [
('name', None),
- ('password', None),
('email', 'barney@example.com'),
('project', None),
('enable', False),
@@ -1256,7 +1228,6 @@ class TestUserSet(identity_fakes.TestIdentityv3):
]
verifylist = [
('name', None),
- ('password', None),
('email', None),
('project', self.project.id),
('enable', False),
@@ -1298,7 +1269,6 @@ class TestUserSet(identity_fakes.TestIdentityv3):
]
verifylist = [
('name', None),
- ('password', None),
('email', None),
('project', self.project.id),
('project_domain', self.project.domain_id),
@@ -1332,7 +1302,6 @@ class TestUserSet(identity_fakes.TestIdentityv3):
]
verifylist = [
('name', None),
- ('password', None),
('email', None),
('project', None),
('enable', True),
@@ -1359,7 +1328,6 @@ class TestUserSet(identity_fakes.TestIdentityv3):
]
verifylist = [
('name', None),
- ('password', None),
('email', None),
('project', None),
('enable', False),
@@ -1386,7 +1354,6 @@ class TestUserSet(identity_fakes.TestIdentityv3):
]
verifylist = [
('name', None),
- ('password', None),
('email', None),
('ignore_lockout_failure_attempts', True),
('project', None),
@@ -1414,7 +1381,6 @@ class TestUserSet(identity_fakes.TestIdentityv3):
]
verifylist = [
('name', None),
- ('password', None),
('email', None),
('no_ignore_lockout_failure_attempts', True),
('project', None),
@@ -1442,7 +1408,6 @@ class TestUserSet(identity_fakes.TestIdentityv3):
]
verifylist = [
('name', None),
- ('password', None),
('email', None),
('ignore_password_expiry', True),
('project', None),
@@ -1470,7 +1435,6 @@ class TestUserSet(identity_fakes.TestIdentityv3):
]
verifylist = [
('name', None),
- ('password', None),
('email', None),
('no_ignore_password_expiry', True),
('project', None),
@@ -1498,7 +1462,6 @@ class TestUserSet(identity_fakes.TestIdentityv3):
]
verifylist = [
('name', None),
- ('password', None),
('email', None),
('ignore_change_password_upon_first_use', True),
('project', None),
@@ -1526,7 +1489,6 @@ class TestUserSet(identity_fakes.TestIdentityv3):
]
verifylist = [
('name', None),
- ('password', None),
('email', None),
('no_ignore_change_password_upon_first_use', True),
('project', None),
@@ -1554,7 +1516,6 @@ class TestUserSet(identity_fakes.TestIdentityv3):
]
verifylist = [
('name', None),
- ('password', None),
('email', None),
('enable_lock_password', True),
('project', None),
@@ -1582,7 +1543,6 @@ class TestUserSet(identity_fakes.TestIdentityv3):
]
verifylist = [
('name', None),
- ('password', None),
('email', None),
('disable_lock_password', True),
('project', None),
@@ -1610,7 +1570,6 @@ class TestUserSet(identity_fakes.TestIdentityv3):
]
verifylist = [
('name', None),
- ('password', None),
('email', None),
('enable_multi_factor_auth', True),
('project', None),
@@ -1638,7 +1597,6 @@ class TestUserSet(identity_fakes.TestIdentityv3):
]
verifylist = [
('name', None),
- ('password', None),
('email', None),
('disable_multi_factor_auth', True),
('project', None),
@@ -1667,9 +1625,8 @@ class TestUserSet(identity_fakes.TestIdentityv3):
]
verifylist = [
('name', None),
- ('password', None),
('email', None),
- ('multi_factor_auth_rule', [identity_fakes.mfa_opt1]),
+ ('multi_factor_auth_rules', [identity_fakes.mfa_opt1]),
('project', None),
('enable', False),
('disable', False),
@@ -1699,11 +1656,10 @@ class TestUserSet(identity_fakes.TestIdentityv3):
]
verifylist = [
('name', None),
- ('password', None),
('email', None),
('ignore_password_expiry', True),
('enable_multi_factor_auth', True),
- ('multi_factor_auth_rule', [identity_fakes.mfa_opt1]),
+ ('multi_factor_auth_rules', [identity_fakes.mfa_opt1]),
('project', None),
('enable', False),
('disable', False),
diff --git a/openstackclient/tests/unit/image/v2/test_image.py b/openstackclient/tests/unit/image/v2/test_image.py
index 7eb7331..c9a273b 100644
--- a/openstackclient/tests/unit/image/v2/test_image.py
+++ b/openstackclient/tests/unit/image/v2/test_image.py
@@ -1295,6 +1295,117 @@ class TestImageSet(TestImage):
# the 'update membership' route.
self.image_client.update_image.assert_called_with(self._image.id)
+ def test_image_set_membership_accept_with_project_no_owner_change(self):
+ """Test that --project with --accept doesn't change image owner."""
+ membership = image_fakes.create_one_image_member(
+ attrs={
+ 'image_id': '0f41529e-7c12-4de8-be2d-181abb825b3c',
+ 'member_id': self.project.id,
+ }
+ )
+ self.image_client.update_member.return_value = membership
+
+ arglist = [
+ '--project',
+ self.project.name,
+ '--accept',
+ self._image.id,
+ ]
+ verifylist = [
+ ('project', self.project.name),
+ ('membership', 'accepted'),
+ ('image', self._image.id),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.cmd.take_action(parsed_args)
+
+ self.image_client.update_member.assert_called_once_with(
+ image=self._image.id,
+ member=self.project.id,
+ status='accepted',
+ )
+
+ self.image_client.update_image.assert_called()
+ call_args = self.image_client.update_image.call_args
+ if call_args:
+ args, kwargs = call_args
+ self.assertNotIn('owner_id', kwargs)
+
+ def test_image_set_membership_reject_with_project_no_owner_change(self):
+ """Test that --project with --reject doesn't change image owner."""
+ membership = image_fakes.create_one_image_member(
+ attrs={
+ 'image_id': '0f41529e-7c12-4de8-be2d-181abb825b3c',
+ 'member_id': self.project.id,
+ }
+ )
+ self.image_client.update_member.return_value = membership
+
+ arglist = [
+ '--project',
+ self.project.name,
+ '--reject',
+ self._image.id,
+ ]
+ verifylist = [
+ ('project', self.project.name),
+ ('membership', 'rejected'),
+ ('image', self._image.id),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.cmd.take_action(parsed_args)
+
+ self.image_client.update_member.assert_called_once_with(
+ image=self._image.id,
+ member=self.project.id,
+ status='rejected',
+ )
+
+ self.image_client.update_image.assert_called()
+ call_args = self.image_client.update_image.call_args
+ if call_args:
+ args, kwargs = call_args
+ self.assertNotIn('owner_id', kwargs)
+
+ def test_image_set_membership_pending_with_project_no_owner_change(self):
+ """Test that --project with --pending doesn't change image owner."""
+ membership = image_fakes.create_one_image_member(
+ attrs={
+ 'image_id': '0f41529e-7c12-4de8-be2d-181abb825b3c',
+ 'member_id': self.project.id,
+ }
+ )
+ self.image_client.update_member.return_value = membership
+
+ arglist = [
+ '--project',
+ self.project.name,
+ '--pending',
+ self._image.id,
+ ]
+ verifylist = [
+ ('project', self.project.name),
+ ('membership', 'pending'),
+ ('image', self._image.id),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.cmd.take_action(parsed_args)
+
+ self.image_client.update_member.assert_called_once_with(
+ image=self._image.id,
+ member=self.project.id,
+ status='pending',
+ )
+
+ self.image_client.update_image.assert_called()
+ call_args = self.image_client.update_image.call_args
+ if call_args:
+ args, kwargs = call_args
+ self.assertNotIn('owner_id', kwargs)
+
def test_image_set_options(self):
arglist = [
'--name',
@@ -1974,7 +2085,7 @@ class TestImageImport(TestImage):
remote_image_id=None,
remote_service_interface=None,
stores=None,
- all_stores=None,
+ all_stores=False,
all_stores_must_succeed=False,
)
@@ -2004,7 +2115,7 @@ class TestImageImport(TestImage):
remote_image_id=None,
remote_service_interface=None,
stores=None,
- all_stores=None,
+ all_stores=False,
all_stores_must_succeed=False,
)
@@ -2142,7 +2253,7 @@ class TestImageImport(TestImage):
remote_image_id=None,
remote_service_interface=None,
stores=['fast'],
- all_stores=None,
+ all_stores=False,
all_stores_must_succeed=False,
)
@@ -2174,7 +2285,7 @@ class TestImageImport(TestImage):
remote_image_id=None,
remote_service_interface=None,
stores=['fast'],
- all_stores=None,
+ all_stores=False,
all_stores_must_succeed=True,
)
@@ -2209,7 +2320,7 @@ class TestImageImport(TestImage):
remote_image_id='remote-image-id',
remote_service_interface='private',
stores=None,
- all_stores=None,
+ all_stores=False,
all_stores_must_succeed=False,
)
diff --git a/openstackclient/tests/unit/network/test_common.py b/openstackclient/tests/unit/network/test_common.py
index c1ad9b2..cc84c8b 100644
--- a/openstackclient/tests/unit/network/test_common.py
+++ b/openstackclient/tests/unit/network/test_common.py
@@ -126,17 +126,13 @@ class TestNetworkAndCompute(utils.TestCommand):
# Create client mocks. Note that we intentionally do not use specced
# mocks since we want to test fake methods.
- self.app.client_manager.network = mock.Mock()
- self.network_client = self.app.client_manager.network
- self.network_client.network_action = mock.Mock(
- return_value='take_action_network'
- )
+ self.app.client_manager.network = mock.Mock() # noqa: O401
+ self.network_client = self.app.client_manager.network # noqa: O401
+ self.network_client.network_action.return_value = 'take_action_network'
- self.app.client_manager.compute = mock.Mock()
- self.compute_client = self.app.client_manager.compute
- self.compute_client.compute_action = mock.Mock(
- return_value='take_action_compute'
- )
+ self.app.client_manager.compute = mock.Mock() # noqa: O401
+ self.compute_client = self.app.client_manager.compute # noqa: O401
+ self.compute_client.compute_action.return_value = 'take_action_compute'
self.cmd = FakeNetworkAndComputeCommand(self.app, None)
@@ -205,9 +201,9 @@ class TestNeutronCommandWithExtraArgs(utils.TestCommand):
# Create client mocks. Note that we intentionally do not use specced
# mocks since we want to test fake methods.
- self.app.client_manager.network = mock.Mock()
- self.network_client = self.app.client_manager.network
- self.network_client.test_create_action = mock.Mock()
+ self.app.client_manager.network = mock.Mock() # noqa: O401
+ self.network_client = self.app.client_manager.network # noqa: O401
+ self.network_client.test_create_action = mock.Mock() # noqa: O402
# Subclasses can override the command object to test.
self.cmd = FakeCreateNeutronCommandWithExtraArgs(self.app, None)
diff --git a/openstackclient/tests/unit/network/v2/taas/__init__.py b/openstackclient/tests/unit/network/v2/taas/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/openstackclient/tests/unit/network/v2/taas/__init__.py
diff --git a/openstackclient/tests/unit/network/v2/taas/test_osc_tap_flow.py b/openstackclient/tests/unit/network/v2/taas/test_osc_tap_flow.py
new file mode 100644
index 0000000..8e4f185
--- /dev/null
+++ b/openstackclient/tests/unit/network/v2/taas/test_osc_tap_flow.py
@@ -0,0 +1,276 @@
+# All Rights Reserved 2020
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import copy
+import operator
+import uuid
+
+from openstack.network.v2 import tap_flow as _tap_flow
+from openstack.network.v2 import tap_service as _tap_service
+from openstack.test import fakes as sdk_fakes
+from osc_lib import utils as osc_utils
+from osc_lib.utils import columns as column_util
+
+from openstackclient.network.v2.taas import tap_flow as osc_tap_flow
+from openstackclient.network.v2.taas import tap_service as osc_tap_service
+from openstackclient.tests.unit.network.v2 import fakes as network_fakes
+
+
+columns_long = tuple(
+ col
+ for col, _, listing_mode in osc_tap_flow._attr_map
+ if listing_mode in (column_util.LIST_BOTH, column_util.LIST_LONG_ONLY)
+)
+headers_long = tuple(
+ head
+ for _, head, listing_mode in osc_tap_flow._attr_map
+ if listing_mode in (column_util.LIST_BOTH, column_util.LIST_LONG_ONLY)
+)
+sorted_attr_map = sorted(osc_tap_flow._attr_map, key=operator.itemgetter(1))
+sorted_columns = tuple(col for col, _, _ in sorted_attr_map)
+sorted_headers = tuple(head for _, head, _ in sorted_attr_map)
+
+
+def _get_data(attrs, columns=sorted_columns):
+ return osc_utils.get_dict_properties(attrs, columns)
+
+
+class TestCreateTapFlow(network_fakes.TestNetworkV2):
+ columns = (
+ 'description',
+ 'direction',
+ 'id',
+ 'name',
+ 'project_id',
+ 'source_port',
+ 'status',
+ 'tap_service_id',
+ )
+
+ def setUp(self):
+ super().setUp()
+ self.cmd = osc_tap_flow.CreateTapFlow(self.app, None)
+
+ def test_create_tap_flow(self):
+ """Test Create Tap Flow."""
+ fake_tap_service = sdk_fakes.generate_fake_resource(
+ _tap_service.TapService
+ )
+ port_id = str(uuid.uuid4())
+ fake_port = network_fakes.create_one_port(attrs={'id': port_id})
+ fake_tap_flow = sdk_fakes.generate_fake_resource(
+ _tap_flow.TapFlow,
+ **{
+ 'source_port': port_id,
+ 'tap_service_id': fake_tap_service['id'],
+ 'direction': 'BOTH',
+ },
+ )
+ self.app.client_manager.network.create_tap_flow.return_value = (
+ fake_tap_flow
+ )
+ self.app.client_manager.network.find_port.return_value = fake_port
+ self.app.client_manager.network.find_tap_service.return_value = (
+ fake_tap_service
+ )
+ arg_list = [
+ '--name',
+ fake_tap_flow['name'],
+ '--port',
+ fake_tap_flow['source_port'],
+ '--tap-service',
+ fake_tap_flow['tap_service_id'],
+ '--direction',
+ fake_tap_flow['direction'],
+ ]
+
+ verify_list = [
+ ('name', fake_tap_flow['name']),
+ ('port', fake_tap_flow['source_port']),
+ ('tap_service', fake_tap_flow['tap_service_id']),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
+ columns, data = self.cmd.take_action(parsed_args)
+ mock_create_t_f = self.app.client_manager.network.create_tap_flow
+ mock_create_t_f.assert_called_once_with(
+ **{
+ 'name': fake_tap_flow['name'],
+ 'source_port': fake_tap_flow['source_port'],
+ 'tap_service_id': fake_tap_flow['tap_service_id'],
+ 'direction': fake_tap_flow['direction'],
+ }
+ )
+ self.assertEqual(self.columns, columns)
+ fake_data = _get_data(
+ fake_tap_flow, osc_tap_service._get_columns(fake_tap_flow)[1]
+ )
+ self.assertEqual(fake_data, data)
+
+
+class TestListTapFlow(network_fakes.TestNetworkV2):
+ def setUp(self):
+ super().setUp()
+ self.cmd = osc_tap_flow.ListTapFlow(self.app, None)
+
+ def test_list_tap_flows(self):
+ """Test List Tap Flow."""
+ fake_tap_flows = list(
+ sdk_fakes.generate_fake_resources(_tap_flow.TapFlow, count=2)
+ )
+ self.app.client_manager.network.tap_flows.return_value = fake_tap_flows
+ arg_list = []
+ verify_list = []
+
+ parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
+
+ headers, data = self.cmd.take_action(parsed_args)
+
+ self.app.client_manager.network.tap_flows.assert_called_once()
+ self.assertEqual(headers, list(headers_long))
+ self.assertCountEqual(
+ list(data),
+ [
+ _get_data(fake_tap_flow, columns_long)
+ for fake_tap_flow in fake_tap_flows
+ ],
+ )
+
+
+class TestDeleteTapFlow(network_fakes.TestNetworkV2):
+ def setUp(self):
+ super().setUp()
+ self.app.client_manager.network.find_tap_flow.side_effect = (
+ lambda name_or_id, ignore_missing: _tap_flow.TapFlow(id=name_or_id)
+ )
+ self.cmd = osc_tap_flow.DeleteTapFlow(self.app, None)
+
+ def test_delete_tap_flow(self):
+ """Test Delete tap flow."""
+
+ fake_tap_flow = sdk_fakes.generate_fake_resource(_tap_flow.TapFlow)
+ arg_list = [
+ fake_tap_flow['id'],
+ ]
+ verify_list = [
+ (osc_tap_flow.TAP_FLOW, [fake_tap_flow['id']]),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
+
+ result = self.cmd.take_action(parsed_args)
+
+ mock_delete_tap_flow = self.app.client_manager.network.delete_tap_flow
+ mock_delete_tap_flow.assert_called_once_with(fake_tap_flow['id'])
+ self.assertIsNone(result)
+
+
+class TestShowTapFlow(network_fakes.TestNetworkV2):
+ columns = (
+ 'description',
+ 'direction',
+ 'id',
+ 'name',
+ 'project_id',
+ 'source_port',
+ 'status',
+ 'tap_service_id',
+ )
+
+ def setUp(self):
+ super().setUp()
+ self.app.client_manager.network.find_tap_flow.side_effect = (
+ lambda name_or_id, ignore_missing: _tap_flow.TapFlow(id=name_or_id)
+ )
+ self.cmd = osc_tap_flow.ShowTapFlow(self.app, None)
+
+ def test_show_tap_flow(self):
+ """Test Show tap flow."""
+ fake_tap_flow = sdk_fakes.generate_fake_resource(_tap_flow.TapFlow)
+ self.app.client_manager.network.get_tap_flow.return_value = (
+ fake_tap_flow
+ )
+ arg_list = [
+ fake_tap_flow['id'],
+ ]
+ verify_list = [
+ (osc_tap_flow.TAP_FLOW, fake_tap_flow['id']),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
+
+ headers, data = self.cmd.take_action(parsed_args)
+
+ self.app.client_manager.network.get_tap_flow.assert_called_once_with(
+ fake_tap_flow['id']
+ )
+ self.assertEqual(self.columns, headers)
+ fake_data = _get_data(
+ fake_tap_flow, osc_tap_service._get_columns(fake_tap_flow)[1]
+ )
+ self.assertEqual(fake_data, data)
+
+
+class TestUpdateTapFlow(network_fakes.TestNetworkV2):
+ _new_name = 'new_name'
+
+ # NOTE(mtomaska): The Resource class from which TapFlow inherits from
+ # returns duplicate `ID and `Name` keys.
+ columns = (
+ 'Direction',
+ 'ID',
+ 'ID',
+ 'Name',
+ 'Name',
+ 'Status',
+ 'Tenant',
+ 'description',
+ 'location',
+ 'project_id',
+ 'source_port',
+ 'tap_service_id',
+ )
+
+ def setUp(self):
+ super().setUp()
+ self.cmd = osc_tap_flow.UpdateTapFlow(self.app, None)
+ self.app.client_manager.network.find_tap_flow.side_effect = (
+ lambda name_or_id, ignore_missing: _tap_flow.TapFlow(id=name_or_id)
+ )
+
+ def test_update_tap_flow(self):
+ """Test update tap service"""
+ fake_tap_flow = sdk_fakes.generate_fake_resource(_tap_flow.TapFlow)
+ new_tap_flow = copy.deepcopy(fake_tap_flow)
+ new_tap_flow['name'] = self._new_name
+
+ self.app.client_manager.network.update_tap_flow.return_value = (
+ new_tap_flow
+ )
+
+ arg_list = [
+ fake_tap_flow['id'],
+ '--name',
+ self._new_name,
+ ]
+ verify_list = [('name', self._new_name)]
+
+ parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
+ columns, data = self.cmd.take_action(parsed_args)
+ attrs = {'name': self._new_name}
+
+ mock_update_t_f = self.app.client_manager.network.update_tap_flow
+ mock_update_t_f.assert_called_once_with(new_tap_flow['id'], **attrs)
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(_get_data(new_tap_flow, self.columns), data)
diff --git a/openstackclient/tests/unit/network/v2/taas/test_osc_tap_mirror.py b/openstackclient/tests/unit/network/v2/taas/test_osc_tap_mirror.py
new file mode 100644
index 0000000..10f3251
--- /dev/null
+++ b/openstackclient/tests/unit/network/v2/taas/test_osc_tap_mirror.py
@@ -0,0 +1,288 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import copy
+import operator
+import uuid
+
+from openstack.network.v2 import tap_mirror
+from openstack.test import fakes as sdk_fakes
+from osc_lib import utils as osc_utils
+from osc_lib.utils import columns as column_util
+
+from openstackclient.network.v2.taas import tap_mirror as osc_tap_mirror
+from openstackclient.tests.unit.network.v2 import fakes as network_fakes
+
+
+columns_long = tuple(
+ col
+ for col, _, listing_mode in osc_tap_mirror._attr_map
+ if listing_mode in (column_util.LIST_BOTH, column_util.LIST_LONG_ONLY)
+)
+headers_long = tuple(
+ head
+ for _, head, listing_mode in osc_tap_mirror._attr_map
+ if listing_mode in (column_util.LIST_BOTH, column_util.LIST_LONG_ONLY)
+)
+sorted_attr_map = sorted(osc_tap_mirror._attr_map, key=operator.itemgetter(1))
+sorted_columns = tuple(col for col, _, _ in sorted_attr_map)
+sorted_headers = tuple(head for _, head, _ in sorted_attr_map)
+
+
+def _get_data(attrs, columns=sorted_columns):
+ return osc_utils.get_dict_properties(attrs, columns)
+
+
+class TestCreateTapMirror(network_fakes.TestNetworkV2):
+ columns = (
+ 'description',
+ 'directions',
+ 'id',
+ 'mirror_type',
+ 'name',
+ 'port_id',
+ 'project_id',
+ 'remote_ip',
+ )
+
+ def setUp(self):
+ super().setUp()
+ self.cmd = osc_tap_mirror.CreateTapMirror(self.app, None)
+
+ def test_create_tap_mirror(self):
+ port_id = str(uuid.uuid4())
+ fake_port = network_fakes.create_one_port(attrs={'id': port_id})
+ fake_tap_mirror = sdk_fakes.generate_fake_resource(
+ tap_mirror.TapMirror, **{'port_id': port_id, 'directions': 'IN=99'}
+ )
+ self.app.client_manager.network.create_tap_mirror.return_value = (
+ fake_tap_mirror
+ )
+ self.app.client_manager.network.find_port.return_value = fake_port
+ self.app.client_manager.network.find_tap_mirror.side_effect = (
+ lambda _, name_or_id: {'id': name_or_id}
+ )
+ arg_list = [
+ '--name',
+ fake_tap_mirror['name'],
+ '--port',
+ fake_tap_mirror['port_id'],
+ '--directions',
+ fake_tap_mirror['directions'],
+ '--remote-ip',
+ fake_tap_mirror['remote_ip'],
+ '--mirror-type',
+ fake_tap_mirror['mirror_type'],
+ ]
+
+ verify_directions = fake_tap_mirror['directions'].split('=')
+ verify_directions_dict = {verify_directions[0]: verify_directions[1]}
+
+ verify_list = [
+ ('name', fake_tap_mirror['name']),
+ ('port_id', fake_tap_mirror['port_id']),
+ ('directions', verify_directions_dict),
+ ('remote_ip', fake_tap_mirror['remote_ip']),
+ ('mirror_type', fake_tap_mirror['mirror_type']),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
+ self.app.client_manager.network.find_tap_mirror.return_value = (
+ fake_tap_mirror
+ )
+
+ columns, data = self.cmd.take_action(parsed_args)
+ create_tap_m_mock = self.app.client_manager.network.create_tap_mirror
+ create_tap_m_mock.assert_called_once_with(
+ **{
+ 'name': fake_tap_mirror['name'],
+ 'port_id': fake_tap_mirror['port_id'],
+ 'directions': verify_directions_dict,
+ 'remote_ip': fake_tap_mirror['remote_ip'],
+ 'mirror_type': fake_tap_mirror['mirror_type'],
+ }
+ )
+ self.assertEqual(self.columns, columns)
+ fake_data = _get_data(
+ fake_tap_mirror, osc_tap_mirror._get_columns(fake_tap_mirror)[1]
+ )
+ self.assertEqual(fake_data, data)
+
+
+class TestListTapMirror(network_fakes.TestNetworkV2):
+ def setUp(self):
+ super().setUp()
+ self.cmd = osc_tap_mirror.ListTapMirror(self.app, None)
+
+ def test_list_tap_mirror(self):
+ """Test List Tap Mirror."""
+ fake_tap_mirrors = list(
+ sdk_fakes.generate_fake_resources(tap_mirror.TapMirror, count=4)
+ )
+ self.app.client_manager.network.tap_mirrors.return_value = (
+ fake_tap_mirrors
+ )
+
+ arg_list = []
+ verify_list = []
+
+ parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
+
+ headers, data = self.cmd.take_action(parsed_args)
+
+ self.app.client_manager.network.tap_mirrors.assert_called_once()
+ self.assertEqual(headers, list(headers_long))
+ self.assertCountEqual(
+ list(data),
+ [
+ _get_data(fake_tap_mirror, columns_long)
+ for fake_tap_mirror in fake_tap_mirrors
+ ],
+ )
+
+
+class TestDeleteTapMirror(network_fakes.TestNetworkV2):
+ def setUp(self):
+ super().setUp()
+ self.app.client_manager.network.find_tap_mirror.side_effect = (
+ lambda name_or_id, ignore_missing: tap_mirror.TapMirror(
+ id=name_or_id
+ )
+ )
+ self.cmd = osc_tap_mirror.DeleteTapMirror(self.app, None)
+
+ def test_delete_tap_mirror(self):
+ """Test Delete Tap Mirror."""
+
+ fake_tap_mirror = sdk_fakes.generate_fake_resource(
+ tap_mirror.TapMirror
+ )
+
+ arg_list = [
+ fake_tap_mirror['id'],
+ ]
+ verify_list = [
+ (osc_tap_mirror.TAP_MIRROR, [fake_tap_mirror['id']]),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
+ result = self.cmd.take_action(parsed_args)
+
+ mock_delete_tap_m = self.app.client_manager.network.delete_tap_mirror
+ mock_delete_tap_m.assert_called_once_with(fake_tap_mirror['id'])
+ self.assertIsNone(result)
+
+
+class TestShowTapMirror(network_fakes.TestNetworkV2):
+ columns = (
+ 'description',
+ 'directions',
+ 'id',
+ 'mirror_type',
+ 'name',
+ 'port_id',
+ 'project_id',
+ 'remote_ip',
+ )
+
+ def setUp(self):
+ super().setUp()
+ self.app.client_manager.network.find_tap_mirror.side_effect = (
+ lambda name_or_id, ignore_missing: tap_mirror.TapMirror(
+ id=name_or_id
+ )
+ )
+ self.cmd = osc_tap_mirror.ShowTapMirror(self.app, None)
+
+ def test_show_tap_mirror(self):
+ """Test Show Tap Mirror."""
+
+ fake_tap_mirror = sdk_fakes.generate_fake_resource(
+ tap_mirror.TapMirror
+ )
+ self.app.client_manager.network.get_tap_mirror.return_value = (
+ fake_tap_mirror
+ )
+ arg_list = [
+ fake_tap_mirror['id'],
+ ]
+ verify_list = [
+ (osc_tap_mirror.TAP_MIRROR, fake_tap_mirror['id']),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
+
+ headers, data = self.cmd.take_action(parsed_args)
+
+ mock_get_tap_m = self.app.client_manager.network.get_tap_mirror
+ mock_get_tap_m.assert_called_once_with(fake_tap_mirror['id'])
+ self.assertEqual(self.columns, headers)
+ fake_data = _get_data(
+ fake_tap_mirror, osc_tap_mirror._get_columns(fake_tap_mirror)[1]
+ )
+ self.assertEqual(fake_data, data)
+
+
+class TestUpdateTapMirror(network_fakes.TestNetworkV2):
+ _new_name = 'new_name'
+ columns = (
+ 'description',
+ 'directions',
+ 'id',
+ 'mirror_type',
+ 'name',
+ 'port_id',
+ 'project_id',
+ 'remote_ip',
+ )
+
+ def setUp(self):
+ super().setUp()
+ self.cmd = osc_tap_mirror.UpdateTapMirror(self.app, None)
+ self.app.client_manager.network.find_tap_mirror.side_effect = (
+ lambda name_or_id, ignore_missing: tap_mirror.TapMirror(
+ id=name_or_id
+ )
+ )
+
+ def test_update_tap_mirror(self):
+ """Test update Tap Mirror"""
+ fake_tap_mirror = sdk_fakes.generate_fake_resource(
+ tap_mirror.TapMirror
+ )
+ new_tap_mirror = copy.deepcopy(fake_tap_mirror)
+ new_tap_mirror['name'] = self._new_name
+
+ self.app.client_manager.network.update_tap_mirror.return_value = (
+ new_tap_mirror
+ )
+
+ arg_list = [
+ fake_tap_mirror['id'],
+ '--name',
+ self._new_name,
+ ]
+ verify_list = [('name', self._new_name)]
+
+ parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
+ columns, data = self.cmd.take_action(parsed_args)
+ attrs = {'name': self._new_name}
+
+ mock_update_tap_m = self.app.client_manager.network.update_tap_mirror
+ mock_update_tap_m.assert_called_once_with(
+ fake_tap_mirror['id'], **attrs
+ )
+ self.assertEqual(self.columns, columns)
+ fake_data = _get_data(
+ new_tap_mirror, osc_tap_mirror._get_columns(new_tap_mirror)[1]
+ )
+ self.assertEqual(fake_data, data)
diff --git a/openstackclient/tests/unit/network/v2/taas/test_osc_tap_service.py b/openstackclient/tests/unit/network/v2/taas/test_osc_tap_service.py
new file mode 100644
index 0000000..fa76689
--- /dev/null
+++ b/openstackclient/tests/unit/network/v2/taas/test_osc_tap_service.py
@@ -0,0 +1,271 @@
+# All Rights Reserved 2020
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import copy
+import operator
+import uuid
+
+from openstack.network.v2 import tap_service
+from openstack.test import fakes as sdk_fakes
+from osc_lib import utils as osc_utils
+from osc_lib.utils import columns as column_util
+
+from openstackclient.network.v2.taas import tap_service as osc_tap_service
+from openstackclient.tests.unit.network.v2 import fakes as network_fakes
+
+
+columns_long = tuple(
+ col
+ for col, _, listing_mode in osc_tap_service._attr_map
+ if listing_mode in (column_util.LIST_BOTH, column_util.LIST_LONG_ONLY)
+)
+headers_long = tuple(
+ head
+ for _, head, listing_mode in osc_tap_service._attr_map
+ if listing_mode in (column_util.LIST_BOTH, column_util.LIST_LONG_ONLY)
+)
+sorted_attr_map = sorted(osc_tap_service._attr_map, key=operator.itemgetter(1))
+sorted_columns = tuple(col for col, _, _ in sorted_attr_map)
+sorted_headers = tuple(head for _, head, _ in sorted_attr_map)
+
+
+def _get_data(attrs, columns=sorted_columns):
+ return osc_utils.get_dict_properties(attrs, columns)
+
+
+class TestCreateTapService(network_fakes.TestNetworkV2):
+ columns = (
+ 'description',
+ 'id',
+ 'name',
+ 'port_id',
+ 'project_id',
+ 'status',
+ )
+
+ def setUp(self):
+ super().setUp()
+ self.cmd = osc_tap_service.CreateTapService(self.app, None)
+
+ def test_create_tap_service(self):
+ """Test Create Tap Service."""
+ port_id = str(uuid.uuid4())
+ fake_port = network_fakes.create_one_port(attrs={'id': port_id})
+ fake_tap_service = sdk_fakes.generate_fake_resource(
+ tap_service.TapService, **{'port_id': port_id}
+ )
+ self.app.client_manager.network.create_tap_service.return_value = (
+ fake_tap_service
+ )
+ self.app.client_manager.network.find_port.return_value = fake_port
+ self.app.client_manager.network.find_tap_service.side_effect = (
+ lambda _, name_or_id: {'id': name_or_id}
+ )
+ arg_list = [
+ '--name',
+ fake_tap_service['name'],
+ '--port',
+ fake_tap_service['port_id'],
+ ]
+
+ verify_list = [
+ ('name', fake_tap_service['name']),
+ ('port_id', fake_tap_service['port_id']),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
+ self.app.client_manager.network.find_tap_service.return_value = (
+ fake_tap_service
+ )
+
+ columns, data = self.cmd.take_action(parsed_args)
+ create_tap_s_mock = self.app.client_manager.network.create_tap_service
+ create_tap_s_mock.assert_called_once_with(
+ **{
+ 'name': fake_tap_service['name'],
+ 'port_id': fake_tap_service['port_id'],
+ }
+ )
+ self.assertEqual(self.columns, columns)
+ fake_data = _get_data(
+ fake_tap_service, osc_tap_service._get_columns(fake_tap_service)[1]
+ )
+ self.assertEqual(fake_data, data)
+
+
+class TestListTapService(network_fakes.TestNetworkV2):
+ def setUp(self):
+ super().setUp()
+ self.cmd = osc_tap_service.ListTapService(self.app, None)
+
+ def test_list_tap_service(self):
+ """Test List Tap Service."""
+ fake_tap_services = list(
+ sdk_fakes.generate_fake_resources(tap_service.TapService, count=4)
+ )
+ self.app.client_manager.network.tap_services.return_value = (
+ fake_tap_services
+ )
+
+ arg_list = []
+ verify_list = []
+
+ parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
+
+ headers, data = self.cmd.take_action(parsed_args)
+
+ self.app.client_manager.network.tap_services.assert_called_once()
+ self.assertEqual(headers, list(headers_long))
+ self.assertCountEqual(
+ list(data),
+ [
+ _get_data(fake_tap_service, columns_long)
+ for fake_tap_service in fake_tap_services
+ ],
+ )
+
+
+class TestDeleteTapService(network_fakes.TestNetworkV2):
+ def setUp(self):
+ super().setUp()
+ self.app.client_manager.network.find_tap_service.side_effect = (
+ lambda name_or_id, ignore_missing: tap_service.TapService(
+ id=name_or_id
+ )
+ )
+ self.cmd = osc_tap_service.DeleteTapService(self.app, None)
+
+ def test_delete_tap_service(self):
+ """Test Delete tap service."""
+
+ fake_tap_service = sdk_fakes.generate_fake_resource(
+ tap_service.TapService
+ )
+
+ arg_list = [
+ fake_tap_service['id'],
+ ]
+ verify_list = [
+ (osc_tap_service.TAP_SERVICE, [fake_tap_service['id']]),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
+ result = self.cmd.take_action(parsed_args)
+
+ mock_delete_tap_s = self.app.client_manager.network.delete_tap_service
+ mock_delete_tap_s.assert_called_once_with(fake_tap_service['id'])
+ self.assertIsNone(result)
+
+
+class TestShowTapService(network_fakes.TestNetworkV2):
+ columns = (
+ 'description',
+ 'id',
+ 'name',
+ 'port_id',
+ 'project_id',
+ 'status',
+ )
+
+ def setUp(self):
+ super().setUp()
+ self.app.client_manager.network.find_tap_service.side_effect = (
+ lambda name_or_id, ignore_missing: tap_service.TapService(
+ id=name_or_id
+ )
+ )
+ self.cmd = osc_tap_service.ShowTapService(self.app, None)
+
+ def test_show_tap_service(self):
+ """Test Show tap service."""
+
+ fake_tap_service = sdk_fakes.generate_fake_resource(
+ tap_service.TapService
+ )
+ self.app.client_manager.network.get_tap_service.return_value = (
+ fake_tap_service
+ )
+ arg_list = [
+ fake_tap_service['id'],
+ ]
+ verify_list = [
+ (osc_tap_service.TAP_SERVICE, fake_tap_service['id']),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
+
+ headers, data = self.cmd.take_action(parsed_args)
+
+ mock_get_tap_s = self.app.client_manager.network.get_tap_service
+ mock_get_tap_s.assert_called_once_with(fake_tap_service['id'])
+ self.assertEqual(self.columns, headers)
+ fake_data = _get_data(
+ fake_tap_service, osc_tap_service._get_columns(fake_tap_service)[1]
+ )
+ self.assertEqual(fake_data, data)
+
+
+class TestUpdateTapService(network_fakes.TestNetworkV2):
+ _new_name = 'new_name'
+
+ columns = (
+ 'description',
+ 'id',
+ 'name',
+ 'port_id',
+ 'project_id',
+ 'status',
+ )
+
+ def setUp(self):
+ super().setUp()
+ self.cmd = osc_tap_service.UpdateTapService(self.app, None)
+ self.app.client_manager.network.find_tap_service.side_effect = (
+ lambda name_or_id, ignore_missing: tap_service.TapService(
+ id=name_or_id
+ )
+ )
+
+ def test_update_tap_service(self):
+ """Test update tap service"""
+ fake_tap_service = sdk_fakes.generate_fake_resource(
+ tap_service.TapService
+ )
+ new_tap_service = copy.deepcopy(fake_tap_service)
+ new_tap_service['name'] = self._new_name
+
+ self.app.client_manager.network.update_tap_service.return_value = (
+ new_tap_service
+ )
+
+ arg_list = [
+ fake_tap_service['id'],
+ '--name',
+ self._new_name,
+ ]
+ verify_list = [('name', self._new_name)]
+
+ parsed_args = self.check_parser(self.cmd, arg_list, verify_list)
+ columns, data = self.cmd.take_action(parsed_args)
+ attrs = {'name': self._new_name}
+
+ mock_update_tap_s = self.app.client_manager.network.update_tap_service
+ mock_update_tap_s.assert_called_once_with(
+ fake_tap_service['id'], **attrs
+ )
+ self.assertEqual(self.columns, columns)
+ fake_data = _get_data(
+ new_tap_service, osc_tap_service._get_columns(new_tap_service)[1]
+ )
+ self.assertEqual(fake_data, data)
diff --git a/openstackclient/tests/unit/network/v2/test_address_group.py b/openstackclient/tests/unit/network/v2/test_address_group.py
index 411d199..48f7066 100644
--- a/openstackclient/tests/unit/network/v2/test_address_group.py
+++ b/openstackclient/tests/unit/network/v2/test_address_group.py
@@ -11,7 +11,6 @@
# under the License.
#
-from unittest import mock
from unittest.mock import call
from osc_lib import exceptions
@@ -58,8 +57,8 @@ class TestCreateAddressGroup(TestAddressGroup):
def setUp(self):
super().setUp()
- self.network_client.create_address_group = mock.Mock(
- return_value=self.new_address_group
+ self.network_client.create_address_group.return_value = (
+ self.new_address_group
)
# Get the command object to test
@@ -145,7 +144,7 @@ class TestDeleteAddressGroup(TestAddressGroup):
def setUp(self):
super().setUp()
- self.network_client.delete_address_group = mock.Mock(return_value=None)
+ self.network_client.delete_address_group.return_value = None
self.network_client.find_address_group = (
network_fakes.get_address_groups(
address_groups=self._address_groups
@@ -206,9 +205,7 @@ class TestDeleteAddressGroup(TestAddressGroup):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
find_mock_result = [self._address_groups[0], exceptions.CommandError]
- self.network_client.find_address_group = mock.Mock(
- side_effect=find_mock_result
- )
+ self.network_client.find_address_group.side_effect = find_mock_result
try:
self.cmd.take_action(parsed_args)
@@ -251,9 +248,7 @@ class TestListAddressGroup(TestAddressGroup):
def setUp(self):
super().setUp()
- self.network_client.address_groups = mock.Mock(
- return_value=self.address_groups
- )
+ self.network_client.address_groups.return_value = self.address_groups
# Get the command object to test
self.cmd = address_group.ListAddressGroup(self.app, None)
@@ -333,13 +328,15 @@ class TestSetAddressGroup(TestAddressGroup):
def setUp(self):
super().setUp()
- self.network_client.update_address_group = mock.Mock(return_value=None)
- self.network_client.find_address_group = mock.Mock(
- return_value=self._address_group
+ self.network_client.update_address_group.return_value = None
+ self.network_client.find_address_group.return_value = (
+ self._address_group
)
- self.network_client.add_addresses_to_address_group = mock.Mock(
- return_value=self._address_group
+
+ self.network_client.add_addresses_to_address_group.return_value = (
+ self._address_group
)
+
# Get the command object to test
self.cmd = address_group.SetAddressGroup(self.app, None)
@@ -442,8 +439,8 @@ class TestShowAddressGroup(TestAddressGroup):
def setUp(self):
super().setUp()
- self.network_client.find_address_group = mock.Mock(
- return_value=self._address_group
+ self.network_client.find_address_group.return_value = (
+ self._address_group
)
# Get the command object to test
@@ -486,12 +483,12 @@ class TestUnsetAddressGroup(TestAddressGroup):
def setUp(self):
super().setUp()
- self.network_client.find_address_group = mock.Mock(
- return_value=self._address_group
- )
- self.network_client.remove_addresses_from_address_group = mock.Mock(
- return_value=self._address_group
+ self.network_client.find_address_group.return_value = (
+ self._address_group
)
+
+ self.network_client.remove_addresses_from_address_group.return_value = self._address_group
+
# Get the command object to test
self.cmd = address_group.UnsetAddressGroup(self.app, None)
diff --git a/openstackclient/tests/unit/network/v2/test_address_scope.py b/openstackclient/tests/unit/network/v2/test_address_scope.py
index c3eb83d..6e2c05e 100644
--- a/openstackclient/tests/unit/network/v2/test_address_scope.py
+++ b/openstackclient/tests/unit/network/v2/test_address_scope.py
@@ -11,7 +11,6 @@
# under the License.
#
-from unittest import mock
from unittest.mock import call
from osc_lib import exceptions
@@ -52,8 +51,8 @@ class TestCreateAddressScope(TestAddressScope):
def setUp(self):
super().setUp()
- self.network_client.create_address_scope = mock.Mock(
- return_value=self.new_address_scope
+ self.network_client.create_address_scope.return_value = (
+ self.new_address_scope
)
# Get the command object to test
@@ -160,7 +159,7 @@ class TestDeleteAddressScope(TestAddressScope):
def setUp(self):
super().setUp()
- self.network_client.delete_address_scope = mock.Mock(return_value=None)
+ self.network_client.delete_address_scope.return_value = None
self.network_client.find_address_scope = (
network_fakes.get_address_scopes(
address_scopes=self._address_scopes
@@ -222,9 +221,7 @@ class TestDeleteAddressScope(TestAddressScope):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
find_mock_result = [self._address_scopes[0], exceptions.CommandError]
- self.network_client.find_address_scope = mock.Mock(
- side_effect=find_mock_result
- )
+ self.network_client.find_address_scope.side_effect = find_mock_result
try:
self.cmd.take_action(parsed_args)
@@ -267,9 +264,7 @@ class TestListAddressScope(TestAddressScope):
def setUp(self):
super().setUp()
- self.network_client.address_scopes = mock.Mock(
- return_value=self.address_scopes
- )
+ self.network_client.address_scopes.return_value = self.address_scopes
# Get the command object to test
self.cmd = address_scope.ListAddressScope(self.app, None)
@@ -398,9 +393,9 @@ class TestSetAddressScope(TestAddressScope):
def setUp(self):
super().setUp()
- self.network_client.update_address_scope = mock.Mock(return_value=None)
- self.network_client.find_address_scope = mock.Mock(
- return_value=self._address_scope
+ self.network_client.update_address_scope.return_value = None
+ self.network_client.find_address_scope.return_value = (
+ self._address_scope
)
# Get the command object to test
@@ -488,8 +483,8 @@ class TestShowAddressScope(TestAddressScope):
def setUp(self):
super().setUp()
- self.network_client.find_address_scope = mock.Mock(
- return_value=self._address_scope
+ self.network_client.find_address_scope.return_value = (
+ self._address_scope
)
# Get the command object to test
diff --git a/openstackclient/tests/unit/network/v2/test_default_security_group_rule.py b/openstackclient/tests/unit/network/v2/test_default_security_group_rule.py
index 9b46126..c44e553 100644
--- a/openstackclient/tests/unit/network/v2/test_default_security_group_rule.py
+++ b/openstackclient/tests/unit/network/v2/test_default_security_group_rule.py
@@ -11,11 +11,9 @@
# under the License.
#
-from unittest import mock
from unittest.mock import call
import uuid
-from openstack.network.v2 import _proxy
from openstack.network.v2 import (
default_security_group_rule as _default_security_group_rule,
)
@@ -28,18 +26,7 @@ from openstackclient.tests.unit.network.v2 import fakes as network_fakes
from openstackclient.tests.unit import utils as tests_utils
-class TestDefaultSecurityGroupRule(network_fakes.TestNetworkV2):
- def setUp(self):
- super().setUp()
-
- self.app.client_manager.sdk_connection = mock.Mock()
- self.app.client_manager.sdk_connection.network = mock.Mock(
- spec=_proxy.Proxy,
- )
- self.sdk_client = self.app.client_manager.sdk_connection.network
-
-
-class TestCreateDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
+class TestCreateDefaultSecurityGroupRule(network_fakes.TestNetworkV2):
expected_columns = (
'description',
'direction',
@@ -82,7 +69,7 @@ class TestCreateDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
**default_security_group_rule_attrs,
)
- self.sdk_client.create_default_security_group_rule.return_value = (
+ self.network_client.create_default_security_group_rule.return_value = (
self._default_sg_rule
)
self.expected_data = (
@@ -208,7 +195,7 @@ class TestCreateDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
columns, data = self.cmd.take_action(parsed_args)
- self.sdk_client.create_default_security_group_rule.assert_called_once_with(
+ self.network_client.create_default_security_group_rule.assert_called_once_with(
**{
'direction': self._default_sg_rule.direction,
'ethertype': self._default_sg_rule.ether_type,
@@ -252,7 +239,7 @@ class TestCreateDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
columns, data = self.cmd.take_action(parsed_args)
- self.sdk_client.create_default_security_group_rule.assert_called_once_with(
+ self.network_client.create_default_security_group_rule.assert_called_once_with(
**{
'direction': self._default_sg_rule.direction,
'ethertype': self._default_sg_rule.ether_type,
@@ -302,7 +289,7 @@ class TestCreateDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
columns, data = self.cmd.take_action(parsed_args)
- self.sdk_client.create_default_security_group_rule.assert_called_once_with(
+ self.network_client.create_default_security_group_rule.assert_called_once_with(
**{
'direction': self._default_sg_rule.direction,
'ethertype': self._default_sg_rule.ether_type,
@@ -347,7 +334,7 @@ class TestCreateDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
columns, data = self.cmd.take_action(parsed_args)
- self.sdk_client.create_default_security_group_rule.assert_called_once_with(
+ self.network_client.create_default_security_group_rule.assert_called_once_with(
**{
'direction': self._default_sg_rule.direction,
'ethertype': self._default_sg_rule.ether_type,
@@ -381,7 +368,7 @@ class TestCreateDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
columns, data = self.cmd.take_action(parsed_args)
- self.sdk_client.create_default_security_group_rule.assert_called_once_with(
+ self.network_client.create_default_security_group_rule.assert_called_once_with(
**{
'direction': self._default_sg_rule.direction,
'ethertype': self._default_sg_rule.ether_type,
@@ -415,7 +402,7 @@ class TestCreateDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
columns, data = self.cmd.take_action(parsed_args)
- self.sdk_client.create_default_security_group_rule.assert_called_once_with(
+ self.network_client.create_default_security_group_rule.assert_called_once_with(
**{
'direction': self._default_sg_rule.direction,
'ethertype': self._default_sg_rule.ether_type,
@@ -449,7 +436,7 @@ class TestCreateDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
columns, data = self.cmd.take_action(parsed_args)
- self.sdk_client.create_default_security_group_rule.assert_called_once_with(
+ self.network_client.create_default_security_group_rule.assert_called_once_with(
**{
'direction': self._default_sg_rule.direction,
'ethertype': self._default_sg_rule.ether_type,
@@ -599,7 +586,7 @@ class TestCreateDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
columns, data = self.cmd.take_action(parsed_args)
- self.sdk_client.create_default_security_group_rule.assert_called_once_with(
+ self.network_client.create_default_security_group_rule.assert_called_once_with(
**{
'direction': self._default_sg_rule.direction,
'ethertype': self._default_sg_rule.ether_type,
@@ -637,7 +624,7 @@ class TestCreateDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
columns, data = self.cmd.take_action(parsed_args)
- self.sdk_client.create_default_security_group_rule.assert_called_once_with(
+ self.network_client.create_default_security_group_rule.assert_called_once_with(
**{
'direction': self._default_sg_rule.direction,
'ethertype': self._default_sg_rule.ether_type,
@@ -675,7 +662,7 @@ class TestCreateDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
columns, data = self.cmd.take_action(parsed_args)
- self.sdk_client.create_default_security_group_rule.assert_called_once_with(
+ self.network_client.create_default_security_group_rule.assert_called_once_with(
**{
'direction': self._default_sg_rule.direction,
'ethertype': self._default_sg_rule.ether_type,
@@ -713,7 +700,7 @@ class TestCreateDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
columns, data = self.cmd.take_action(parsed_args)
- self.sdk_client.create_default_security_group_rule.assert_called_once_with(
+ self.network_client.create_default_security_group_rule.assert_called_once_with(
**{
'direction': self._default_sg_rule.direction,
'ethertype': self._default_sg_rule.ether_type,
@@ -754,7 +741,7 @@ class TestCreateDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
columns, data = self.cmd.take_action(parsed_args)
- self.sdk_client.create_default_security_group_rule.assert_called_once_with(
+ self.network_client.create_default_security_group_rule.assert_called_once_with(
**{
'direction': self._default_sg_rule.direction,
'ethertype': self._default_sg_rule.ether_type,
@@ -794,7 +781,7 @@ class TestCreateDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
columns, data = self.cmd.take_action(parsed_args)
- self.sdk_client.create_default_security_group_rule.assert_called_once_with(
+ self.network_client.create_default_security_group_rule.assert_called_once_with(
**{
'direction': self._default_sg_rule.direction,
'ethertype': self._default_sg_rule.ether_type,
@@ -825,7 +812,7 @@ class TestCreateDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
columns, data = self.cmd.take_action(parsed_args)
- self.sdk_client.create_default_security_group_rule.assert_called_once_with(
+ self.network_client.create_default_security_group_rule.assert_called_once_with(
**{
'description': self._default_sg_rule.description,
'direction': self._default_sg_rule.direction,
@@ -840,7 +827,7 @@ class TestCreateDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
self.assertEqual(self.expected_data, data)
-class TestDeleteDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
+class TestDeleteDefaultSecurityGroupRule(network_fakes.TestNetworkV2):
# The default security group rules to be deleted.
default_security_group_rule_attrs = {
'direction': 'ingress',
@@ -866,7 +853,9 @@ class TestDeleteDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
def setUp(self):
super().setUp()
- self.sdk_client.delete_default_security_group_rule.return_value = None
+ self.network_client.delete_default_security_group_rule.return_value = (
+ None
+ )
# Get the command object to test
self.cmd = default_security_group_rule.DeleteDefaultSecurityGroupRule(
@@ -880,7 +869,7 @@ class TestDeleteDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
verifylist = [
('rule', [self._default_sg_rules[0].id]),
]
- self.sdk_client.find_default_security_group_rule.return_value = (
+ self.network_client.find_default_security_group_rule.return_value = (
self._default_sg_rules[0]
)
@@ -888,7 +877,7 @@ class TestDeleteDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
result = self.cmd.take_action(parsed_args)
- self.sdk_client.delete_default_security_group_rule.assert_called_once_with(
+ self.network_client.delete_default_security_group_rule.assert_called_once_with(
self._default_sg_rules[0]
)
self.assertIsNone(result)
@@ -902,7 +891,7 @@ class TestDeleteDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
verifylist = [
('rule', arglist),
]
- self.sdk_client.find_default_security_group_rule.side_effect = (
+ self.network_client.find_default_security_group_rule.side_effect = (
self._default_sg_rules
)
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -912,7 +901,7 @@ class TestDeleteDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
calls = []
for s in self._default_sg_rules:
calls.append(call(s))
- self.sdk_client.delete_default_security_group_rule.assert_has_calls(
+ self.network_client.delete_default_security_group_rule.assert_has_calls(
calls
)
self.assertIsNone(result)
@@ -931,8 +920,8 @@ class TestDeleteDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
self._default_sg_rules[0],
exceptions.CommandError,
]
- self.sdk_client.find_default_security_group_rule = mock.Mock(
- side_effect=find_mock_result
+ self.network_client.find_default_security_group_rule.side_effect = (
+ find_mock_result
)
try:
@@ -941,18 +930,18 @@ class TestDeleteDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
except exceptions.CommandError as e:
self.assertEqual('1 of 2 default rules failed to delete.', str(e))
- self.sdk_client.find_default_security_group_rule.assert_any_call(
+ self.network_client.find_default_security_group_rule.assert_any_call(
self._default_sg_rules[0].id, ignore_missing=False
)
- self.sdk_client.find_default_security_group_rule.assert_any_call(
+ self.network_client.find_default_security_group_rule.assert_any_call(
'unexist_rule', ignore_missing=False
)
- self.sdk_client.delete_default_security_group_rule.assert_called_once_with(
+ self.network_client.delete_default_security_group_rule.assert_called_once_with(
self._default_sg_rules[0]
)
-class TestListDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
+class TestListDefaultSecurityGroupRule(network_fakes.TestNetworkV2):
# The security group rule to be listed.
_default_sg_rule_tcp = sdk_fakes.generate_fake_resource(
_default_security_group_rule.DefaultSecurityGroupRule,
@@ -1001,7 +990,7 @@ class TestListDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
def setUp(self):
super().setUp()
- self.sdk_client.default_security_group_rules.return_value = (
+ self.network_client.default_security_group_rules.return_value = (
self._default_sg_rules
)
@@ -1016,7 +1005,7 @@ class TestListDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
columns, data = self.cmd.take_action(parsed_args)
- self.sdk_client.default_security_group_rules.assert_called_once_with(
+ self.network_client.default_security_group_rules.assert_called_once_with(
**{}
)
self.assertEqual(self.expected_columns, columns)
@@ -1035,7 +1024,7 @@ class TestListDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
columns, data = self.cmd.take_action(parsed_args)
- self.sdk_client.default_security_group_rules.assert_called_once_with(
+ self.network_client.default_security_group_rules.assert_called_once_with(
**{
'protocol': 'tcp',
}
@@ -1055,7 +1044,7 @@ class TestListDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
columns, data = self.cmd.take_action(parsed_args)
- self.sdk_client.default_security_group_rules.assert_called_once_with(
+ self.network_client.default_security_group_rules.assert_called_once_with(
**{
'direction': 'ingress',
}
@@ -1075,7 +1064,7 @@ class TestListDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
columns, data = self.cmd.take_action(parsed_args)
- self.sdk_client.default_security_group_rules.assert_called_once_with(
+ self.network_client.default_security_group_rules.assert_called_once_with(
**{
'direction': 'egress',
}
@@ -1084,7 +1073,7 @@ class TestListDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
self.assertEqual(self.expected_data, list(data))
-class TestShowDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
+class TestShowDefaultSecurityGroupRule(network_fakes.TestNetworkV2):
# The default security group rule to be shown.
_default_sg_rule = sdk_fakes.generate_fake_resource(
_default_security_group_rule.DefaultSecurityGroupRule
@@ -1123,7 +1112,7 @@ class TestShowDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
def setUp(self):
super().setUp()
- self.sdk_client.find_default_security_group_rule.return_value = (
+ self.network_client.find_default_security_group_rule.return_value = (
self._default_sg_rule
)
@@ -1148,7 +1137,7 @@ class TestShowDefaultSecurityGroupRule(TestDefaultSecurityGroupRule):
columns, data = self.cmd.take_action(parsed_args)
- self.sdk_client.find_default_security_group_rule.assert_called_once_with(
+ self.network_client.find_default_security_group_rule.assert_called_once_with(
self._default_sg_rule.id, ignore_missing=False
)
self.assertEqual(self.columns, columns)
diff --git a/openstackclient/tests/unit/network/v2/test_floating_ip_network.py b/openstackclient/tests/unit/network/v2/test_floating_ip_network.py
index 605f4d9..ab0ec17 100644
--- a/openstackclient/tests/unit/network/v2/test_floating_ip_network.py
+++ b/openstackclient/tests/unit/network/v2/test_floating_ip_network.py
@@ -11,7 +11,6 @@
# under the License.
#
-from unittest import mock
from unittest.mock import call
from openstack.network.v2 import floating_ip as _floating_ip
@@ -86,16 +85,14 @@ class TestCreateFloatingIPNetwork(TestFloatingIPNetwork):
def setUp(self):
super().setUp()
- self.network_client.create_ip = mock.Mock(
- return_value=self.floating_ip
- )
- self.network_client.set_tags = mock.Mock(return_value=None)
+ self.network_client.create_ip.return_value = self.floating_ip
- self.network_client.find_network = mock.Mock(
- return_value=self.floating_network
- )
- self.network_client.find_subnet = mock.Mock(return_value=self.subnet)
- self.network_client.find_port = mock.Mock(return_value=self.port)
+ self.network_client.set_tags.return_value = None
+
+ self.network_client.find_network.return_value = self.floating_network
+
+ self.network_client.find_subnet.return_value = self.subnet
+ self.network_client.find_port.return_value = self.port
# Get the command object to test
self.cmd = fip.CreateFloatingIP(self.app, None)
@@ -304,7 +301,7 @@ class TestDeleteFloatingIPNetwork(TestFloatingIPNetwork):
def setUp(self):
super().setUp()
- self.network_client.delete_ip = mock.Mock(return_value=None)
+ self.network_client.delete_ip.return_value = None
# Get the command object to test
self.cmd = fip.DeleteFloatingIP(self.app, None)
@@ -470,14 +467,11 @@ class TestListFloatingIPNetwork(TestFloatingIPNetwork):
def setUp(self):
super().setUp()
- self.network_client.ips = mock.Mock(return_value=self.floating_ips)
- self.network_client.find_network = mock.Mock(
- return_value=self.fake_network
- )
- self.network_client.find_port = mock.Mock(return_value=self.fake_port)
- self.network_client.find_router = mock.Mock(
- return_value=self.fake_router
- )
+ self.network_client.ips.return_value = self.floating_ips
+ self.network_client.find_network.return_value = self.fake_network
+
+ self.network_client.find_port.return_value = self.fake_port
+ self.network_client.find_router.return_value = self.fake_router
# Get the command object to test
self.cmd = fip.ListFloatingIP(self.app, None)
@@ -713,7 +707,7 @@ class TestShowFloatingIPNetwork(TestFloatingIPNetwork):
self.floating_ip = sdk_fakes.generate_fake_resource(
_floating_ip.FloatingIP
)
- self.network_client.find_ip = mock.Mock(return_value=self.floating_ip)
+ self.network_client.find_ip.return_value = self.floating_ip
self.columns = (
'created_at',
@@ -797,10 +791,10 @@ class TestSetFloatingIP(TestFloatingIPNetwork):
def setUp(self):
super().setUp()
- self.network_client.find_ip = mock.Mock(return_value=self.floating_ip)
- self.network_client.find_port = mock.Mock(return_value=self.port)
- self.network_client.update_ip = mock.Mock(return_value=None)
- self.network_client.set_tags = mock.Mock(return_value=None)
+ self.network_client.find_ip.return_value = self.floating_ip
+ self.network_client.find_port.return_value = self.port
+ self.network_client.update_ip.return_value = None
+ self.network_client.set_tags.return_value = None
# Get the command object to test
self.cmd = fip.SetFloatingIP(self.app, None)
@@ -1044,9 +1038,9 @@ class TestUnsetFloatingIP(TestFloatingIPNetwork):
def setUp(self):
super().setUp()
- self.network_client.find_ip = mock.Mock(return_value=self.floating_ip)
- self.network_client.update_ip = mock.Mock(return_value=None)
- self.network_client.set_tags = mock.Mock(return_value=None)
+ self.network_client.find_ip.return_value = self.floating_ip
+ self.network_client.update_ip.return_value = None
+ self.network_client.set_tags.return_value = None
# Get the command object to test
self.cmd = fip.UnsetFloatingIP(self.app, None)
diff --git a/openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py b/openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py
index 2e4c93f..33b9011 100644
--- a/openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py
+++ b/openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py
@@ -33,7 +33,7 @@ class TestFloatingIPPortForwarding(network_fakes.TestNetworkV2):
)
self.port = network_fakes.create_one_port()
self.project = identity_fakes_v2.FakeProject.create_one_project()
- self.network_client.find_port = mock.Mock(return_value=self.port)
+ self.network_client.find_port.return_value = self.port
class TestCreateFloatingIPPortForwarding(TestFloatingIPPortForwarding):
@@ -54,11 +54,11 @@ class TestCreateFloatingIPPortForwarding(TestFloatingIPPortForwarding):
},
)
- self.network_client.create_floating_ip_port_forwarding = mock.Mock(
- return_value=self.new_port_forwarding
+ self.network_client.create_floating_ip_port_forwarding.return_value = (
+ self.new_port_forwarding
)
- self.network_client.find_ip = mock.Mock(return_value=self.floating_ip)
+ self.network_client.find_ip.return_value = self.floating_ip
# Get the command object to test
self.cmd = floating_ip_port_forwarding.CreateFloatingIPPortForwarding(
@@ -351,11 +351,11 @@ class TestDeleteFloatingIPPortForwarding(TestFloatingIPPortForwarding):
},
)
)
- self.network_client.delete_floating_ip_port_forwarding = mock.Mock(
- return_value=None
+ self.network_client.delete_floating_ip_port_forwarding.return_value = (
+ None
)
- self.network_client.find_ip = mock.Mock(return_value=self.floating_ip)
+ self.network_client.find_ip.return_value = self.floating_ip
# Get the command object to test
self.cmd = floating_ip_port_forwarding.DeleteFloatingIPPortForwarding(
self.app, None
@@ -490,10 +490,11 @@ class TestListFloatingIPPortForwarding(TestFloatingIPPortForwarding):
port_forwarding.description,
)
)
- self.network_client.floating_ip_port_forwardings = mock.Mock(
- return_value=self.port_forwardings
+ self.network_client.floating_ip_port_forwardings.return_value = (
+ self.port_forwardings
)
- self.network_client.find_ip = mock.Mock(return_value=self.floating_ip)
+
+ self.network_client.find_ip.return_value = self.floating_ip
# Get the command object to test
self.cmd = floating_ip_port_forwarding.ListFloatingIPPortForwarding(
self.app, None
@@ -557,14 +558,15 @@ class TestSetFloatingIPPortForwarding(TestFloatingIPPortForwarding):
'floatingip_id': self.floating_ip.id,
}
)
- self.network_client.update_floating_ip_port_forwarding = mock.Mock(
- return_value=None
+ self.network_client.update_floating_ip_port_forwarding.return_value = (
+ None
)
- self.network_client.find_floating_ip_port_forwarding = mock.Mock(
- return_value=self._port_forwarding
+ self.network_client.find_floating_ip_port_forwarding.return_value = (
+ self._port_forwarding
)
- self.network_client.find_ip = mock.Mock(return_value=self.floating_ip)
+
+ self.network_client.find_ip.return_value = self.floating_ip
# Get the command object to test
self.cmd = floating_ip_port_forwarding.SetFloatingIPPortForwarding(
self.app, None
@@ -690,10 +692,11 @@ class TestShowFloatingIPPortForwarding(TestFloatingIPPortForwarding):
self._port_forwarding.internal_port_range,
self._port_forwarding.protocol,
)
- self.network_client.find_floating_ip_port_forwarding = mock.Mock(
- return_value=self._port_forwarding
+ self.network_client.find_floating_ip_port_forwarding.return_value = (
+ self._port_forwarding
)
- self.network_client.find_ip = mock.Mock(return_value=self.floating_ip)
+
+ self.network_client.find_ip.return_value = self.floating_ip
# Get the command object to test
self.cmd = floating_ip_port_forwarding.ShowFloatingIPPortForwarding(
self.app, None
diff --git a/openstackclient/tests/unit/network/v2/test_ip_availability.py b/openstackclient/tests/unit/network/v2/test_ip_availability.py
index 4224d12..def3e17 100644
--- a/openstackclient/tests/unit/network/v2/test_ip_availability.py
+++ b/openstackclient/tests/unit/network/v2/test_ip_availability.py
@@ -11,7 +11,6 @@
# under the License.
#
-from unittest import mock
from osc_lib.cli import format_columns
@@ -55,8 +54,8 @@ class TestListIPAvailability(TestIPAvailability):
super().setUp()
self.cmd = ip_availability.ListIPAvailability(self.app, None)
- self.network_client.network_ip_availabilities = mock.Mock(
- return_value=self._ip_availability
+ self.network_client.network_ip_availabilities.return_value = (
+ self._ip_availability
)
def test_list_no_options(self):
@@ -134,13 +133,12 @@ class TestShowIPAvailability(TestIPAvailability):
def setUp(self):
super().setUp()
- self.network_client.find_network_ip_availability = mock.Mock(
- return_value=self._ip_availability
- )
- self.network_client.find_network = mock.Mock(
- return_value=self._network
+ self.network_client.find_network_ip_availability.return_value = (
+ self._ip_availability
)
+ self.network_client.find_network.return_value = self._network
+
# Get the command object to test
self.cmd = ip_availability.ShowIPAvailability(self.app, None)
diff --git a/openstackclient/tests/unit/network/v2/test_l3_conntrack_helper.py b/openstackclient/tests/unit/network/v2/test_l3_conntrack_helper.py
index b358024..0769e2e 100644
--- a/openstackclient/tests/unit/network/v2/test_l3_conntrack_helper.py
+++ b/openstackclient/tests/unit/network/v2/test_l3_conntrack_helper.py
@@ -11,7 +11,6 @@
# under the License.
#
-from unittest import mock
from osc_lib import exceptions
@@ -46,8 +45,8 @@ class TestCreateL3ConntrackHelper(TestConntrackHelper):
self.ct_helper.protocol,
self.ct_helper.router_id,
)
- self.network_client.create_conntrack_helper = mock.Mock(
- return_value=self.ct_helper
+ self.network_client.create_conntrack_helper.return_value = (
+ self.ct_helper
)
# Get the command object to test
@@ -119,9 +118,7 @@ class TestDeleteL3ConntrackHelper(TestConntrackHelper):
attrs
)
)
- self.network_client.delete_conntrack_helper = mock.Mock(
- return_value=None
- )
+ self.network_client.delete_conntrack_helper.return_value = None
# Get the command object to test
self.cmd = l3_conntrack_helper.DeleteConntrackHelper(self.app, None)
@@ -181,9 +178,7 @@ class TestListL3ConntrackHelper(TestConntrackHelper):
ct_helper.port,
)
)
- self.network_client.conntrack_helpers = mock.Mock(
- return_value=ct_helpers
- )
+ self.network_client.conntrack_helpers.return_value = ct_helpers
# Get the command object to test
self.cmd = l3_conntrack_helper.ListConntrackHelper(self.app, None)
@@ -216,9 +211,7 @@ class TestSetL3ConntrackHelper(TestConntrackHelper):
attrs
)
)
- self.network_client.update_conntrack_helper = mock.Mock(
- return_value=None
- )
+ self.network_client.update_conntrack_helper.return_value = None
# Get the command object to test
self.cmd = l3_conntrack_helper.SetConntrackHelper(self.app, None)
@@ -281,9 +274,7 @@ class TestShowL3ConntrackHelper(TestConntrackHelper):
self.ct_helper.protocol,
self.ct_helper.router_id,
)
- self.network_client.get_conntrack_helper = mock.Mock(
- return_value=self.ct_helper
- )
+ self.network_client.get_conntrack_helper.return_value = self.ct_helper
# Get the command object to test
self.cmd = l3_conntrack_helper.ShowConntrackHelper(self.app, None)
diff --git a/openstackclient/tests/unit/network/v2/test_local_ip.py b/openstackclient/tests/unit/network/v2/test_local_ip.py
index cf4105b..585fec7 100644
--- a/openstackclient/tests/unit/network/v2/test_local_ip.py
+++ b/openstackclient/tests/unit/network/v2/test_local_ip.py
@@ -13,7 +13,6 @@
# under the License.
#
-from unittest import mock
from unittest.mock import call
from osc_lib import exceptions
@@ -77,13 +76,11 @@ class TestCreateLocalIP(TestLocalIP):
def setUp(self):
super().setUp()
- self.network_client.create_local_ip = mock.Mock(
- return_value=self.new_local_ip
- )
- self.network_client.find_network = mock.Mock(
- return_value=self.local_ip_network
- )
- self.network_client.find_port = mock.Mock(return_value=self.port)
+ self.network_client.create_local_ip.return_value = self.new_local_ip
+
+ self.network_client.find_network.return_value = self.local_ip_network
+
+ self.network_client.find_port.return_value = self.port
# Get the command object to test
self.cmd = local_ip.CreateLocalIP(self.app, None)
@@ -149,7 +146,7 @@ class TestDeleteLocalIP(TestLocalIP):
def setUp(self):
super().setUp()
- self.network_client.delete_local_ip = mock.Mock(return_value=None)
+ self.network_client.delete_local_ip.return_value = None
self.network_client.find_local_ip = network_fakes.get_local_ips(
local_ips=self._local_ips
)
@@ -205,9 +202,7 @@ class TestDeleteLocalIP(TestLocalIP):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
find_mock_result = [self._local_ips[0], exceptions.CommandError]
- self.network_client.find_local_ip = mock.Mock(
- side_effect=find_mock_result
- )
+ self.network_client.find_local_ip.side_effect = find_mock_result
try:
self.cmd.take_action(parsed_args)
@@ -258,10 +253,8 @@ class TestListLocalIP(TestLocalIP):
def setUp(self):
super().setUp()
- self.network_client.local_ips = mock.Mock(return_value=self.local_ips)
- self.network_client.find_network = mock.Mock(
- return_value=self.fake_network
- )
+ self.network_client.local_ips.return_value = self.local_ips
+ self.network_client.find_network.return_value = self.fake_network
# Get the command object to test
self.cmd = local_ip.ListLocalIP(self.app, None)
@@ -402,10 +395,8 @@ class TestSetLocalIP(TestLocalIP):
def setUp(self):
super().setUp()
- self.network_client.update_local_ip = mock.Mock(return_value=None)
- self.network_client.find_local_ip = mock.Mock(
- return_value=self._local_ip
- )
+ self.network_client.update_local_ip.return_value = None
+ self.network_client.find_local_ip.return_value = self._local_ip
# Get the command object to test
self.cmd = local_ip.SetLocalIP(self.app, None)
@@ -482,9 +473,7 @@ class TestShowLocalIP(TestLocalIP):
def setUp(self):
super().setUp()
- self.network_client.find_local_ip = mock.Mock(
- return_value=self._local_ip
- )
+ self.network_client.find_local_ip.return_value = self._local_ip
# Get the command object to test
self.cmd = local_ip.ShowLocalIP(self.app, None)
diff --git a/openstackclient/tests/unit/network/v2/test_local_ip_association.py b/openstackclient/tests/unit/network/v2/test_local_ip_association.py
index 2c1c0ff..9efdc29 100644
--- a/openstackclient/tests/unit/network/v2/test_local_ip_association.py
+++ b/openstackclient/tests/unit/network/v2/test_local_ip_association.py
@@ -29,7 +29,7 @@ class TestLocalIPAssociation(network_fakes.TestNetworkV2):
self.local_ip = network_fakes.create_one_local_ip()
self.fixed_port = network_fakes.create_one_port()
self.project = identity_fakes_v2.FakeProject.create_one_project()
- self.network_client.find_port = mock.Mock(return_value=self.fixed_port)
+ self.network_client.find_port.return_value = self.fixed_port
class TestCreateLocalIPAssociation(TestLocalIPAssociation):
@@ -43,13 +43,11 @@ class TestCreateLocalIPAssociation(TestLocalIPAssociation):
}
)
)
- self.network_client.create_local_ip_association = mock.Mock(
- return_value=self.new_local_ip_association
+ self.network_client.create_local_ip_association.return_value = (
+ self.new_local_ip_association
)
- self.network_client.find_local_ip = mock.Mock(
- return_value=self.local_ip
- )
+ self.network_client.find_local_ip.return_value = self.local_ip
# Get the command object to test
self.cmd = local_ip_association.CreateLocalIPAssociation(
@@ -128,13 +126,10 @@ class TestDeleteLocalIPAssociation(TestLocalIPAssociation):
},
)
)
- self.network_client.delete_local_ip_association = mock.Mock(
- return_value=None
- )
+ self.network_client.delete_local_ip_association.return_value = None
+
+ self.network_client.find_local_ip.return_value = self.local_ip
- self.network_client.find_local_ip = mock.Mock(
- return_value=self.local_ip
- )
# Get the command object to test
self.cmd = local_ip_association.DeleteLocalIPAssociation(
self.app, None
@@ -262,13 +257,13 @@ class TestListLocalIPAssociation(TestLocalIPAssociation):
lip_assoc.host,
)
)
- self.network_client.local_ip_associations = mock.Mock(
- return_value=self.local_ip_associations
+ self.network_client.local_ip_associations.return_value = (
+ self.local_ip_associations
)
- self.network_client.find_local_ip = mock.Mock(
- return_value=self.local_ip
- )
- self.network_client.find_port = mock.Mock(return_value=self.fixed_port)
+
+ self.network_client.find_local_ip.return_value = self.local_ip
+
+ self.network_client.find_port.return_value = self.fixed_port
# Get the command object to test
self.cmd = local_ip_association.ListLocalIPAssociation(self.app, None)
diff --git a/openstackclient/tests/unit/network/v2/test_ndp_proxy.py b/openstackclient/tests/unit/network/v2/test_ndp_proxy.py
index f9d9a3b..0fe8740 100644
--- a/openstackclient/tests/unit/network/v2/test_ndp_proxy.py
+++ b/openstackclient/tests/unit/network/v2/test_ndp_proxy.py
@@ -11,7 +11,6 @@
# under the License.
#
-from unittest import mock
from unittest.mock import call
from osc_lib import exceptions
@@ -31,9 +30,9 @@ class TestNDPProxy(network_fakes.TestNetworkV2):
self.domains_mock = self.identity_client.domains
self.router = network_fakes.create_one_router({'id': 'fake-router-id'})
- self.network_client.find_router = mock.Mock(return_value=self.router)
+ self.network_client.find_router.return_value = self.router
self.port = network_fakes.create_one_port()
- self.network_client.find_port = mock.Mock(return_value=self.port)
+ self.network_client.find_port.return_value = self.port
class TestCreateNDPProxy(TestNDPProxy):
@@ -66,9 +65,7 @@ class TestCreateNDPProxy(TestNDPProxy):
self.ndp_proxy.router_id,
self.ndp_proxy.updated_at,
)
- self.network_client.create_ndp_proxy = mock.Mock(
- return_value=self.ndp_proxy
- )
+ self.network_client.create_ndp_proxy.return_value = self.ndp_proxy
# Get the command object to test
self.cmd = ndp_proxy.CreateNDPProxy(self.app, None)
@@ -127,10 +124,8 @@ class TestDeleteNDPProxy(TestNDPProxy):
attrs = {'router_id': self.router.id, 'port_id': self.port.id}
self.ndp_proxies = network_fakes.create_ndp_proxies(attrs)
self.ndp_proxy = self.ndp_proxies[0]
- self.network_client.delete_ndp_proxy = mock.Mock(return_value=None)
- self.network_client.find_ndp_proxy = mock.Mock(
- return_value=self.ndp_proxy
- )
+ self.network_client.delete_ndp_proxy.return_value = None
+ self.network_client.find_ndp_proxy.return_value = self.ndp_proxy
# Get the command object to test
self.cmd = ndp_proxy.DeleteNDPProxy(self.app, None)
@@ -203,7 +198,7 @@ class TestListNDPProxy(TestNDPProxy):
)
)
- self.network_client.ndp_proxies = mock.Mock(return_value=ndp_proxies)
+ self.network_client.ndp_proxies.return_value = ndp_proxies
# Get the command object to test
self.cmd = ndp_proxy.ListNDPProxy(self.app, None)
@@ -340,10 +335,8 @@ class TestSetNDPProxy(TestNDPProxy):
super().setUp()
attrs = {'router_id': self.router.id, 'port_id': self.port.id}
self.ndp_proxy = network_fakes.create_one_ndp_proxy(attrs)
- self.network_client.update_ndp_proxy = mock.Mock(return_value=None)
- self.network_client.find_ndp_proxy = mock.Mock(
- return_value=self.ndp_proxy
- )
+ self.network_client.update_ndp_proxy.return_value = None
+ self.network_client.find_ndp_proxy.return_value = self.ndp_proxy
# Get the command object to test
self.cmd = ndp_proxy.SetNDPProxy(self.app, None)
@@ -434,12 +427,9 @@ class TestShowNDPProxy(TestNDPProxy):
self.ndp_proxy.router_id,
self.ndp_proxy.updated_at,
)
- self.network_client.get_ndp_proxy = mock.Mock(
- return_value=self.ndp_proxy
- )
- self.network_client.find_ndp_proxy = mock.Mock(
- return_value=self.ndp_proxy
- )
+ self.network_client.get_ndp_proxy.return_value = self.ndp_proxy
+
+ self.network_client.find_ndp_proxy.return_value = self.ndp_proxy
# Get the command object to test
self.cmd = ndp_proxy.ShowNDPProxy(self.app, None)
diff --git a/openstackclient/tests/unit/network/v2/test_network.py b/openstackclient/tests/unit/network/v2/test_network.py
index f809cad..1e923d0 100644
--- a/openstackclient/tests/unit/network/v2/test_network.py
+++ b/openstackclient/tests/unit/network/v2/test_network.py
@@ -12,7 +12,6 @@
#
import random
-from unittest import mock
from unittest.mock import call
from osc_lib.cli import format_columns
@@ -116,19 +115,16 @@ class TestCreateNetworkIdentityV3(TestNetwork):
def setUp(self):
super().setUp()
- self.network_client.create_network = mock.Mock(
- return_value=self._network
- )
- self.network_client.set_tags = mock.Mock(return_value=None)
+ self.network_client.create_network.return_value = self._network
+
+ self.network_client.set_tags.return_value = None
# Get the command object to test
self.cmd = network.CreateNetwork(self.app, None)
self.projects_mock.get.return_value = self.project
self.domains_mock.get.return_value = self.domain
- self.network_client.find_qos_policy = mock.Mock(
- return_value=self.qos_policy
- )
+ self.network_client.find_qos_policy.return_value = self.qos_policy
def test_create_no_options(self):
arglist = []
@@ -330,6 +326,23 @@ class TestCreateNetworkIdentityV3(TestNetwork):
exceptions.CommandError, self.cmd.take_action, parsed_args
)
+ def test_create_with_provider_segment_without_provider_type(self):
+ arglist = [
+ "--provider-segment",
+ "123",
+ self._network.name,
+ ]
+ verifylist = [
+ ('provider_network_type', None),
+ ('segmentation_id', "123"),
+ ('name', self._network.name),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.assertRaises(
+ exceptions.CommandError, self.cmd.take_action, parsed_args
+ )
+
class TestCreateNetworkIdentityV2(
identity_fakes_v2.FakeClientMixin,
@@ -406,10 +419,9 @@ class TestCreateNetworkIdentityV2(
def setUp(self):
super().setUp()
- self.network_client.create_network = mock.Mock(
- return_value=self._network
- )
- self.network_client.set_tags = mock.Mock(return_value=None)
+ self.network_client.create_network.return_value = self._network
+
+ self.network_client.set_tags.return_value = None
# Get the command object to test
self.cmd = network.CreateNetwork(self.app, None)
@@ -481,7 +493,7 @@ class TestDeleteNetwork(TestNetwork):
# The networks to delete
self._networks = network_fakes.create_networks(count=3)
- self.network_client.delete_network = mock.Mock(return_value=None)
+ self.network_client.delete_network.return_value = None
self.network_client.find_network = network_fakes.get_networks(
networks=self._networks
@@ -540,14 +552,14 @@ class TestDeleteNetwork(TestNetwork):
exceptions.NotFound('404'),
self._networks[1],
]
- self.network_client.find_network = mock.Mock(side_effect=ret_find)
+ self.network_client.find_network.side_effect = ret_find
# Fake exception in delete_network()
ret_delete = [
None,
exceptions.NotFound('404'),
]
- self.network_client.delete_network = mock.Mock(side_effect=ret_delete)
+ self.network_client.delete_network.side_effect = ret_delete
self.assertRaises(
exceptions.CommandError, self.cmd.take_action, parsed_args
@@ -619,13 +631,13 @@ class TestListNetwork(TestNetwork):
# Get the command object to test
self.cmd = network.ListNetwork(self.app, None)
- self.network_client.networks = mock.Mock(return_value=self._network)
+ self.network_client.networks.return_value = self._network
self._agent = network_fakes.create_one_network_agent()
self.network_client.get_agent.return_value = self._agent
- self.network_client.dhcp_agent_hosting_networks = mock.Mock(
- return_value=self._network
+ self.network_client.dhcp_agent_hosting_networks.return_value = (
+ self._network
)
# TestListTagMixin
@@ -974,15 +986,12 @@ class TestSetNetwork(TestNetwork):
def setUp(self):
super().setUp()
- self.network_client.update_network = mock.Mock(return_value=None)
- self.network_client.set_tags = mock.Mock(return_value=None)
+ self.network_client.update_network.return_value = None
+ self.network_client.set_tags.return_value = None
- self.network_client.find_network = mock.Mock(
- return_value=self._network
- )
- self.network_client.find_qos_policy = mock.Mock(
- return_value=self.qos_policy
- )
+ self.network_client.find_network.return_value = self._network
+
+ self.network_client.find_qos_policy.return_value = self.qos_policy
# Get the command object to test
self.cmd = network.SetNetwork(self.app, None)
@@ -1225,9 +1234,7 @@ class TestShowNetwork(TestNetwork):
def setUp(self):
super().setUp()
- self.network_client.find_network = mock.Mock(
- return_value=self._network
- )
+ self.network_client.find_network.return_value = self._network
# Get the command object to test
self.cmd = network.ShowNetwork(self.app, None)
@@ -1273,15 +1280,12 @@ class TestUnsetNetwork(TestNetwork):
def setUp(self):
super().setUp()
- self.network_client.update_network = mock.Mock(return_value=None)
- self.network_client.set_tags = mock.Mock(return_value=None)
+ self.network_client.update_network.return_value = None
+ self.network_client.set_tags.return_value = None
- self.network_client.find_network = mock.Mock(
- return_value=self._network
- )
- self.network_client.find_qos_policy = mock.Mock(
- return_value=self.qos_policy
- )
+ self.network_client.find_network.return_value = self._network
+
+ self.network_client.find_qos_policy.return_value = self.qos_policy
# Get the command object to test
self.cmd = network.UnsetNetwork(self.app, None)
diff --git a/openstackclient/tests/unit/network/v2/test_network_agent.py b/openstackclient/tests/unit/network/v2/test_network_agent.py
index bd79950..48b394d 100644
--- a/openstackclient/tests/unit/network/v2/test_network_agent.py
+++ b/openstackclient/tests/unit/network/v2/test_network_agent.py
@@ -11,7 +11,6 @@
# under the License.
#
-from unittest import mock
from unittest.mock import call
from osc_lib.cli import format_columns
@@ -34,8 +33,8 @@ class TestAddNetworkToAgent(TestNetworkAgent):
def setUp(self):
super().setUp()
- self.network_client.get_agent = mock.Mock(return_value=self.agent)
- self.network_client.find_network = mock.Mock(return_value=self.net)
+ self.network_client.get_agent.return_value = self.agent
+ self.network_client.find_network.return_value = self.net
self.network_client.name = self.network_client.find_network.name
self.cmd = network_agent.AddNetworkToAgent(self.app, None)
@@ -76,8 +75,8 @@ class TestAddRouterAgent(TestNetworkAgent):
def setUp(self):
super().setUp()
- self.network_client.get_agent = mock.Mock(return_value=self._agent)
- self.network_client.find_router = mock.Mock(return_value=self._router)
+ self.network_client.get_agent.return_value = self._agent
+ self.network_client.find_router.return_value = self._router
self.cmd = network_agent.AddRouterToAgent(self.app, None)
@@ -120,7 +119,7 @@ class TestDeleteNetworkAgent(TestNetworkAgent):
def setUp(self):
super().setUp()
- self.network_client.delete_agent = mock.Mock(return_value=None)
+ self.network_client.delete_agent.return_value = None
# Get the command object to test
self.cmd = network_agent.DeleteNetworkAgent(self.app, None)
@@ -173,9 +172,7 @@ class TestDeleteNetworkAgent(TestNetworkAgent):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
delete_mock_result = [True, exceptions.CommandError]
- self.network_client.delete_agent = mock.Mock(
- side_effect=delete_mock_result
- )
+ self.network_client.delete_agent.side_effect = delete_mock_result
try:
self.cmd.take_action(parsed_args)
@@ -357,8 +354,8 @@ class TestRemoveNetworkFromAgent(TestNetworkAgent):
def setUp(self):
super().setUp()
- self.network_client.get_agent = mock.Mock(return_value=self.agent)
- self.network_client.find_network = mock.Mock(return_value=self.net)
+ self.network_client.get_agent.return_value = self.agent
+ self.network_client.find_network.return_value = self.net
self.network_client.name = self.network_client.find_network.name
self.cmd = network_agent.RemoveNetworkFromAgent(self.app, None)
@@ -414,8 +411,8 @@ class TestRemoveRouterAgent(TestNetworkAgent):
def setUp(self):
super().setUp()
- self.network_client.get_agent = mock.Mock(return_value=self._agent)
- self.network_client.find_router = mock.Mock(return_value=self._router)
+ self.network_client.get_agent.return_value = self._agent
+ self.network_client.find_router.return_value = self._router
self.cmd = network_agent.RemoveRouterFromAgent(self.app, None)
@@ -458,10 +455,8 @@ class TestSetNetworkAgent(TestNetworkAgent):
def setUp(self):
super().setUp()
- self.network_client.update_agent = mock.Mock(return_value=None)
- self.network_client.get_agent = mock.Mock(
- return_value=self._network_agent
- )
+ self.network_client.update_agent.return_value = None
+ self.network_client.get_agent.return_value = self._network_agent
# Get the command object to test
self.cmd = network_agent.SetNetworkAgent(self.app, None)
@@ -574,9 +569,7 @@ class TestShowNetworkAgent(TestNetworkAgent):
def setUp(self):
super().setUp()
- self.network_client.get_agent = mock.Mock(
- return_value=self._network_agent
- )
+ self.network_client.get_agent.return_value = self._network_agent
# Get the command object to test
self.cmd = network_agent.ShowNetworkAgent(self.app, None)
diff --git a/openstackclient/tests/unit/network/v2/test_network_auto_allocated_topology.py b/openstackclient/tests/unit/network/v2/test_network_auto_allocated_topology.py
index 20c645b..d13bd8c 100644
--- a/openstackclient/tests/unit/network/v2/test_network_auto_allocated_topology.py
+++ b/openstackclient/tests/unit/network/v2/test_network_auto_allocated_topology.py
@@ -13,7 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-from unittest import mock
from openstackclient.network.v2 import network_auto_allocated_topology
from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes
@@ -50,8 +49,8 @@ class TestCreateAutoAllocatedTopology(TestAutoAllocatedTopology):
self.cmd = network_auto_allocated_topology.CreateAutoAllocatedTopology(
self.app, None
)
- self.network_client.get_auto_allocated_topology = mock.Mock(
- return_value=self.topology
+ self.network_client.get_auto_allocated_topology.return_value = (
+ self.topology
)
def test_create_no_options(self):
@@ -155,8 +154,8 @@ class TestValidateAutoAllocatedTopology(TestAutoAllocatedTopology):
self.cmd = network_auto_allocated_topology.CreateAutoAllocatedTopology(
self.app, None
)
- self.network_client.validate_auto_allocated_topology = mock.Mock(
- return_value=self.topology
+ self.network_client.validate_auto_allocated_topology.return_value = (
+ self.topology
)
def test_show_dry_run_no_project(self):
@@ -228,9 +227,7 @@ class TestDeleteAutoAllocatedTopology(TestAutoAllocatedTopology):
self.cmd = network_auto_allocated_topology.DeleteAutoAllocatedTopology(
self.app, None
)
- self.network_client.delete_auto_allocated_topology = mock.Mock(
- return_value=None
- )
+ self.network_client.delete_auto_allocated_topology.return_value = None
def test_delete_no_project(self):
arglist = []
diff --git a/openstackclient/tests/unit/network/v2/test_network_flavor.py b/openstackclient/tests/unit/network/v2/test_network_flavor.py
index cfbe1f7..10038e3 100644
--- a/openstackclient/tests/unit/network/v2/test_network_flavor.py
+++ b/openstackclient/tests/unit/network/v2/test_network_flavor.py
@@ -41,11 +41,9 @@ class TestAddNetworkFlavorToProfile(TestNetworkFlavor):
def setUp(self):
super().setUp()
- self.network_client.find_flavor = mock.Mock(
- return_value=self.network_flavor
- )
- self.network_client.find_service_profile = mock.Mock(
- return_value=self.service_profile
+ self.network_client.find_flavor.return_value = self.network_flavor
+ self.network_client.find_service_profile.return_value = (
+ self.service_profile
)
self.cmd = network_flavor.AddNetworkFlavorToProfile(self.app, None)
@@ -102,8 +100,8 @@ class TestCreateNetworkFlavor(TestNetworkFlavor):
def setUp(self):
super().setUp()
- self.network_client.create_flavor = mock.Mock(
- return_value=self.new_network_flavor
+ self.network_client.create_flavor.return_value = (
+ self.new_network_flavor
)
# Get the command object to test
@@ -218,7 +216,7 @@ class TestDeleteNetworkFlavor(TestNetworkFlavor):
def setUp(self):
super().setUp()
- self.network_client.delete_flavor = mock.Mock(return_value=None)
+ self.network_client.delete_flavor.return_value = None
self.network_client.find_flavor = network_fakes.get_flavor(
network_flavors=self._network_flavors
)
@@ -278,9 +276,7 @@ class TestDeleteNetworkFlavor(TestNetworkFlavor):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
find_mock_result = [self._network_flavors[0], exceptions.CommandError]
- self.network_client.find_flavor = mock.Mock(
- side_effect=find_mock_result
- )
+ self.network_client.find_flavor.side_effect = find_mock_result
try:
self.cmd.take_action(parsed_args)
@@ -323,9 +319,7 @@ class TestListNetworkFlavor(TestNetworkFlavor):
def setUp(self):
super().setUp()
- self.network_client.flavors = mock.Mock(
- return_value=self._network_flavors
- )
+ self.network_client.flavors.return_value = self._network_flavors
# Get the command object to test
self.cmd = network_flavor.ListNetworkFlavor(self.app, None)
@@ -348,11 +342,9 @@ class TestRemoveNetworkFlavorFromProfile(TestNetworkFlavor):
def setUp(self):
super().setUp()
- self.network_client.find_flavor = mock.Mock(
- return_value=self.network_flavor
- )
- self.network_client.find_service_profile = mock.Mock(
- return_value=self.service_profile
+ self.network_client.find_flavor.return_value = self.network_flavor
+ self.network_client.find_service_profile.return_value = (
+ self.service_profile
)
self.network_client.disassociate_flavor_from_service_profile = (
mock.Mock()
@@ -412,9 +404,7 @@ class TestShowNetworkFlavor(TestNetworkFlavor):
def setUp(self):
super().setUp()
- self.network_client.find_flavor = mock.Mock(
- return_value=self.new_network_flavor
- )
+ self.network_client.find_flavor.return_value = self.new_network_flavor
# Get the command object to test
self.cmd = network_flavor.ShowNetworkFlavor(self.app, None)
@@ -456,10 +446,8 @@ class TestSetNetworkFlavor(TestNetworkFlavor):
def setUp(self):
super().setUp()
- self.network_client.update_flavor = mock.Mock(return_value=None)
- self.network_client.find_flavor = mock.Mock(
- return_value=self.new_network_flavor
- )
+ self.network_client.update_flavor.return_value = None
+ self.network_client.find_flavor.return_value = self.new_network_flavor
# Get the command object to test
self.cmd = network_flavor.SetNetworkFlavor(self.app, None)
diff --git a/openstackclient/tests/unit/network/v2/test_network_flavor_profile.py b/openstackclient/tests/unit/network/v2/test_network_flavor_profile.py
index d94926c..c8235bf 100644
--- a/openstackclient/tests/unit/network/v2/test_network_flavor_profile.py
+++ b/openstackclient/tests/unit/network/v2/test_network_flavor_profile.py
@@ -49,9 +49,10 @@ class TestCreateFlavorProfile(TestFlavorProfile):
def setUp(self):
super().setUp()
- self.network_client.create_service_profile = mock.Mock(
- return_value=self.new_flavor_profile
+ self.network_client.create_service_profile.return_value = (
+ self.new_flavor_profile
)
+
# Get the command object to test
self.cmd = network_flavor_profile.CreateNetworkFlavorProfile(
self.app, None
@@ -195,9 +196,8 @@ class TestDeleteFlavorProfile(TestFlavorProfile):
def setUp(self):
super().setUp()
- self.network_client.delete_service_profile = mock.Mock(
- return_value=None
- )
+ self.network_client.delete_service_profile.return_value = None
+
self.network_client.find_service_profile = (
network_fakes.get_service_profile(
flavor_profile=self._network_flavor_profiles
@@ -266,9 +266,7 @@ class TestDeleteFlavorProfile(TestFlavorProfile):
self._network_flavor_profiles[0],
exceptions.CommandError,
]
- self.network_client.find_service_profile = mock.Mock(
- side_effect=find_mock_result
- )
+ self.network_client.find_service_profile.side_effect = find_mock_result
try:
self.cmd.take_action(parsed_args)
@@ -314,8 +312,8 @@ class TestListFlavorProfile(TestFlavorProfile):
def setUp(self):
super().setUp()
- self.network_client.service_profiles = mock.Mock(
- return_value=self._network_flavor_profiles
+ self.network_client.service_profiles.return_value = (
+ self._network_flavor_profiles
)
# Get the command object to test
@@ -355,8 +353,8 @@ class TestShowFlavorProfile(TestFlavorProfile):
def setUp(self):
super().setUp()
- self.network_client.find_service_profile = mock.Mock(
- return_value=self.network_flavor_profile
+ self.network_client.find_service_profile.return_value = (
+ self.network_flavor_profile
)
# Get the command object to test
@@ -388,11 +386,10 @@ class TestSetFlavorProfile(TestFlavorProfile):
def setUp(self):
super().setUp()
- self.network_client.update_service_profile = mock.Mock(
- return_value=None
- )
- self.network_client.find_service_profile = mock.Mock(
- return_value=self.network_flavor_profile
+ self.network_client.update_service_profile.return_value = None
+
+ self.network_client.find_service_profile.return_value = (
+ self.network_flavor_profile
)
# Get the command object to test
diff --git a/openstackclient/tests/unit/network/v2/test_network_meter.py b/openstackclient/tests/unit/network/v2/test_network_meter.py
index a92035d..f13839a 100644
--- a/openstackclient/tests/unit/network/v2/test_network_meter.py
+++ b/openstackclient/tests/unit/network/v2/test_network_meter.py
@@ -13,7 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-from unittest import mock
from unittest.mock import call
from osc_lib import exceptions
@@ -55,9 +54,8 @@ class TestCreateMeter(TestMeter):
def setUp(self):
super().setUp()
- self.network_client.create_metering_label = mock.Mock(
- return_value=self.new_meter
- )
+ self.network_client.create_metering_label.return_value = self.new_meter
+
self.projects_mock.get.return_value = self.project
self.cmd = network_meter.CreateMeter(self.app, None)
@@ -132,9 +130,7 @@ class TestDeleteMeter(TestMeter):
self.meter_list = network_fakes.FakeNetworkMeter.create_meter(count=2)
- self.network_client.delete_metering_label = mock.Mock(
- return_value=None
- )
+ self.network_client.delete_metering_label.return_value = None
self.network_client.find_metering_label = (
network_fakes.FakeNetworkMeter.get_meter(meter=self.meter_list)
@@ -194,15 +190,13 @@ class TestDeleteMeter(TestMeter):
exceptions.NotFound('404'),
self.meter_list[1],
]
- self.network_client.find_meter = mock.Mock(side_effect=return_find)
+ self.network_client.find_metering_label.side_effect = return_find
ret_delete = [
None,
exceptions.NotFound('404'),
]
- self.network_client.delete_metering_label = mock.Mock(
- side_effect=ret_delete
- )
+ self.network_client.delete_metering_label.side_effect = ret_delete
self.assertRaises(
exceptions.CommandError, self.cmd.take_action, parsed_args
@@ -240,9 +234,7 @@ class TestListMeter(TestMeter):
def setUp(self):
super().setUp()
- self.network_client.metering_labels = mock.Mock(
- return_value=self.meter_list
- )
+ self.network_client.metering_labels.return_value = self.meter_list
self.cmd = network_meter.ListMeter(self.app, None)
@@ -282,9 +274,7 @@ class TestShowMeter(TestMeter):
self.cmd = network_meter.ShowMeter(self.app, None)
- self.network_client.find_metering_label = mock.Mock(
- return_value=self.new_meter
- )
+ self.network_client.find_metering_label.return_value = self.new_meter
def test_show_no_options(self):
arglist = []
diff --git a/openstackclient/tests/unit/network/v2/test_network_meter_rule.py b/openstackclient/tests/unit/network/v2/test_network_meter_rule.py
index e90ed05..407fb04 100644
--- a/openstackclient/tests/unit/network/v2/test_network_meter_rule.py
+++ b/openstackclient/tests/unit/network/v2/test_network_meter_rule.py
@@ -13,7 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-from unittest import mock
from unittest.mock import call
from osc_lib import exceptions
@@ -65,14 +64,13 @@ class TestCreateMeterRule(TestMeterRule):
{'id': self.new_rule.metering_label_id}
)
- self.network_client.create_metering_label_rule = mock.Mock(
- return_value=self.new_rule
+ self.network_client.create_metering_label_rule.return_value = (
+ self.new_rule
)
+
self.projects_mock.get.return_value = self.project
self.cmd = network_meter_rule.CreateMeterRule(self.app, None)
- self.network_client.find_metering_label = mock.Mock(
- return_value=fake_meter
- )
+ self.network_client.find_metering_label.return_value = fake_meter
def test_create_no_options(self):
arglist = []
@@ -146,9 +144,7 @@ class TestDeleteMeterRule(TestMeterRule):
self.rule_list = network_fakes.FakeNetworkMeterRule.create_meter_rule(
count=2
)
- self.network_client.delete_metering_label_rule = mock.Mock(
- return_value=None
- )
+ self.network_client.delete_metering_label_rule.return_value = None
self.network_client.find_metering_label_rule = (
network_fakes.FakeNetworkMeterRule.get_meter_rule(
@@ -210,17 +206,13 @@ class TestDeleteMeterRule(TestMeterRule):
exceptions.NotFound('404'),
self.rule_list[1],
]
- self.network_client.find_metering_label_rule = mock.Mock(
- side_effect=return_find
- )
+ self.network_client.find_metering_label_rule.side_effect = return_find
ret_delete = [
None,
exceptions.NotFound('404'),
]
- self.network_client.delete_metering_label_rule = mock.Mock(
- side_effect=ret_delete
- )
+ self.network_client.delete_metering_label_rule.side_effect = ret_delete
self.assertRaises(
exceptions.CommandError, self.cmd.take_action, parsed_args
@@ -262,9 +254,7 @@ class TestListMeterRule(TestMeterRule):
def setUp(self):
super().setUp()
- self.network_client.metering_label_rules = mock.Mock(
- return_value=self.rule_list
- )
+ self.network_client.metering_label_rules.return_value = self.rule_list
self.cmd = network_meter_rule.ListMeterRule(self.app, None)
@@ -311,8 +301,8 @@ class TestShowMeterRule(TestMeterRule):
self.cmd = network_meter_rule.ShowMeterRule(self.app, None)
- self.network_client.find_metering_label_rule = mock.Mock(
- return_value=self.new_rule
+ self.network_client.find_metering_label_rule.return_value = (
+ self.new_rule
)
def test_show_no_options(self):
diff --git a/openstackclient/tests/unit/network/v2/test_network_qos_policy.py b/openstackclient/tests/unit/network/v2/test_network_qos_policy.py
index fae5b69..17f40ef 100644
--- a/openstackclient/tests/unit/network/v2/test_network_qos_policy.py
+++ b/openstackclient/tests/unit/network/v2/test_network_qos_policy.py
@@ -63,8 +63,8 @@ class TestCreateNetworkQosPolicy(TestQosPolicy):
def setUp(self):
super().setUp()
- self.network_client.create_qos_policy = mock.Mock(
- return_value=self.new_qos_policy
+ self.network_client.create_qos_policy.return_value = (
+ self.new_qos_policy
)
# Get the command object to test
@@ -163,7 +163,7 @@ class TestDeleteNetworkQosPolicy(TestQosPolicy):
def setUp(self):
super().setUp()
- self.network_client.delete_qos_policy = mock.Mock(return_value=None)
+ self.network_client.delete_qos_policy.return_value = None
self.network_client.find_qos_policy = network_fakes.get_qos_policies(
qos_policies=self._qos_policies
)
@@ -264,9 +264,7 @@ class TestListNetworkQosPolicy(TestQosPolicy):
def setUp(self):
super().setUp()
- self.network_client.qos_policies = mock.Mock(
- return_value=self.qos_policies
- )
+ self.network_client.qos_policies.return_value = self.qos_policies
# Get the command object to test
self.cmd = network_qos_policy.ListNetworkQosPolicy(self.app, None)
@@ -344,10 +342,8 @@ class TestSetNetworkQosPolicy(TestQosPolicy):
def setUp(self):
super().setUp()
- self.network_client.update_qos_policy = mock.Mock(return_value=None)
- self.network_client.find_qos_policy = mock.Mock(
- return_value=self._qos_policy
- )
+ self.network_client.update_qos_policy.return_value = None
+ self.network_client.find_qos_policy.return_value = self._qos_policy
# Get the command object to test
self.cmd = network_qos_policy.SetNetworkQosPolicy(self.app, None)
@@ -447,9 +443,7 @@ class TestShowNetworkQosPolicy(TestQosPolicy):
def setUp(self):
super().setUp()
- self.network_client.find_qos_policy = mock.Mock(
- return_value=self._qos_policy
- )
+ self.network_client.find_qos_policy.return_value = self._qos_policy
# Get the command object to test
self.cmd = network_qos_policy.ShowNetworkQosPolicy(self.app, None)
diff --git a/openstackclient/tests/unit/network/v2/test_network_qos_rule.py b/openstackclient/tests/unit/network/v2/test_network_qos_rule.py
index e658684..4300304 100644
--- a/openstackclient/tests/unit/network/v2/test_network_qos_rule.py
+++ b/openstackclient/tests/unit/network/v2/test_network_qos_rule.py
@@ -56,9 +56,7 @@ class TestNetworkQosRule(network_fakes.TestNetworkV2):
def setUp(self):
super().setUp()
self.qos_policy = network_fakes.create_one_qos_policy()
- self.network_client.find_qos_policy = mock.Mock(
- return_value=self.qos_policy
- )
+ self.network_client.find_qos_policy.return_value = self.qos_policy
class TestCreateNetworkQosRuleMinimumBandwidth(TestNetworkQosRule):
@@ -87,8 +85,8 @@ class TestCreateNetworkQosRuleMinimumBandwidth(TestNetworkQosRule):
self.new_rule.project_id,
self.new_rule.type,
)
- self.network_client.create_qos_minimum_bandwidth_rule = mock.Mock(
- return_value=self.new_rule
+ self.network_client.create_qos_minimum_bandwidth_rule.return_value = (
+ self.new_rule
)
# Get the command object to test
@@ -190,9 +188,7 @@ class TestCreateNetworkQosRuleMinimumPacketRate(TestNetworkQosRule):
self.new_rule.project_id,
self.new_rule.type,
)
- self.network_client.create_qos_minimum_packet_rate_rule = mock.Mock(
- return_value=self.new_rule
- )
+ self.network_client.create_qos_minimum_packet_rate_rule.return_value = self.new_rule
# Get the command object to test
self.cmd = network_qos_rule.CreateNetworkQosRule(self.app, None)
@@ -291,8 +287,8 @@ class TestCreateNetworkQosRuleDSCPMarking(TestNetworkQosRule):
self.new_rule.project_id,
self.new_rule.type,
)
- self.network_client.create_qos_dscp_marking_rule = mock.Mock(
- return_value=self.new_rule
+ self.network_client.create_qos_dscp_marking_rule.return_value = (
+ self.new_rule
)
# Get the command object to test
@@ -389,8 +385,8 @@ class TestCreateNetworkQosRuleBandwidtLimit(TestNetworkQosRule):
self.new_rule.project_id,
self.new_rule.type,
)
- self.network_client.create_qos_bandwidth_limit_rule = mock.Mock(
- return_value=self.new_rule
+ self.network_client.create_qos_bandwidth_limit_rule.return_value = (
+ self.new_rule
)
# Get the command object to test
@@ -529,9 +525,10 @@ class TestDeleteNetworkQosRuleMinimumBandwidth(TestNetworkQosRule):
}
self.new_rule = network_fakes.create_one_qos_rule(attrs)
self.qos_policy.rules = [self.new_rule]
- self.network_client.delete_qos_minimum_bandwidth_rule = mock.Mock(
- return_value=None
+ self.network_client.delete_qos_minimum_bandwidth_rule.return_value = (
+ None
)
+
self.network_client.find_qos_minimum_bandwidth_rule = (
network_fakes.get_qos_rules(qos_rules=self.new_rule)
)
@@ -592,9 +589,8 @@ class TestDeleteNetworkQosRuleMinimumPacketRate(TestNetworkQosRule):
}
self.new_rule = network_fakes.create_one_qos_rule(attrs)
self.qos_policy.rules = [self.new_rule]
- self.network_client.delete_qos_minimum_packet_rate_rule = mock.Mock(
- return_value=None
- )
+ self.network_client.delete_qos_minimum_packet_rate_rule.return_value = None
+
self.network_client.find_qos_minimum_packet_rate_rule = (
network_fakes.get_qos_rules(qos_rules=self.new_rule)
)
@@ -655,9 +651,8 @@ class TestDeleteNetworkQosRuleDSCPMarking(TestNetworkQosRule):
}
self.new_rule = network_fakes.create_one_qos_rule(attrs)
self.qos_policy.rules = [self.new_rule]
- self.network_client.delete_qos_dscp_marking_rule = mock.Mock(
- return_value=None
- )
+ self.network_client.delete_qos_dscp_marking_rule.return_value = None
+
self.network_client.find_qos_dscp_marking_rule = (
network_fakes.get_qos_rules(qos_rules=self.new_rule)
)
@@ -718,9 +713,8 @@ class TestDeleteNetworkQosRuleBandwidthLimit(TestNetworkQosRule):
}
self.new_rule = network_fakes.create_one_qos_rule(attrs)
self.qos_policy.rules = [self.new_rule]
- self.network_client.delete_qos_bandwidth_limit_rule = mock.Mock(
- return_value=None
- )
+ self.network_client.delete_qos_bandwidth_limit_rule.return_value = None
+
self.network_client.find_qos_bandwidth_limit_rule = (
network_fakes.get_qos_rules(qos_rules=self.new_rule)
)
@@ -781,16 +775,16 @@ class TestSetNetworkQosRuleMinimumBandwidth(TestNetworkQosRule):
}
self.new_rule = network_fakes.create_one_qos_rule(attrs)
self.qos_policy.rules = [self.new_rule]
- self.network_client.update_qos_minimum_bandwidth_rule = mock.Mock(
- return_value=None
+ self.network_client.update_qos_minimum_bandwidth_rule.return_value = (
+ None
)
- self.network_client.find_qos_minimum_bandwidth_rule = mock.Mock(
- return_value=self.new_rule
- )
- self.network_client.find_qos_policy = mock.Mock(
- return_value=self.qos_policy
+
+ self.network_client.find_qos_minimum_bandwidth_rule.return_value = (
+ self.new_rule
)
+ self.network_client.find_qos_policy.return_value = self.qos_policy
+
# Get the command object to test
self.cmd = network_qos_rule.SetNetworkQosRule(self.app, None)
@@ -883,16 +877,14 @@ class TestSetNetworkQosRuleMinimumPacketRate(TestNetworkQosRule):
}
self.new_rule = network_fakes.create_one_qos_rule(attrs)
self.qos_policy.rules = [self.new_rule]
- self.network_client.update_qos_minimum_packet_rate_rule = mock.Mock(
- return_value=None
- )
- self.network_client.find_qos_minimum_packet_rate_rule = mock.Mock(
- return_value=self.new_rule
- )
- self.network_client.find_qos_policy = mock.Mock(
- return_value=self.qos_policy
+ self.network_client.update_qos_minimum_packet_rate_rule.return_value = None
+
+ self.network_client.find_qos_minimum_packet_rate_rule.return_value = (
+ self.new_rule
)
+ self.network_client.find_qos_policy.return_value = self.qos_policy
+
# Get the command object to test
self.cmd = network_qos_rule.SetNetworkQosRule(self.app, None)
@@ -985,16 +977,14 @@ class TestSetNetworkQosRuleDSCPMarking(TestNetworkQosRule):
}
self.new_rule = network_fakes.create_one_qos_rule(attrs)
self.qos_policy.rules = [self.new_rule]
- self.network_client.update_qos_dscp_marking_rule = mock.Mock(
- return_value=None
- )
- self.network_client.find_qos_dscp_marking_rule = mock.Mock(
- return_value=self.new_rule
- )
- self.network_client.find_qos_policy = mock.Mock(
- return_value=self.qos_policy
+ self.network_client.update_qos_dscp_marking_rule.return_value = None
+
+ self.network_client.find_qos_dscp_marking_rule.return_value = (
+ self.new_rule
)
+ self.network_client.find_qos_policy.return_value = self.qos_policy
+
# Get the command object to test
self.cmd = network_qos_rule.SetNetworkQosRule(self.app, None)
@@ -1351,8 +1341,8 @@ class TestShowNetworkQosRuleMinimumBandwidth(TestNetworkQosRule):
self.new_rule.type,
)
- self.network_client.get_qos_minimum_bandwidth_rule = mock.Mock(
- return_value=self.new_rule
+ self.network_client.get_qos_minimum_bandwidth_rule.return_value = (
+ self.new_rule
)
# Get the command object to test
@@ -1415,8 +1405,8 @@ class TestShowNetworkQosRuleMinimumPacketRate(TestNetworkQosRule):
self.new_rule.type,
)
- self.network_client.get_qos_minimum_packet_rate_rule = mock.Mock(
- return_value=self.new_rule
+ self.network_client.get_qos_minimum_packet_rate_rule.return_value = (
+ self.new_rule
)
# Get the command object to test
@@ -1477,8 +1467,8 @@ class TestShowNetworkQosDSCPMarking(TestNetworkQosRule):
self.new_rule.type,
)
- self.network_client.get_qos_dscp_marking_rule = mock.Mock(
- return_value=self.new_rule
+ self.network_client.get_qos_dscp_marking_rule.return_value = (
+ self.new_rule
)
# Get the command object to test
@@ -1543,8 +1533,8 @@ class TestShowNetworkQosBandwidthLimit(TestNetworkQosRule):
self.new_rule.type,
)
- self.network_client.get_qos_bandwidth_limit_rule = mock.Mock(
- return_value=self.new_rule
+ self.network_client.get_qos_bandwidth_limit_rule.return_value = (
+ self.new_rule
)
# Get the command object to test
diff --git a/openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py b/openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py
index c0aafa0..1c50b9e 100644
--- a/openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py
+++ b/openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py
@@ -13,7 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-from unittest import mock
from openstackclient.network.v2 import network_qos_rule_type as _qos_rule_type
from openstackclient.tests.unit.network.v2 import fakes as network_fakes
@@ -35,9 +34,7 @@ class TestShowNetworkQosRuleType(TestNetworkQosRuleType):
def setUp(self):
super().setUp()
- self.network_client.get_qos_rule_type = mock.Mock(
- return_value=self.qos_rule_type
- )
+ self.network_client.get_qos_rule_type.return_value = self.qos_rule_type
# Get the command object to test
self.cmd = _qos_rule_type.ShowNetworkQosRuleType(self.app, None)
@@ -84,9 +81,7 @@ class TestListNetworkQosRuleType(TestNetworkQosRuleType):
def setUp(self):
super().setUp()
- self.network_client.qos_rule_types = mock.Mock(
- return_value=self.qos_rule_types
- )
+ self.network_client.qos_rule_types.return_value = self.qos_rule_types
# Get the command object to test
self.cmd = _qos_rule_type.ListNetworkQosRuleType(self.app, None)
diff --git a/openstackclient/tests/unit/network/v2/test_network_rbac.py b/openstackclient/tests/unit/network/v2/test_network_rbac.py
index 816e932..d3a7192 100644
--- a/openstackclient/tests/unit/network/v2/test_network_rbac.py
+++ b/openstackclient/tests/unit/network/v2/test_network_rbac.py
@@ -11,7 +11,6 @@
# under the License.
#
-from unittest import mock
from unittest.mock import call
import ddt
@@ -72,27 +71,20 @@ class TestCreateNetworkRBAC(TestNetworkRBAC):
# Get the command object to test
self.cmd = network_rbac.CreateNetworkRBAC(self.app, None)
- self.network_client.create_rbac_policy = mock.Mock(
- return_value=self.rbac_policy
- )
- self.network_client.find_network = mock.Mock(
- return_value=self.network_object
- )
- self.network_client.find_qos_policy = mock.Mock(
- return_value=self.qos_object
- )
- self.network_client.find_security_group = mock.Mock(
- return_value=self.sg_object
- )
- self.network_client.find_address_scope = mock.Mock(
- return_value=self.as_object
- )
- self.network_client.find_subnet_pool = mock.Mock(
- return_value=self.snp_object
- )
- self.network_client.find_address_group = mock.Mock(
- return_value=self.ag_object
- )
+ self.network_client.create_rbac_policy.return_value = self.rbac_policy
+
+ self.network_client.find_network.return_value = self.network_object
+
+ self.network_client.find_qos_policy.return_value = self.qos_object
+
+ self.network_client.find_security_group.return_value = self.sg_object
+
+ self.network_client.find_address_scope.return_value = self.as_object
+
+ self.network_client.find_subnet_pool.return_value = self.snp_object
+
+ self.network_client.find_address_group.return_value = self.ag_object
+
self.projects_mock.get.return_value = self.project
def test_network_rbac_create_no_type(self):
@@ -343,7 +335,7 @@ class TestDeleteNetworkRBAC(TestNetworkRBAC):
def setUp(self):
super().setUp()
- self.network_client.delete_rbac_policy = mock.Mock(return_value=None)
+ self.network_client.delete_rbac_policy.return_value = None
self.network_client.find_rbac_policy = network_fakes.get_network_rbacs(
rbac_policies=self.rbac_policies
)
@@ -400,9 +392,7 @@ class TestDeleteNetworkRBAC(TestNetworkRBAC):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
find_mock_result = [self.rbac_policies[0], exceptions.CommandError]
- self.network_client.find_rbac_policy = mock.Mock(
- side_effect=find_mock_result
- )
+ self.network_client.find_rbac_policy.side_effect = find_mock_result
try:
self.cmd.take_action(parsed_args)
@@ -462,9 +452,7 @@ class TestListNetworkRABC(TestNetworkRBAC):
# Get the command object to test
self.cmd = network_rbac.ListNetworkRBAC(self.app, None)
- self.network_client.rbac_policies = mock.Mock(
- return_value=self.rbac_policies
- )
+ self.network_client.rbac_policies.return_value = self.rbac_policies
self.project = identity_fakes_v3.FakeProject.create_one_project()
self.projects_mock.get.return_value = self.project
@@ -564,10 +552,9 @@ class TestSetNetworkRBAC(TestNetworkRBAC):
# Get the command object to test
self.cmd = network_rbac.SetNetworkRBAC(self.app, None)
- self.network_client.find_rbac_policy = mock.Mock(
- return_value=self.rbac_policy
- )
- self.network_client.update_rbac_policy = mock.Mock(return_value=None)
+ self.network_client.find_rbac_policy.return_value = self.rbac_policy
+
+ self.network_client.update_rbac_policy.return_value = None
self.projects_mock.get.return_value = self.project
def test_network_rbac_set_nothing(self):
@@ -639,9 +626,7 @@ class TestShowNetworkRBAC(TestNetworkRBAC):
# Get the command object to test
self.cmd = network_rbac.ShowNetworkRBAC(self.app, None)
- self.network_client.find_rbac_policy = mock.Mock(
- return_value=self.rbac_policy
- )
+ self.network_client.find_rbac_policy.return_value = self.rbac_policy
def test_show_no_options(self):
arglist = []
diff --git a/openstackclient/tests/unit/network/v2/test_network_segment.py b/openstackclient/tests/unit/network/v2/test_network_segment.py
index 936a20a..ab71c32 100644
--- a/openstackclient/tests/unit/network/v2/test_network_segment.py
+++ b/openstackclient/tests/unit/network/v2/test_network_segment.py
@@ -11,7 +11,6 @@
# under the License.
#
-from unittest import mock
from unittest.mock import call
from osc_lib import exceptions
@@ -58,12 +57,9 @@ class TestCreateNetworkSegment(TestNetworkSegment):
def setUp(self):
super().setUp()
- self.network_client.create_segment = mock.Mock(
- return_value=self._network_segment
- )
- self.network_client.find_network = mock.Mock(
- return_value=self._network
- )
+ self.network_client.create_segment.return_value = self._network_segment
+
+ self.network_client.find_network.return_value = self._network
# Get the command object to test
self.cmd = network_segment.CreateNetworkSegment(self.app, None)
@@ -172,10 +168,8 @@ class TestDeleteNetworkSegment(TestNetworkSegment):
def setUp(self):
super().setUp()
- self.network_client.delete_segment = mock.Mock(return_value=None)
- self.network_client.find_segment = mock.Mock(
- side_effect=self._network_segments
- )
+ self.network_client.delete_segment.return_value = None
+ self.network_client.find_segment.side_effect = self._network_segments
# Get the command object to test
self.cmd = network_segment.DeleteNetworkSegment(self.app, None)
@@ -224,9 +218,7 @@ class TestDeleteNetworkSegment(TestNetworkSegment):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
find_mock_result = [self._network_segments[0], exceptions.CommandError]
- self.network_client.find_segment = mock.Mock(
- side_effect=find_mock_result
- )
+ self.network_client.find_segment.side_effect = find_mock_result
try:
self.cmd.take_action(parsed_args)
@@ -291,12 +283,9 @@ class TestListNetworkSegment(TestNetworkSegment):
# Get the command object to test
self.cmd = network_segment.ListNetworkSegment(self.app, None)
- self.network_client.find_network = mock.Mock(
- return_value=self._network
- )
- self.network_client.segments = mock.Mock(
- return_value=self._network_segments
- )
+ self.network_client.find_network.return_value = self._network
+
+ self.network_client.segments.return_value = self._network_segments
def test_list_no_option(self):
arglist = []
@@ -352,12 +341,9 @@ class TestSetNetworkSegment(TestNetworkSegment):
def setUp(self):
super().setUp()
- self.network_client.find_segment = mock.Mock(
- return_value=self._network_segment
- )
- self.network_client.update_segment = mock.Mock(
- return_value=self._network_segment
- )
+ self.network_client.find_segment.return_value = self._network_segment
+
+ self.network_client.update_segment.return_value = self._network_segment
# Get the command object to test
self.cmd = network_segment.SetNetworkSegment(self.app, None)
@@ -432,9 +418,7 @@ class TestShowNetworkSegment(TestNetworkSegment):
def setUp(self):
super().setUp()
- self.network_client.find_segment = mock.Mock(
- return_value=self._network_segment
- )
+ self.network_client.find_segment.return_value = self._network_segment
# Get the command object to test
self.cmd = network_segment.ShowNetworkSegment(self.app, None)
diff --git a/openstackclient/tests/unit/network/v2/test_network_segment_range.py b/openstackclient/tests/unit/network/v2/test_network_segment_range.py
index d5e406f..9c9c900 100644
--- a/openstackclient/tests/unit/network/v2/test_network_segment_range.py
+++ b/openstackclient/tests/unit/network/v2/test_network_segment_range.py
@@ -78,8 +78,8 @@ class TestCreateNetworkSegmentRange(TestNetworkSegmentRange):
def setUp(self):
super().setUp()
- self.network_client.create_network_segment_range = mock.Mock(
- return_value=self._network_segment_range
+ self.network_client.create_network_segment_range.return_value = (
+ self._network_segment_range
)
# Get the command object to test
@@ -351,11 +351,10 @@ class TestDeleteNetworkSegmentRange(TestNetworkSegmentRange):
def setUp(self):
super().setUp()
- self.network_client.delete_network_segment_range = mock.Mock(
- return_value=None
- )
- self.network_client.find_network_segment_range = mock.Mock(
- side_effect=self._network_segment_ranges
+ self.network_client.delete_network_segment_range.return_value = None
+
+ self.network_client.find_network_segment_range.side_effect = (
+ self._network_segment_ranges
)
# Get the command object to test
@@ -412,8 +411,8 @@ class TestDeleteNetworkSegmentRange(TestNetworkSegmentRange):
self._network_segment_ranges[0],
exceptions.CommandError,
]
- self.network_client.find_network_segment_range = mock.Mock(
- side_effect=find_mock_result
+ self.network_client.find_network_segment_range.side_effect = (
+ find_mock_result
)
try:
@@ -493,8 +492,8 @@ class TestListNetworkSegmentRange(TestNetworkSegmentRange):
def setUp(self):
super().setUp()
- self.network_client.network_segment_ranges = mock.Mock(
- return_value=self._network_segment_ranges
+ self.network_client.network_segment_ranges.return_value = (
+ self._network_segment_ranges
)
# Get the command object to test
@@ -567,8 +566,8 @@ class TestSetNetworkSegmentRange(TestNetworkSegmentRange):
def setUp(self):
super().setUp()
- self.network_client.find_network_segment_range = mock.Mock(
- return_value=self._network_segment_range
+ self.network_client.find_network_segment_range.return_value = (
+ self._network_segment_range
)
# Get the command object to test
@@ -583,9 +582,10 @@ class TestSetNetworkSegmentRange(TestNetworkSegmentRange):
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- self.network_client.update_network_segment_range = mock.Mock(
- return_value=self._network_segment_range
+ self.network_client.update_network_segment_range.return_value = (
+ self._network_segment_range
)
+
result = self.cmd.take_action(parsed_args)
self.network_client.update_network_segment_range.assert_called_once_with(
@@ -611,9 +611,10 @@ class TestSetNetworkSegmentRange(TestNetworkSegmentRange):
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- self.network_client.update_network_segment_range = mock.Mock(
- return_value=self._network_segment_range_updated
+ self.network_client.update_network_segment_range.return_value = (
+ self._network_segment_range_updated
)
+
result = self.cmd.take_action(parsed_args)
attrs = {
@@ -662,8 +663,8 @@ class TestShowNetworkSegmentRange(TestNetworkSegmentRange):
def setUp(self):
super().setUp()
- self.network_client.find_network_segment_range = mock.Mock(
- return_value=self._network_segment_range
+ self.network_client.find_network_segment_range.return_value = (
+ self._network_segment_range
)
# Get the command object to test
diff --git a/openstackclient/tests/unit/network/v2/test_network_service_provider.py b/openstackclient/tests/unit/network/v2/test_network_service_provider.py
index 9f61bce..f84bcd3 100644
--- a/openstackclient/tests/unit/network/v2/test_network_service_provider.py
+++ b/openstackclient/tests/unit/network/v2/test_network_service_provider.py
@@ -13,7 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-from unittest import mock
from openstackclient.network.v2 import (
network_service_provider as service_provider,
@@ -52,9 +51,7 @@ class TestListNetworkServiceProvider(TestNetworkServiceProvider):
def setUp(self):
super().setUp()
- self.network_client.service_providers = mock.Mock(
- return_value=self.provider_list
- )
+ self.network_client.service_providers.return_value = self.provider_list
self.cmd = service_provider.ListNetworkServiceProvider(self.app, None)
diff --git a/openstackclient/tests/unit/network/v2/test_network_trunk.py b/openstackclient/tests/unit/network/v2/test_network_trunk.py
index 180e80d..1056c21 100644
--- a/openstackclient/tests/unit/network/v2/test_network_trunk.py
+++ b/openstackclient/tests/unit/network/v2/test_network_trunk.py
@@ -11,7 +11,6 @@
# under the License.
import copy
-from unittest import mock
from unittest.mock import call
from osc_lib.cli import format_columns
@@ -84,12 +83,12 @@ class TestCreateNetworkTrunk(TestNetworkTrunk):
def setUp(self):
super().setUp()
- self.network_client.create_trunk = mock.Mock(
- return_value=self.new_trunk
- )
- self.network_client.find_port = mock.Mock(
- side_effect=[self.parent_port, self.sub_port]
- )
+ self.network_client.create_trunk.return_value = self.new_trunk
+
+ self.network_client.find_port.side_effect = [
+ self.parent_port,
+ self.sub_port,
+ ]
# Get the command object to test
self.cmd = network_trunk.CreateNetworkTrunk(self.app, None)
@@ -313,13 +312,16 @@ class TestDeleteNetworkTrunk(TestNetworkTrunk):
def setUp(self):
super().setUp()
- self.network_client.find_trunk = mock.Mock(
- side_effect=[self.new_trunks[0], self.new_trunks[1]]
- )
- self.network_client.delete_trunk = mock.Mock(return_value=None)
- self.network_client.find_port = mock.Mock(
- side_effect=[self.parent_port, self.sub_port]
- )
+ self.network_client.find_trunk.side_effect = [
+ self.new_trunks[0],
+ self.new_trunks[1],
+ ]
+
+ self.network_client.delete_trunk.return_value = None
+ self.network_client.find_port.side_effect = [
+ self.parent_port,
+ self.sub_port,
+ ]
self.projects_mock.get.return_value = self.project
self.domains_mock.get.return_value = self.domain
@@ -371,9 +373,11 @@ class TestDeleteNetworkTrunk(TestNetworkTrunk):
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- self.network_client.find_trunk = mock.Mock(
- side_effect=[self.new_trunks[0], exceptions.CommandError]
- )
+ self.network_client.find_trunk.side_effect = [
+ self.new_trunks[0],
+ exceptions.CommandError,
+ ]
+
with testtools.ExpectedException(exceptions.CommandError) as e:
self.cmd.take_action(parsed_args)
self.assertEqual('1 of 2 trunks failed to delete.', str(e))
@@ -412,8 +416,8 @@ class TestShowNetworkTrunk(TestNetworkTrunk):
def setUp(self):
super().setUp()
- self.network_client.find_trunk = mock.Mock(return_value=self.new_trunk)
- self.network_client.get_trunk = mock.Mock(return_value=self.new_trunk)
+ self.network_client.find_trunk.return_value = self.new_trunk
+ self.network_client.get_trunk.return_value = self.new_trunk
self.projects_mock.get.return_value = self.project
self.domains_mock.get.return_value = self.domain
@@ -485,7 +489,7 @@ class TestListNetworkTrunk(TestNetworkTrunk):
def setUp(self):
super().setUp()
- self.network_client.trunks = mock.Mock(return_value=self.new_trunks)
+ self.network_client.trunks.return_value = self.new_trunks
self.projects_mock.get.return_value = self.project
self.domains_mock.get.return_value = self.domain
@@ -564,14 +568,14 @@ class TestSetNetworkTrunk(TestNetworkTrunk):
def setUp(self):
super().setUp()
- self.network_client.update_trunk = mock.Mock(return_value=self._trunk)
- self.network_client.add_trunk_subports = mock.Mock(
- return_value=self._trunk
- )
- self.network_client.find_trunk = mock.Mock(return_value=self._trunk)
- self.network_client.find_port = mock.Mock(
- side_effect=[self.sub_port, self.sub_port]
- )
+ self.network_client.update_trunk.return_value = self._trunk
+ self.network_client.add_trunk_subports.return_value = self._trunk
+
+ self.network_client.find_trunk.return_value = self._trunk
+ self.network_client.find_port.side_effect = [
+ self.sub_port,
+ self.sub_port,
+ ]
self.projects_mock.get.return_value = self.project
self.domains_mock.get.return_value = self.domain
@@ -763,9 +767,8 @@ class TestSetNetworkTrunk(TestNetworkTrunk):
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- self.network_client.update_trunk = mock.Mock(
- side_effect=exceptions.CommandError
- )
+ self.network_client.update_trunk.side_effect = exceptions.CommandError
+
with testtools.ExpectedException(exceptions.CommandError) as e:
self.cmd.take_action(parsed_args)
self.assertEqual(
@@ -790,12 +793,14 @@ class TestSetNetworkTrunk(TestNetworkTrunk):
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
- self.network_client.add_trunk_subports = mock.Mock(
- side_effect=exceptions.CommandError
- )
- self.network_client.find_port = mock.Mock(
- return_value={'id': 'invalid_subport'}
+ self.network_client.add_trunk_subports.side_effect = (
+ exceptions.CommandError
)
+
+ self.network_client.find_port.side_effect = [
+ network_fakes.create_one_port({'id': 'invalid_subport'})
+ ]
+
with testtools.ExpectedException(exceptions.CommandError) as e:
self.cmd.take_action(parsed_args)
self.assertEqual(
@@ -832,10 +837,10 @@ class TestListNetworkSubport(TestNetworkTrunk):
def setUp(self):
super().setUp()
- self.network_client.find_trunk = mock.Mock(return_value=self._trunk)
- self.network_client.get_trunk_subports = mock.Mock(
- return_value={network_trunk.SUB_PORTS: self._subports}
- )
+ self.network_client.find_trunk.return_value = self._trunk
+ self.network_client.get_trunk_subports.return_value = {
+ network_trunk.SUB_PORTS: self._subports
+ }
# Get the command object to test
self.cmd = network_trunk.ListNetworkSubport(self.app, None)
@@ -902,13 +907,13 @@ class TestUnsetNetworkTrunk(TestNetworkTrunk):
def setUp(self):
super().setUp()
- self.network_client.find_trunk = mock.Mock(return_value=self._trunk)
- self.network_client.find_port = mock.Mock(
- side_effect=[self.sub_port, self.sub_port]
- )
- self.network_client.delete_trunk_subports = mock.Mock(
- return_value=None
- )
+ self.network_client.find_trunk.return_value = self._trunk
+ self.network_client.find_port.side_effect = [
+ self.sub_port,
+ self.sub_port,
+ ]
+
+ self.network_client.delete_trunk_subports.return_value = None
# Get the command object to test
self.cmd = network_trunk.UnsetNetworkTrunk(self.app, None)
diff --git a/openstackclient/tests/unit/network/v2/test_port.py b/openstackclient/tests/unit/network/v2/test_port.py
index 0611be4..11a8711 100644
--- a/openstackclient/tests/unit/network/v2/test_port.py
+++ b/openstackclient/tests/unit/network/v2/test_port.py
@@ -136,19 +136,18 @@ class TestCreatePort(TestPort):
def setUp(self):
super().setUp()
- self.network_client.create_port = mock.Mock(return_value=self._port)
- self.network_client.set_tags = mock.Mock(return_value=None)
+ self.network_client.create_port.return_value = self._port
+ self.network_client.set_tags.return_value = None
fake_net = network_fakes.create_one_network(
{
'id': self._port.network_id,
}
)
- self.network_client.find_network = mock.Mock(return_value=fake_net)
+ self.network_client.find_network.return_value = fake_net
self.fake_subnet = network_fakes.FakeSubnet.create_one_subnet()
- self.network_client.find_subnet = mock.Mock(
- return_value=self.fake_subnet
- )
- self.network_client.find_extension = mock.Mock(return_value=[])
+ self.network_client.find_subnet.return_value = self.fake_subnet
+
+ self.network_client.find_extension.return_value = []
# Get the command object to test
self.cmd = port.CreatePort(self.app, None)
@@ -321,9 +320,8 @@ class TestCreatePort(TestPort):
def test_create_with_security_group(self):
secgroup = network_fakes.create_one_security_group()
- self.network_client.find_security_group = mock.Mock(
- return_value=secgroup
- )
+ self.network_client.find_security_group.return_value = secgroup
+
arglist = [
'--network',
self._port.network_id,
@@ -393,9 +391,8 @@ class TestCreatePort(TestPort):
def test_create_with_security_groups(self):
sg_1 = network_fakes.create_one_security_group()
sg_2 = network_fakes.create_one_security_group()
- self.network_client.find_security_group = mock.Mock(
- side_effect=[sg_1, sg_2]
- )
+ self.network_client.find_security_group.side_effect = [sg_1, sg_2]
+
arglist = [
'--network',
self._port.network_id,
@@ -583,9 +580,8 @@ class TestCreatePort(TestPort):
def test_create_port_with_qos(self):
qos_policy = network_fakes.create_one_qos_policy()
- self.network_client.find_qos_policy = mock.Mock(
- return_value=qos_policy
- )
+ self.network_client.find_qos_policy.return_value = qos_policy
+
arglist = [
'--network',
self._port.network_id,
@@ -701,9 +697,7 @@ class TestCreatePort(TestPort):
else:
verifylist.append(('no_tag', True))
- self.network_client.find_extension = mock.Mock(
- return_value=add_tags_in_post
- )
+ self.network_client.find_extension.return_value = add_tags_in_post
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
@@ -1170,7 +1164,7 @@ class TestDeletePort(TestPort):
def setUp(self):
super().setUp()
- self.network_client.delete_port = mock.Mock(return_value=None)
+ self.network_client.delete_port.return_value = None
self.network_client.find_port = network_fakes.get_ports(
ports=self._ports
)
@@ -1223,7 +1217,7 @@ class TestDeletePort(TestPort):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
find_mock_result = [self._ports[0], exceptions.CommandError]
- self.network_client.find_port = mock.Mock(side_effect=find_mock_result)
+ self.network_client.find_port.side_effect = find_mock_result
try:
self.cmd.take_action(parsed_args)
@@ -1324,7 +1318,7 @@ class TestListPort(compute_fakes.FakeClientMixin, TestPort):
def setUp(self):
super().setUp()
- self.network_client.ports = mock.Mock(return_value=self._ports)
+ self.network_client.ports.return_value = self._ports
fake_router = network_fakes.create_one_router(
{
'id': 'fake-router-id',
@@ -1335,8 +1329,8 @@ class TestListPort(compute_fakes.FakeClientMixin, TestPort):
'id': 'fake-network-id',
}
)
- self.network_client.find_router = mock.Mock(return_value=fake_router)
- self.network_client.find_network = mock.Mock(return_value=fake_network)
+ self.network_client.find_router.return_value = fake_router
+ self.network_client.find_network.return_value = fake_network
# Get the command object to test
self.cmd = port.ListPort(self.app, None)
@@ -1550,9 +1544,8 @@ class TestListPort(compute_fakes.FakeClientMixin, TestPort):
self.fake_subnet = network_fakes.FakeSubnet.create_one_subnet(
{'id': subnet_id}
)
- self.network_client.find_subnet = mock.Mock(
- return_value=self.fake_subnet
- )
+ self.network_client.find_subnet.return_value = self.fake_subnet
+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
@@ -1579,9 +1572,8 @@ class TestListPort(compute_fakes.FakeClientMixin, TestPort):
self.fake_subnet = network_fakes.FakeSubnet.create_one_subnet(
{'id': subnet_id}
)
- self.network_client.find_subnet = mock.Mock(
- return_value=self.fake_subnet
- )
+ self.network_client.find_subnet.return_value = self.fake_subnet
+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
@@ -1616,9 +1608,8 @@ class TestListPort(compute_fakes.FakeClientMixin, TestPort):
'fields': LIST_FIELDS_TO_RETRIEVE,
}
)
- self.network_client.find_subnet = mock.Mock(
- return_value=self.fake_subnet
- )
+ self.network_client.find_subnet.return_value = self.fake_subnet
+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
@@ -1825,12 +1816,11 @@ class TestSetPort(TestPort):
def setUp(self):
super().setUp()
self.fake_subnet = network_fakes.FakeSubnet.create_one_subnet()
- self.network_client.find_subnet = mock.Mock(
- return_value=self.fake_subnet
- )
- self.network_client.find_port = mock.Mock(return_value=self._port)
- self.network_client.update_port = mock.Mock(return_value=None)
- self.network_client.set_tags = mock.Mock(return_value=None)
+ self.network_client.find_subnet.return_value = self.fake_subnet
+
+ self.network_client.find_port.return_value = self._port
+ self.network_client.update_port.return_value = None
+ self.network_client.set_tags.return_value = None
# Get the command object to test
self.cmd = port.SetPort(self.app, None)
@@ -1853,7 +1843,7 @@ class TestSetPort(TestPort):
_testport = network_fakes.create_one_port(
{'fixed_ips': [{'ip_address': '0.0.0.1'}]}
)
- self.network_client.find_port = mock.Mock(return_value=_testport)
+ self.network_client.find_port.return_value = _testport
arglist = [
'--fixed-ip',
'ip-address=10.0.0.12',
@@ -1881,7 +1871,7 @@ class TestSetPort(TestPort):
_testport = network_fakes.create_one_port(
{'fixed_ips': [{'ip_address': '0.0.0.1'}]}
)
- self.network_client.find_port = mock.Mock(return_value=_testport)
+ self.network_client.find_port.return_value = _testport
arglist = [
'--fixed-ip',
'ip-address=10.0.0.12',
@@ -1931,7 +1921,7 @@ class TestSetPort(TestPort):
_testport = network_fakes.create_one_port(
{'binding_profile': {'lok_i': 'visi_on'}}
)
- self.network_client.find_port = mock.Mock(return_value=_testport)
+ self.network_client.find_port.return_value = _testport
arglist = [
'--binding-profile',
'lok_i=than_os',
@@ -1956,7 +1946,7 @@ class TestSetPort(TestPort):
_testport = network_fakes.create_one_port(
{'mac_address': '11:22:33:44:55:66'}
)
- self.network_client.find_port = mock.Mock(return_value=_testport)
+ self.network_client.find_port.return_value = _testport
arglist = [
'--mac-address',
'66:55:44:33:22:11',
@@ -2097,7 +2087,7 @@ class TestSetPort(TestPort):
def test_set_port_security_group(self):
sg = network_fakes.create_one_security_group()
- self.network_client.find_security_group = mock.Mock(return_value=sg)
+ self.network_client.find_security_group.return_value = sg
arglist = [
'--security-group',
sg.id,
@@ -2122,13 +2112,12 @@ class TestSetPort(TestPort):
sg_1 = network_fakes.create_one_security_group()
sg_2 = network_fakes.create_one_security_group()
sg_3 = network_fakes.create_one_security_group()
- self.network_client.find_security_group = mock.Mock(
- side_effect=[sg_2, sg_3]
- )
+ self.network_client.find_security_group.side_effect = [sg_2, sg_3]
+
_testport = network_fakes.create_one_port(
{'security_group_ids': [sg_1.id]}
)
- self.network_client.find_port = mock.Mock(return_value=_testport)
+ self.network_client.find_port.return_value = _testport
arglist = [
'--security-group',
sg_2.id,
@@ -2177,8 +2166,8 @@ class TestSetPort(TestPort):
_testport = network_fakes.create_one_port(
{'security_group_ids': [sg1.id]}
)
- self.network_client.find_port = mock.Mock(return_value=_testport)
- self.network_client.find_security_group = mock.Mock(return_value=sg2)
+ self.network_client.find_port.return_value = _testport
+ self.network_client.find_security_group.return_value = sg2
arglist = [
'--security-group',
sg2.id,
@@ -2226,7 +2215,7 @@ class TestSetPort(TestPort):
_testport = network_fakes.create_one_port(
{'allowed_address_pairs': [{'ip_address': '192.168.1.123'}]}
)
- self.network_client.find_port = mock.Mock(return_value=_testport)
+ self.network_client.find_port.return_value = _testport
arglist = [
'--allowed-address',
'ip-address=192.168.1.45',
@@ -2255,7 +2244,7 @@ class TestSetPort(TestPort):
_testport = network_fakes.create_one_port(
{'allowed_address_pairs': [{'ip_address': '192.168.1.123'}]}
)
- self.network_client.find_port = mock.Mock(return_value=_testport)
+ self.network_client.find_port.return_value = _testport
arglist = [
'--allowed-address',
'ip-address=192.168.1.45',
@@ -2372,11 +2361,10 @@ class TestSetPort(TestPort):
def test_set_port_with_qos(self):
qos_policy = network_fakes.create_one_qos_policy()
- self.network_client.find_qos_policy = mock.Mock(
- return_value=qos_policy
- )
+ self.network_client.find_qos_policy.return_value = qos_policy
+
_testport = network_fakes.create_one_port({'qos_policy_id': None})
- self.network_client.find_port = mock.Mock(return_value=_testport)
+ self.network_client.find_port.return_value = _testport
arglist = [
'--qos-policy',
qos_policy.id,
@@ -2400,7 +2388,7 @@ class TestSetPort(TestPort):
def test_set_port_data_plane_status(self):
_testport = network_fakes.create_one_port({'data_plane_status': None})
- self.network_client.find_port = mock.Mock(return_value=_testport)
+ self.network_client.find_port.return_value = _testport
arglist = [
'--data-plane-status',
'ACTIVE',
@@ -2546,10 +2534,12 @@ class TestSetPort(TestPort):
def test_set_hints_valid_alias_value(self):
testport = network_fakes.create_one_port()
- self.network_client.find_port = mock.Mock(return_value=testport)
- self.network_client.find_extension = mock.Mock(
- return_value=['port-hints', 'port-hint-ovs-tx-steering']
- )
+ self.network_client.find_port.return_value = testport
+ self.network_client.find_extension.return_value = [
+ 'port-hints',
+ 'port-hint-ovs-tx-steering',
+ ]
+
arglist = [
'--hint',
'ovs-tx-steering=hash',
@@ -2574,10 +2564,12 @@ class TestSetPort(TestPort):
def test_set_hints_valid_json(self):
testport = network_fakes.create_one_port()
- self.network_client.find_port = mock.Mock(return_value=testport)
- self.network_client.find_extension = mock.Mock(
- return_value=['port-hints', 'port-hint-ovs-tx-steering']
- )
+ self.network_client.find_port.return_value = testport
+ self.network_client.find_extension.return_value = [
+ 'port-hints',
+ 'port-hint-ovs-tx-steering',
+ ]
+
arglist = [
'--hint',
'{"openvswitch": {"other_config": {"tx-steering": "hash"}}}',
@@ -2670,7 +2662,7 @@ class TestShowPort(TestPort):
def setUp(self):
super().setUp()
- self.network_client.find_port = mock.Mock(return_value=self._port)
+ self.network_client.find_port.return_value = self._port
# Get the command object to test
self.cmd = port.ShowPort(self.app, None)
@@ -2731,12 +2723,11 @@ class TestUnsetPort(TestPort):
self.fake_subnet = network_fakes.FakeSubnet.create_one_subnet(
{'id': '042eb10a-3a18-4658-ab-cf47c8d03152'}
)
- self.network_client.find_subnet = mock.Mock(
- return_value=self.fake_subnet
- )
- self.network_client.find_port = mock.Mock(return_value=self._testport)
- self.network_client.update_port = mock.Mock(return_value=None)
- self.network_client.set_tags = mock.Mock(return_value=None)
+ self.network_client.find_subnet.return_value = self.fake_subnet
+
+ self.network_client.find_port.return_value = self._testport
+ self.network_client.update_port.return_value = None
+ self.network_client.set_tags.return_value = None
# Get the command object to test
self.cmd = port.UnsetPort(self.app, None)
@@ -2826,10 +2817,9 @@ class TestUnsetPort(TestPort):
_fake_port = network_fakes.create_one_port(
{'security_group_ids': [_fake_sg1.id, _fake_sg2.id]}
)
- self.network_client.find_port = mock.Mock(return_value=_fake_port)
- self.network_client.find_security_group = mock.Mock(
- return_value=_fake_sg2
- )
+ self.network_client.find_port.return_value = _fake_port
+ self.network_client.find_security_group.return_value = _fake_sg2
+
arglist = [
'--security-group',
_fake_sg2.id,
@@ -2854,9 +2844,8 @@ class TestUnsetPort(TestPort):
_fake_port = network_fakes.create_one_port(
{'security_group_ids': [_fake_sg1.id]}
)
- self.network_client.find_security_group = mock.Mock(
- return_value=_fake_sg2
- )
+ self.network_client.find_security_group.return_value = _fake_sg2
+
arglist = [
'--security-group',
_fake_sg2.id,
@@ -2875,7 +2864,7 @@ class TestUnsetPort(TestPort):
_fake_port = network_fakes.create_one_port(
{'allowed_address_pairs': [{'ip_address': '192.168.1.123'}]}
)
- self.network_client.find_port = mock.Mock(return_value=_fake_port)
+ self.network_client.find_port.return_value = _fake_port
arglist = [
'--allowed-address',
'ip-address=192.168.1.123',
@@ -2901,7 +2890,7 @@ class TestUnsetPort(TestPort):
_fake_port = network_fakes.create_one_port(
{'allowed_address_pairs': [{'ip_address': '192.168.1.123'}]}
)
- self.network_client.find_port = mock.Mock(return_value=_fake_port)
+ self.network_client.find_port.return_value = _fake_port
arglist = [
'--allowed-address',
'ip-address=192.168.1.45',
@@ -2920,7 +2909,7 @@ class TestUnsetPort(TestPort):
_fake_port = network_fakes.create_one_port(
{'data_plane_status': 'ACTIVE'}
)
- self.network_client.find_port = mock.Mock(return_value=_fake_port)
+ self.network_client.find_port.return_value = _fake_port
arglist = [
'--data-plane-status',
_fake_port.name,
@@ -2973,7 +2962,7 @@ class TestUnsetPort(TestPort):
_fake_port = network_fakes.create_one_port(
{'numa_affinity_policy': 'required'}
)
- self.network_client.find_port = mock.Mock(return_value=_fake_port)
+ self.network_client.find_port.return_value = _fake_port
arglist = [
'--numa-policy',
_fake_port.name,
@@ -2997,7 +2986,7 @@ class TestUnsetPort(TestPort):
def test_unset_hints(self):
testport = network_fakes.create_one_port()
- self.network_client.find_port = mock.Mock(return_value=testport)
+ self.network_client.find_port.return_value = testport
arglist = [
'--hints',
testport.name,
@@ -3017,7 +3006,7 @@ class TestUnsetPort(TestPort):
def test_unset_device(self):
testport = network_fakes.create_one_port()
- self.network_client.find_port = mock.Mock(return_value=testport)
+ self.network_client.find_port.return_value = testport
arglist = [
'--device',
testport.name,
@@ -3037,7 +3026,7 @@ class TestUnsetPort(TestPort):
def test_unset_device_owner(self):
testport = network_fakes.create_one_port()
- self.network_client.find_port = mock.Mock(return_value=testport)
+ self.network_client.find_port.return_value = testport
arglist = [
'--device-owner',
testport.name,
diff --git a/openstackclient/tests/unit/network/v2/test_router.py b/openstackclient/tests/unit/network/v2/test_router.py
index 3536583..6ebb780 100644
--- a/openstackclient/tests/unit/network/v2/test_router.py
+++ b/openstackclient/tests/unit/network/v2/test_router.py
@@ -39,8 +39,8 @@ class TestAddPortToRouter(TestRouter):
def setUp(self):
super().setUp()
- self.network_client.find_router = mock.Mock(return_value=self._router)
- self.network_client.find_port = mock.Mock(return_value=self._port)
+ self.network_client.find_router.return_value = self._router
+ self.network_client.find_port.return_value = self._port
self.cmd = router.AddPortToRouter(self.app, None)
@@ -87,8 +87,8 @@ class TestAddSubnetToRouter(TestRouter):
def setUp(self):
super().setUp()
- self.network_client.find_router = mock.Mock(return_value=self._router)
- self.network_client.find_subnet = mock.Mock(return_value=self._subnet)
+ self.network_client.find_router.return_value = self._router
+ self.network_client.find_subnet.return_value = self._subnet
self.cmd = router.AddSubnetToRouter(self.app, None)
@@ -172,12 +172,11 @@ class TestCreateRouter(TestRouter):
def setUp(self):
super().setUp()
- self.network_client.create_router = mock.Mock(
- return_value=self.new_router
- )
- self.network_client.set_tags = mock.Mock(return_value=None)
- self.network_client.find_extension = mock.Mock(
- side_effect=lambda name: self._extensions.get(name)
+ self.network_client.create_router.return_value = self.new_router
+
+ self.network_client.set_tags.return_value = None
+ self.network_client.find_extension.side_effect = (
+ lambda name, ignore_missing=True: self._extensions.get(name)
)
# Get the command object to test
self.cmd = router.CreateRouter(self.app, None)
@@ -222,8 +221,8 @@ class TestCreateRouter(TestRouter):
def test_create_with_gateway(self):
_network = network_fakes.create_one_network()
_subnet = network_fakes.FakeSubnet.create_one_subnet()
- self.network_client.find_network = mock.Mock(return_value=_network)
- self.network_client.find_subnet = mock.Mock(return_value=_subnet)
+ self.network_client.find_network.return_value = _network
+ self.network_client.find_subnet.return_value = _subnet
arglist = [
self.new_router.name,
'--external-gateway',
@@ -392,7 +391,7 @@ class TestCreateRouter(TestRouter):
def test_create_with_flavor_id_id(self):
_flavor = network_fakes.create_one_network_flavor()
- self.network_client.find_flavor = mock.Mock(return_value=_flavor)
+ self.network_client.find_flavor.return_value = _flavor
arglist = [
self.new_router.name,
'--flavor-id',
@@ -419,7 +418,7 @@ class TestCreateRouter(TestRouter):
def test_create_with_flavor_id_name(self):
_flavor = network_fakes.create_one_network_flavor()
- self.network_client.find_flavor = mock.Mock(return_value=_flavor)
+ self.network_client.find_flavor.return_value = _flavor
arglist = [self.new_router.name, '--flavor-id', _flavor.name]
verifylist = [
('name', self.new_router.name),
@@ -442,7 +441,7 @@ class TestCreateRouter(TestRouter):
def test_create_with_flavor_id(self):
_flavor = network_fakes.create_one_network_flavor()
- self.network_client.find_flavor = mock.Mock(return_value=_flavor)
+ self.network_client.find_flavor.return_value = _flavor
arglist = [
self.new_router.name,
'--flavor',
@@ -469,7 +468,7 @@ class TestCreateRouter(TestRouter):
def test_create_with_flavor_name(self):
_flavor = network_fakes.create_one_network_flavor()
- self.network_client.find_flavor = mock.Mock(return_value=_flavor)
+ self.network_client.find_flavor.return_value = _flavor
arglist = [self.new_router.name, '--flavor', _flavor.name]
verifylist = [
('name', self.new_router.name),
@@ -491,11 +490,12 @@ class TestCreateRouter(TestRouter):
self.assertCountEqual(self.data, data)
def test_create_with_enable_default_route_bfd(self):
- self.network_client.find_extension = mock.Mock(
- return_value=network_fakes.create_one_extension(
+ self._extensions = {
+ 'external-gateway-multihoming': network_fakes.create_one_extension(
attrs={'name': 'external-gateway-multihoming'}
- )
- )
+ ),
+ }
+
arglist = [self.new_router.name, '--enable-default-route-bfd']
verifylist = [
('name', self.new_router.name),
@@ -525,11 +525,12 @@ class TestCreateRouter(TestRouter):
)
def test_create_with_enable_default_route_ecmp(self):
- self.network_client.find_extension = mock.Mock(
- return_value=network_fakes.create_one_extension(
+ self._extensions = {
+ 'external-gateway-multihoming': network_fakes.create_one_extension(
attrs={'name': 'external-gateway-multihoming'}
- )
- )
+ ),
+ }
+
arglist = [self.new_router.name, '--enable-default-route-ecmp']
verifylist = [
('name', self.new_router.name),
@@ -560,11 +561,10 @@ class TestCreateRouter(TestRouter):
def test_create_with_qos_policy(self):
_network = network_fakes.create_one_network()
- self.network_client.find_network = mock.Mock(return_value=_network)
+ self.network_client.find_network.return_value = _network
_qos_policy = network_fakes.create_one_qos_policy()
- self.network_client.find_qos_policy = mock.Mock(
- return_value=_qos_policy
- )
+ self.network_client.find_qos_policy.return_value = _qos_policy
+
arglist = [
self.new_router.name,
'--external-gateway',
@@ -595,9 +595,8 @@ class TestCreateRouter(TestRouter):
def test_create_with_qos_policy_no_external_gateway(self):
_qos_policy = network_fakes.create_one_qos_policy()
- self.network_client.find_qos_policy = mock.Mock(
- return_value=_qos_policy
- )
+ self.network_client.find_qos_policy.return_value = _qos_policy
+
arglist = [
self.new_router.name,
'--qos-policy',
@@ -625,7 +624,7 @@ class TestDeleteRouter(TestRouter):
def setUp(self):
super().setUp()
- self.network_client.delete_router = mock.Mock(return_value=None)
+ self.network_client.delete_router.return_value = None
self.network_client.find_router = network_fakes.get_routers(
self._routers
@@ -679,9 +678,7 @@ class TestDeleteRouter(TestRouter):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
find_mock_result = [self._routers[0], exceptions.CommandError]
- self.network_client.find_router = mock.Mock(
- side_effect=find_mock_result
- )
+ self.network_client.find_router.side_effect = find_mock_result
try:
self.cmd.take_action(parsed_args)
@@ -786,21 +783,16 @@ class TestListRouter(TestRouter):
# Get the command object to test
self.cmd = router.ListRouter(self.app, None)
- self.network_client.agent_hosted_routers = mock.Mock(
- return_value=self.routers
- )
- self.network_client.routers = mock.Mock(return_value=self.routers)
- self.network_client.find_extension = mock.Mock(
- return_value=self.extensions
- )
- self.network_client.find_router = mock.Mock(
- return_value=self.routers[0]
- )
+ self.network_client.agent_hosted_routers.return_value = self.routers
+
+ self.network_client.routers.return_value = self.routers
+ self.network_client.find_extension.return_value = self.extensions
+
+ self.network_client.find_router.return_value = self.routers[0]
+
self._testagent = network_fakes.create_one_network_agent()
- self.network_client.get_agent = mock.Mock(return_value=self._testagent)
- self.network_client.get_router = mock.Mock(
- return_value=self.routers[0]
- )
+ self.network_client.get_agent.return_value = self._testagent
+ self.network_client.get_router.return_value = self.routers[0]
def test_router_list_no_options(self):
arglist = []
@@ -865,7 +857,7 @@ class TestListRouter(TestRouter):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# to mock, that no availability zone
- self.network_client.find_extension = mock.Mock(return_value=None)
+ self.network_client.find_extension.return_value = None
# In base command class Lister in cliff, abstract method take_action()
# returns a tuple containing the column names and an iterable
@@ -1044,8 +1036,8 @@ class TestRemovePortFromRouter(TestRouter):
def setUp(self):
super().setUp()
- self.network_client.find_router = mock.Mock(return_value=self._router)
- self.network_client.find_port = mock.Mock(return_value=self._port)
+ self.network_client.find_router.return_value = self._router
+ self.network_client.find_port.return_value = self._port
self.cmd = router.RemovePortFromRouter(self.app, None)
@@ -1089,8 +1081,8 @@ class TestRemoveSubnetFromRouter(TestRouter):
def setUp(self):
super().setUp()
- self.network_client.find_router = mock.Mock(return_value=self._router)
- self.network_client.find_subnet = mock.Mock(return_value=self._subnet)
+ self.network_client.find_router.return_value = self._router
+ self.network_client.find_subnet.return_value = self._subnet
self.cmd = router.RemoveSubnetFromRouter(self.app, None)
@@ -1129,11 +1121,12 @@ class TestAddExtraRoutesToRouter(TestRouter):
def setUp(self):
super().setUp()
- self.network_client.add_extra_routes_to_router = mock.Mock(
- return_value=self._router
+ self.network_client.add_extra_routes_to_router.return_value = (
+ self._router
)
+
self.cmd = router.AddExtraRoutesToRouter(self.app, None)
- self.network_client.find_router = mock.Mock(return_value=self._router)
+ self.network_client.find_router.return_value = self._router
def test_add_no_extra_route(self):
arglist = [
@@ -1218,11 +1211,12 @@ class TestRemoveExtraRoutesFromRouter(TestRouter):
def setUp(self):
super().setUp()
- self.network_client.remove_extra_routes_from_router = mock.Mock(
- return_value=self._router
+ self.network_client.remove_extra_routes_from_router.return_value = (
+ self._router
)
+
self.cmd = router.RemoveExtraRoutesFromRouter(self.app, None)
- self.network_client.find_router = mock.Mock(return_value=self._router)
+ self.network_client.find_router.return_value = self._router
def test_remove_no_extra_route(self):
arglist = [
@@ -1316,15 +1310,14 @@ class TestSetRouter(TestRouter):
def setUp(self):
super().setUp()
- self.network_client.update_router = mock.Mock(return_value=None)
- self.network_client.set_tags = mock.Mock(return_value=None)
- self.network_client.find_router = mock.Mock(return_value=self._router)
- self.network_client.find_network = mock.Mock(
- return_value=self._network
- )
- self.network_client.find_subnet = mock.Mock(return_value=self._subnet)
- self.network_client.find_extension = mock.Mock(
- side_effect=lambda name: self._extensions.get(name)
+ self.network_client.update_router.return_value = None
+ self.network_client.set_tags.return_value = None
+ self.network_client.find_router.return_value = self._router
+ self.network_client.find_network.return_value = self._network
+
+ self.network_client.find_subnet.return_value = self._subnet
+ self.network_client.find_extension.side_effect = (
+ lambda name, ignore_missing=True: self._extensions.get(name)
)
# Get the command object to test
self.cmd = router.SetRouter(self.app, None)
@@ -1459,7 +1452,7 @@ class TestSetRouter(TestRouter):
_testrouter = network_fakes.create_one_router(
{'routes': [{"destination": "10.0.0.2", "nexthop": "1.1.1.1"}]}
)
- self.network_client.find_router = mock.Mock(return_value=_testrouter)
+ self.network_client.find_router.return_value = _testrouter
arglist = [
_testrouter.name,
'--route',
@@ -1667,9 +1660,8 @@ class TestSetRouter(TestRouter):
def test_set_gateway_ip_qos(self):
qos_policy = network_fakes.create_one_qos_policy()
- self.network_client.find_qos_policy = mock.Mock(
- return_value=qos_policy
- )
+ self.network_client.find_qos_policy.return_value = qos_policy
+
arglist = [
"--external-gateway",
self._network.id,
@@ -1724,9 +1716,8 @@ class TestSetRouter(TestRouter):
def test_set_unset_gateway_ip_qos(self):
qos_policy = network_fakes.create_one_qos_policy()
- self.network_client.find_qos_policy = mock.Mock(
- return_value=qos_policy
- )
+ self.network_client.find_qos_policy.return_value = qos_policy
+
arglist = [
"--external-gateway",
self._network.id,
@@ -1752,11 +1743,10 @@ class TestSetRouter(TestRouter):
def test_set_gateway_ip_qos_no_gateway(self):
qos_policy = network_fakes.create_one_qos_policy()
- self.network_client.find_qos_policy = mock.Mock(
- return_value=qos_policy
- )
+ self.network_client.find_qos_policy.return_value = qos_policy
+
router = network_fakes.create_one_router()
- self.network_client.find_router = mock.Mock(return_value=router)
+ self.network_client.find_router.return_value = router
arglist = [
"--qos-policy",
qos_policy.id,
@@ -1774,11 +1764,10 @@ class TestSetRouter(TestRouter):
def test_unset_gateway_ip_qos_no_gateway(self):
qos_policy = network_fakes.create_one_qos_policy()
- self.network_client.find_qos_policy = mock.Mock(
- return_value=qos_policy
- )
+ self.network_client.find_qos_policy.return_value = qos_policy
+
router = network_fakes.create_one_router()
- self.network_client.find_router = mock.Mock(return_value=router)
+ self.network_client.find_router.return_value = router
arglist = [
"--no-qos-policy",
router.id,
@@ -1857,8 +1846,8 @@ class TestShowRouter(TestRouter):
def setUp(self):
super().setUp()
- self.network_client.find_router = mock.Mock(return_value=self._router)
- self.network_client.ports = mock.Mock(return_value=[self._port])
+ self.network_client.find_router.return_value = self._router
+ self.network_client.ports.return_value = [self._port]
# Get the command object to test
self.cmd = router.ShowRouter(self.app, None)
@@ -1961,18 +1950,16 @@ class TestUnsetRouter(TestRouter):
}
)
self.fake_subnet = network_fakes.FakeSubnet.create_one_subnet()
- self.network_client.find_router = mock.Mock(
- return_value=self._testrouter
- )
- self.network_client.update_router = mock.Mock(return_value=None)
- self.network_client.set_tags = mock.Mock(return_value=None)
+ self.network_client.find_router.return_value = self._testrouter
+
+ self.network_client.update_router.return_value = None
+ self.network_client.set_tags.return_value = None
self._extensions = {'fake': network_fakes.create_one_extension()}
- self.network_client.find_extension = mock.Mock(
- side_effect=lambda name: self._extensions.get(name)
- )
- self.network_client.remove_external_gateways = mock.Mock(
- return_value=None
+ self.network_client.find_extension.side_effect = (
+ lambda name, ignore_missing=True: self._extensions.get(name)
)
+ self.network_client.remove_external_gateways.return_value = None
+
# Get the command object to test
self.cmd = router.UnsetRouter(self.app, None)
@@ -2109,11 +2096,10 @@ class TestUnsetRouter(TestRouter):
def test_unset_gateway_ip_qos_no_network(self):
qos_policy = network_fakes.create_one_qos_policy()
- self.network_client.find_qos_policy = mock.Mock(
- return_value=qos_policy
- )
+ self.network_client.find_qos_policy.return_value = qos_policy
+
router = network_fakes.create_one_router()
- self.network_client.find_router = mock.Mock(return_value=router)
+ self.network_client.find_router.return_value = router
arglist = [
"--qos-policy",
router.id,
@@ -2129,13 +2115,12 @@ class TestUnsetRouter(TestRouter):
def test_unset_gateway_ip_qos_no_qos(self):
qos_policy = network_fakes.create_one_qos_policy()
- self.network_client.find_qos_policy = mock.Mock(
- return_value=qos_policy
- )
+ self.network_client.find_qos_policy.return_value = qos_policy
+
router = network_fakes.create_one_router(
{"external_gateway_info": {"network_id": "fake-id"}}
)
- self.network_client.find_router = mock.Mock(return_value=router)
+ self.network_client.find_router.return_value = router
arglist = [
"--qos-policy",
router.id,
@@ -2172,10 +2157,10 @@ class TestGatewayOps(TestRouter):
attrs={'name': 'external-gateway-multihoming'}
)
}
- self.network_client.find_extension = mock.Mock(
- side_effect=lambda name: self._extensions.get(name)
+ self.network_client.find_extension.side_effect = (
+ lambda name, ignore_missing=True: self._extensions.get(name)
)
- self.network_client.find_router = mock.Mock(return_value=self._router)
+ self.network_client.find_router.return_value = self._router
def _find_network(name_or_id, ignore_missing):
for network in self._networks:
@@ -2185,15 +2170,12 @@ class TestGatewayOps(TestRouter):
return None
raise Exception('Test resource not found')
- self.network_client.find_network = mock.Mock(side_effect=_find_network)
+ self.network_client.find_network.side_effect = _find_network
- self.network_client.find_subnet = mock.Mock(return_value=self._subnet)
- self.network_client.add_external_gateways = mock.Mock(
- return_value=None
- )
- self.network_client.remove_external_gateways = mock.Mock(
- return_value=None
- )
+ self.network_client.find_subnet.return_value = self._subnet
+ self.network_client.add_external_gateways.return_value = None
+
+ self.network_client.remove_external_gateways.return_value = None
class TestCreateMultipleGateways(TestGatewayOps):
@@ -2223,13 +2205,10 @@ class TestCreateMultipleGateways(TestGatewayOps):
self._second_network = network_fakes.create_one_network()
self._networks.append(self._second_network)
- self.network_client.create_router = mock.Mock(
- return_value=self._router
- )
- self.network_client.update_router = mock.Mock(return_value=None)
- self.network_client.update_external_gateways = mock.Mock(
- return_value=None
- )
+ self.network_client.create_router.return_value = self._router
+
+ self.network_client.update_router.return_value = None
+ self.network_client.update_external_gateways.return_value = None
self._data = (
router.AdminStateColumn(self._router.is_admin_state_up),
@@ -2353,10 +2332,9 @@ class TestUpdateMultipleGateways(TestGatewayOps):
self._second_network = network_fakes.create_one_network()
self._networks.append(self._second_network)
- self.network_client.update_router = mock.Mock(return_value=None)
- self.network_client.update_external_gateways = mock.Mock(
- return_value=None
- )
+ self.network_client.update_router.return_value = None
+ self.network_client.update_external_gateways.return_value = None
+
self.cmd = router.SetRouter(self.app, None)
def test_update_one_gateway(self):
diff --git a/openstackclient/tests/unit/network/v2/test_security_group_network.py b/openstackclient/tests/unit/network/v2/test_security_group_network.py
index 9bf1f67..c5ccf62 100644
--- a/openstackclient/tests/unit/network/v2/test_security_group_network.py
+++ b/openstackclient/tests/unit/network/v2/test_security_group_network.py
@@ -11,7 +11,6 @@
# under the License.
#
-from unittest import mock
from unittest.mock import call
from osc_lib import exceptions
@@ -69,13 +68,13 @@ class TestCreateSecurityGroupNetwork(TestSecurityGroupNetwork):
def setUp(self):
super().setUp()
- self.network_client.create_security_group = mock.Mock(
- return_value=self._security_group
+ self.network_client.create_security_group.return_value = (
+ self._security_group
)
self.projects_mock.get.return_value = self.project
self.domains_mock.get.return_value = self.domain
- self.network_client.set_tags = mock.Mock(return_value=None)
+ self.network_client.set_tags.return_value = None
# Get the command object to test
self.cmd = security_group.CreateSecurityGroup(self.app, None)
@@ -185,9 +184,7 @@ class TestDeleteSecurityGroupNetwork(TestSecurityGroupNetwork):
def setUp(self):
super().setUp()
- self.network_client.delete_security_group = mock.Mock(
- return_value=None
- )
+ self.network_client.delete_security_group.return_value = None
self.network_client.find_security_group = (
network_fakes.get_security_groups(self._security_groups)
@@ -245,9 +242,7 @@ class TestDeleteSecurityGroupNetwork(TestSecurityGroupNetwork):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
find_mock_result = [self._security_groups[0], exceptions.CommandError]
- self.network_client.find_security_group = mock.Mock(
- side_effect=find_mock_result
- )
+ self.network_client.find_security_group.side_effect = find_mock_result
try:
self.cmd.take_action(parsed_args)
@@ -295,8 +290,8 @@ class TestListSecurityGroupNetwork(TestSecurityGroupNetwork):
def setUp(self):
super().setUp()
- self.network_client.security_groups = mock.Mock(
- return_value=self._security_groups
+ self.network_client.security_groups.return_value = (
+ self._security_groups
)
# Get the command object to test
@@ -423,14 +418,13 @@ class TestSetSecurityGroupNetwork(TestSecurityGroupNetwork):
def setUp(self):
super().setUp()
- self.network_client.update_security_group = mock.Mock(
- return_value=None
- )
+ self.network_client.update_security_group.return_value = None
- self.network_client.find_security_group = mock.Mock(
- return_value=self._security_group
+ self.network_client.find_security_group.return_value = (
+ self._security_group
)
- self.network_client.set_tags = mock.Mock(return_value=None)
+
+ self.network_client.set_tags.return_value = None
# Get the command object to test
self.cmd = security_group.SetSecurityGroup(self.app, None)
@@ -557,8 +551,8 @@ class TestShowSecurityGroupNetwork(TestSecurityGroupNetwork):
def setUp(self):
super().setUp()
- self.network_client.find_security_group = mock.Mock(
- return_value=self._security_group
+ self.network_client.find_security_group.return_value = (
+ self._security_group
)
# Get the command object to test
@@ -596,14 +590,13 @@ class TestUnsetSecurityGroupNetwork(TestSecurityGroupNetwork):
def setUp(self):
super().setUp()
- self.network_client.update_security_group = mock.Mock(
- return_value=None
- )
+ self.network_client.update_security_group.return_value = None
- self.network_client.find_security_group = mock.Mock(
- return_value=self._security_group
+ self.network_client.find_security_group.return_value = (
+ self._security_group
)
- self.network_client.set_tags = mock.Mock(return_value=None)
+
+ self.network_client.set_tags.return_value = None
# Get the command object to test
self.cmd = security_group.UnsetSecurityGroup(self.app, None)
diff --git a/openstackclient/tests/unit/network/v2/test_security_group_rule_network.py b/openstackclient/tests/unit/network/v2/test_security_group_rule_network.py
index d5630c3..920e891 100644
--- a/openstackclient/tests/unit/network/v2/test_security_group_rule_network.py
+++ b/openstackclient/tests/unit/network/v2/test_security_group_rule_network.py
@@ -11,7 +11,6 @@
# under the License.
#
-from unittest import mock
from unittest.mock import call
from osc_lib import exceptions
@@ -69,9 +68,10 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
self._security_group_rule = (
network_fakes.create_one_security_group_rule(attrs)
)
- self.network_client.create_security_group_rule = mock.Mock(
- return_value=self._security_group_rule
+ self.network_client.create_security_group_rule.return_value = (
+ self._security_group_rule
)
+
self.expected_data = (
self._security_group_rule.created_at,
self._security_group_rule.description,
@@ -93,12 +93,12 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
def setUp(self):
super().setUp()
- self.network_client.find_security_group = mock.Mock(
- return_value=self._security_group
+ self.network_client.find_security_group.return_value = (
+ self._security_group
)
- self.network_client.find_address_group = mock.Mock(
- return_value=self._address_group
+ self.network_client.find_address_group.return_value = (
+ self._address_group
)
self.projects_mock.get.return_value = self.project
@@ -970,9 +970,7 @@ class TestDeleteSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
def setUp(self):
super().setUp()
- self.network_client.delete_security_group_rule = mock.Mock(
- return_value=None
- )
+ self.network_client.delete_security_group_rule.return_value = None
self.network_client.find_security_group_rule = (
network_fakes.get_security_group_rules(self._security_group_rules)
@@ -1030,8 +1028,8 @@ class TestDeleteSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
self._security_group_rules[0],
exceptions.CommandError,
]
- self.network_client.find_security_group_rule = mock.Mock(
- side_effect=find_mock_result
+ self.network_client.find_security_group_rule.side_effect = (
+ find_mock_result
)
try:
@@ -1134,11 +1132,12 @@ class TestListSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
def setUp(self):
super().setUp()
- self.network_client.find_security_group = mock.Mock(
- return_value=self._security_group
+ self.network_client.find_security_group.return_value = (
+ self._security_group
)
- self.network_client.security_group_rules = mock.Mock(
- return_value=self._security_group_rules
+
+ self.network_client.security_group_rules.return_value = (
+ self._security_group_rules
)
# Get the command object to test
@@ -1344,8 +1343,8 @@ class TestShowSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
def setUp(self):
super().setUp()
- self.network_client.find_security_group_rule = mock.Mock(
- return_value=self._security_group_rule
+ self.network_client.find_security_group_rule.return_value = (
+ self._security_group_rule
)
# Get the command object to test
diff --git a/openstackclient/tests/unit/network/v2/test_subnet.py b/openstackclient/tests/unit/network/v2/test_subnet.py
index 8b82074..e59168e 100644
--- a/openstackclient/tests/unit/network/v2/test_subnet.py
+++ b/openstackclient/tests/unit/network/v2/test_subnet.py
@@ -11,7 +11,6 @@
# under the License.
#
-from unittest import mock
from unittest.mock import call
from osc_lib.cli import format_columns
@@ -266,19 +265,14 @@ class TestCreateSubnet(TestSubnet):
self.domains_mock.get.return_value = self.domain
# Mock SDK calls for all tests.
- self.network_client.create_subnet = mock.Mock(
- return_value=self._subnet
- )
- self.network_client.set_tags = mock.Mock(return_value=None)
- self.network_client.find_network = mock.Mock(
- return_value=self._network
- )
- self.network_client.find_segment = mock.Mock(
- return_value=self._network_segment
- )
- self.network_client.find_subnet_pool = mock.Mock(
- return_value=self._subnet_pool
- )
+ self.network_client.create_subnet.return_value = self._subnet
+
+ self.network_client.set_tags.return_value = None
+ self.network_client.find_network.return_value = self._network
+
+ self.network_client.find_segment.return_value = self._network_segment
+
+ self.network_client.find_subnet_pool.return_value = self._subnet_pool
def test_create_no_options(self):
arglist = []
@@ -333,7 +327,7 @@ class TestCreateSubnet(TestSubnet):
def test_create_from_subnet_pool_options(self):
# Mock SDK calls for this test.
self.network_client.create_subnet.return_value = self._subnet_from_pool
- self.network_client.set_tags = mock.Mock(return_value=None)
+ self.network_client.set_tags.return_value = None
self._network.id = self._subnet_from_pool.network_id
arglist = [
@@ -721,7 +715,7 @@ class TestDeleteSubnet(TestSubnet):
def setUp(self):
super().setUp()
- self.network_client.delete_subnet = mock.Mock(return_value=None)
+ self.network_client.delete_subnet.return_value = None
self.network_client.find_subnet = network_fakes.FakeSubnet.get_subnets(
self._subnets
@@ -775,9 +769,7 @@ class TestDeleteSubnet(TestSubnet):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
find_mock_result = [self._subnets[0], exceptions.CommandError]
- self.network_client.find_subnet = mock.Mock(
- side_effect=find_mock_result
- )
+ self.network_client.find_subnet.side_effect = find_mock_result
try:
self.cmd.take_action(parsed_args)
@@ -855,7 +847,7 @@ class TestListSubnet(TestSubnet):
# Get the command object to test
self.cmd = subnet_v2.ListSubnet(self.app, None)
- self.network_client.subnets = mock.Mock(return_value=self._subnet)
+ self.network_client.subnets.return_value = self._subnet
def test_subnet_list_no_options(self):
arglist = []
@@ -1019,7 +1011,7 @@ class TestListSubnet(TestSubnet):
def test_subnet_list_network(self):
network = network_fakes.create_one_network()
- self.network_client.find_network = mock.Mock(return_value=network)
+ self.network_client.find_network.return_value = network
arglist = [
'--network',
network.id,
@@ -1038,7 +1030,7 @@ class TestListSubnet(TestSubnet):
def test_subnet_list_gateway(self):
subnet = network_fakes.FakeSubnet.create_one_subnet()
- self.network_client.find_network = mock.Mock(return_value=subnet)
+ self.network_client.find_network.return_value = subnet
arglist = [
'--gateway',
subnet.gateway_ip,
@@ -1057,7 +1049,7 @@ class TestListSubnet(TestSubnet):
def test_subnet_list_name(self):
subnet = network_fakes.FakeSubnet.create_one_subnet()
- self.network_client.find_network = mock.Mock(return_value=subnet)
+ self.network_client.find_network.return_value = subnet
arglist = [
'--name',
subnet.name,
@@ -1076,7 +1068,7 @@ class TestListSubnet(TestSubnet):
def test_subnet_list_subnet_range(self):
subnet = network_fakes.FakeSubnet.create_one_subnet()
- self.network_client.find_network = mock.Mock(return_value=subnet)
+ self.network_client.find_network.return_value = subnet
arglist = [
'--subnet-range',
subnet.cidr,
@@ -1098,10 +1090,9 @@ class TestListSubnet(TestSubnet):
subnet = network_fakes.FakeSubnet.create_one_subnet(
{'subnetpool_id': subnet_pool.id}
)
- self.network_client.find_network = mock.Mock(return_value=subnet)
- self.network_client.find_subnet_pool = mock.Mock(
- return_value=subnet_pool
- )
+ self.network_client.find_network.return_value = subnet
+ self.network_client.find_subnet_pool.return_value = subnet_pool
+
arglist = [
'--subnet-pool',
subnet_pool.name,
@@ -1123,10 +1114,9 @@ class TestListSubnet(TestSubnet):
subnet = network_fakes.FakeSubnet.create_one_subnet(
{'subnetpool_id': subnet_pool.id}
)
- self.network_client.find_network = mock.Mock(return_value=subnet)
- self.network_client.find_subnet_pool = mock.Mock(
- return_value=subnet_pool
- )
+ self.network_client.find_network.return_value = subnet
+ self.network_client.find_subnet_pool.return_value = subnet_pool
+
arglist = [
'--subnet-pool',
subnet_pool.id,
@@ -1182,9 +1172,9 @@ class TestSetSubnet(TestSubnet):
def setUp(self):
super().setUp()
- self.network_client.update_subnet = mock.Mock(return_value=None)
- self.network_client.set_tags = mock.Mock(return_value=None)
- self.network_client.find_subnet = mock.Mock(return_value=self._subnet)
+ self.network_client.update_subnet.return_value = None
+ self.network_client.set_tags.return_value = None
+ self.network_client.find_subnet.return_value = self._subnet
self.cmd = subnet_v2.SetSubnet(self.app, None)
def test_set_this(self):
@@ -1263,7 +1253,7 @@ class TestSetSubnet(TestSubnet):
'service_types': ["network:router_gateway"],
}
)
- self.network_client.find_subnet = mock.Mock(return_value=_testsubnet)
+ self.network_client.find_subnet.return_value = _testsubnet
arglist = [
'--dns-nameserver',
'10.0.0.2',
@@ -1329,7 +1319,7 @@ class TestSetSubnet(TestSubnet):
'dns_nameservers': ["10.0.0.1"],
}
)
- self.network_client.find_subnet = mock.Mock(return_value=_testsubnet)
+ self.network_client.find_subnet.return_value = _testsubnet
arglist = [
'--host-route',
'destination=10.30.30.30/24,gateway=10.30.30.1',
@@ -1379,7 +1369,7 @@ class TestSetSubnet(TestSubnet):
'dns_nameservers': ['10.0.0.1'],
}
)
- self.network_client.find_subnet = mock.Mock(return_value=_testsubnet)
+ self.network_client.find_subnet.return_value = _testsubnet
arglist = [
'--no-host-route',
'--no-allocation-pool',
@@ -1448,8 +1438,8 @@ class TestSetSubnet(TestSubnet):
'segment_id': None,
}
)
- self.network_client.find_subnet = mock.Mock(return_value=_subnet)
- self.network_client.find_segment = mock.Mock(return_value=_segment)
+ self.network_client.find_subnet.return_value = _subnet
+ self.network_client.find_segment.return_value = _segment
arglist = ['--network-segment', _segment.id, _subnet.name]
verifylist = [('network_segment', _segment.id)]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -1514,7 +1504,7 @@ class TestShowSubnet(TestSubnet):
# Get the command object to test
self.cmd = subnet_v2.ShowSubnet(self.app, None)
- self.network_client.find_subnet = mock.Mock(return_value=self._subnet)
+ self.network_client.find_subnet.return_value = self._subnet
def test_show_no_options(self):
arglist = []
@@ -1572,11 +1562,10 @@ class TestUnsetSubnet(TestSubnet):
'tags': ['green', 'red'],
}
)
- self.network_client.find_subnet = mock.Mock(
- return_value=self._testsubnet
- )
- self.network_client.update_subnet = mock.Mock(return_value=None)
- self.network_client.set_tags = mock.Mock(return_value=None)
+ self.network_client.find_subnet.return_value = self._testsubnet
+
+ self.network_client.update_subnet.return_value = None
+ self.network_client.set_tags.return_value = None
# Get the command object to test
self.cmd = subnet_v2.UnsetSubnet(self.app, None)
diff --git a/openstackclient/tests/unit/network/v2/test_subnet_pool.py b/openstackclient/tests/unit/network/v2/test_subnet_pool.py
index 40aa1e9..013550e 100644
--- a/openstackclient/tests/unit/network/v2/test_subnet_pool.py
+++ b/openstackclient/tests/unit/network/v2/test_subnet_pool.py
@@ -10,7 +10,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-from unittest import mock
from unittest.mock import call
from osc_lib.cli import format_columns
@@ -76,16 +75,15 @@ class TestCreateSubnetPool(TestSubnetPool):
def setUp(self):
super().setUp()
- self.network_client.create_subnet_pool = mock.Mock(
- return_value=self._subnet_pool
- )
- self.network_client.set_tags = mock.Mock(return_value=None)
+ self.network_client.create_subnet_pool.return_value = self._subnet_pool
+
+ self.network_client.set_tags.return_value = None
# Get the command object to test
self.cmd = subnet_pool.CreateSubnetPool(self.app, None)
- self.network_client.find_address_scope = mock.Mock(
- return_value=self._address_scope
+ self.network_client.find_address_scope.return_value = (
+ self._address_scope
)
self.projects_mock.get.return_value = self.project
@@ -387,7 +385,7 @@ class TestDeleteSubnetPool(TestSubnetPool):
def setUp(self):
super().setUp()
- self.network_client.delete_subnet_pool = mock.Mock(return_value=None)
+ self.network_client.delete_subnet_pool.return_value = None
self.network_client.find_subnet_pool = (
network_fakes.FakeSubnetPool.get_subnet_pools(self._subnet_pools)
@@ -445,9 +443,7 @@ class TestDeleteSubnetPool(TestSubnetPool):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
find_mock_result = [self._subnet_pools[0], exceptions.CommandError]
- self.network_client.find_subnet_pool = mock.Mock(
- side_effect=find_mock_result
- )
+ self.network_client.find_subnet_pool.side_effect = find_mock_result
try:
self.cmd.take_action(parsed_args)
@@ -514,9 +510,7 @@ class TestListSubnetPool(TestSubnetPool):
# Get the command object to test
self.cmd = subnet_pool.ListSubnetPool(self.app, None)
- self.network_client.subnet_pools = mock.Mock(
- return_value=self._subnet_pools
- )
+ self.network_client.subnet_pools.return_value = self._subnet_pools
def test_subnet_pool_list_no_option(self):
arglist = []
@@ -653,7 +647,7 @@ class TestListSubnetPool(TestSubnetPool):
def test_subnet_pool_list_name(self):
subnet_pool = network_fakes.FakeSubnetPool.create_one_subnet_pool()
- self.network_client.find_network = mock.Mock(return_value=subnet_pool)
+ self.network_client.find_network.return_value = subnet_pool
arglist = [
'--name',
subnet_pool.name,
@@ -672,9 +666,8 @@ class TestListSubnetPool(TestSubnetPool):
def test_subnet_pool_list_address_scope(self):
addr_scope = network_fakes.create_one_address_scope()
- self.network_client.find_address_scope = mock.Mock(
- return_value=addr_scope
- )
+ self.network_client.find_address_scope.return_value = addr_scope
+
arglist = [
'--address-scope',
addr_scope.id,
@@ -734,15 +727,13 @@ class TestSetSubnetPool(TestSubnetPool):
def setUp(self):
super().setUp()
- self.network_client.update_subnet_pool = mock.Mock(return_value=None)
- self.network_client.set_tags = mock.Mock(return_value=None)
+ self.network_client.update_subnet_pool.return_value = None
+ self.network_client.set_tags.return_value = None
- self.network_client.find_subnet_pool = mock.Mock(
- return_value=self._subnet_pool
- )
+ self.network_client.find_subnet_pool.return_value = self._subnet_pool
- self.network_client.find_address_scope = mock.Mock(
- return_value=self._address_scope
+ self.network_client.find_address_scope.return_value = (
+ self._address_scope
)
# Get the command object to test
@@ -1079,9 +1070,7 @@ class TestShowSubnetPool(TestSubnetPool):
def setUp(self):
super().setUp()
- self.network_client.find_subnet_pool = mock.Mock(
- return_value=self._subnet_pool
- )
+ self.network_client.find_subnet_pool.return_value = self._subnet_pool
# Get the command object to test
self.cmd = subnet_pool.ShowSubnetPool(self.app, None)
@@ -1122,11 +1111,10 @@ class TestUnsetSubnetPool(TestSubnetPool):
self._subnetpool = network_fakes.FakeSubnetPool.create_one_subnet_pool(
{'tags': ['green', 'red']}
)
- self.network_client.find_subnet_pool = mock.Mock(
- return_value=self._subnetpool
- )
- self.network_client.update_subnet_pool = mock.Mock(return_value=None)
- self.network_client.set_tags = mock.Mock(return_value=None)
+ self.network_client.find_subnet_pool.return_value = self._subnetpool
+
+ self.network_client.update_subnet_pool.return_value = None
+ self.network_client.set_tags.return_value = None
# Get the command object to test
self.cmd = subnet_pool.UnsetSubnetPool(self.app, None)
diff --git a/openstackclient/tests/unit/volume/test_find_resource.py b/openstackclient/tests/unit/volume/test_find_resource.py
index df087dd..614fa9a 100644
--- a/openstackclient/tests/unit/volume/test_find_resource.py
+++ b/openstackclient/tests/unit/volume/test_find_resource.py
@@ -21,15 +21,6 @@ from osc_lib import exceptions
from osc_lib import utils
from openstackclient.tests.unit import utils as test_utils
-from openstackclient.volume import client # noqa
-
-
-# Monkey patch for v1 cinderclient
-# NOTE(dtroyer): Do here because openstackclient.volume.client
-# doesn't do it until the client object is created now.
-volumes.Volume.NAME_ATTR = 'display_name'
-volume_snapshots.Snapshot.NAME_ATTR = 'display_name'
-
ID = '1after909'
NAME = 'PhilSpector'
@@ -42,14 +33,14 @@ class TestFindResourceVolumes(test_utils.TestCase):
api.client = mock.Mock()
api.client.get = mock.Mock()
resp = mock.Mock()
- body = {"volumes": [{"id": ID, 'display_name': NAME}]}
+ body = {"volumes": [{"id": ID, 'name': NAME}]}
api.client.get.side_effect = [Exception("Not found"), (resp, body)]
self.manager = volumes.VolumeManager(api)
def test_find(self):
result = utils.find_resource(self.manager, NAME)
self.assertEqual(ID, result.id)
- self.assertEqual(NAME, result.display_name)
+ self.assertEqual(NAME, result.name)
def test_not_find(self):
self.assertRaises(
@@ -67,14 +58,14 @@ class TestFindResourceVolumeSnapshots(test_utils.TestCase):
api.client = mock.Mock()
api.client.get = mock.Mock()
resp = mock.Mock()
- body = {"snapshots": [{"id": ID, 'display_name': NAME}]}
+ body = {"snapshots": [{"id": ID, 'name': NAME}]}
api.client.get.side_effect = [Exception("Not found"), (resp, body)]
self.manager = volume_snapshots.SnapshotManager(api)
def test_find(self):
result = utils.find_resource(self.manager, NAME)
self.assertEqual(ID, result.id)
- self.assertEqual(NAME, result.display_name)
+ self.assertEqual(NAME, result.name)
def test_not_find(self):
self.assertRaises(
diff --git a/openstackclient/tests/unit/volume/v2/test_consistency_group.py b/openstackclient/tests/unit/volume/v2/test_consistency_group.py
index dc62e5e..68021c8 100644
--- a/openstackclient/tests/unit/volume/v2/test_consistency_group.py
+++ b/openstackclient/tests/unit/volume/v2/test_consistency_group.py
@@ -129,7 +129,10 @@ class TestConsistencyGroupAddVolume(TestConsistencyGroup):
utils, 'find_resource', side_effect=find_mock_result
) as find_mock:
result = self.cmd.take_action(parsed_args)
- mock_error.assert_called_with("1 of 2 volumes failed to add.")
+ mock_error.assert_called_with(
+ '%(result)s of %(total)s volumes failed to add.',
+ {'result': 1, 'total': 2},
+ )
self.assertIsNone(result)
find_mock.assert_any_call(
self.consistencygroups_mock, self._consistency_group.id
@@ -602,7 +605,10 @@ class TestConsistencyGroupRemoveVolume(TestConsistencyGroup):
utils, 'find_resource', side_effect=find_mock_result
) as find_mock:
result = self.cmd.take_action(parsed_args)
- mock_error.assert_called_with("1 of 2 volumes failed to remove.")
+ mock_error.assert_called_with(
+ '%(result)s of %(total)s volumes failed to remove.',
+ {'result': 1, 'total': 2},
+ )
self.assertIsNone(result)
find_mock.assert_any_call(
self.consistencygroups_mock, self._consistency_group.id
diff --git a/openstackclient/tests/unit/volume/v2/test_volume.py b/openstackclient/tests/unit/volume/v2/test_volume.py
index b68020f..8a9f777 100644
--- a/openstackclient/tests/unit/volume/v2/test_volume.py
+++ b/openstackclient/tests/unit/volume/v2/test_volume.py
@@ -655,7 +655,7 @@ class TestVolumeDelete(volume_fakes.TestVolume):
arglist = [self.volumes[0].id]
verifylist = [
("force", False),
- ("purge", False),
+ ("cascade", False),
("volumes", [self.volumes[0].id]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -674,7 +674,7 @@ class TestVolumeDelete(volume_fakes.TestVolume):
arglist = [v.id for v in self.volumes]
verifylist = [
('force', False),
- ('purge', False),
+ ('cascade', False),
('volumes', arglist),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -701,7 +701,7 @@ class TestVolumeDelete(volume_fakes.TestVolume):
]
verifylist = [
('force', False),
- ('purge', False),
+ ('cascade', False),
('volumes', [self.volumes[0].id, 'unexist_volume']),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -732,7 +732,7 @@ class TestVolumeDelete(volume_fakes.TestVolume):
]
verifylist = [
('force', False),
- ('purge', True),
+ ('cascade', True),
('volumes', [self.volumes[0].id]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -754,7 +754,7 @@ class TestVolumeDelete(volume_fakes.TestVolume):
]
verifylist = [
('force', True),
- ('purge', False),
+ ('cascade', False),
('volumes', [self.volumes[0].id]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -1618,7 +1618,8 @@ class TestVolumeSet(TestVolume):
result = self.cmd.take_action(parsed_args)
self.volumes_mock.retype.assert_not_called()
mock_warning.assert_called_with(
- "'--retype-policy' option will not work without '--type' option"
+ "'%s' option will not work without '--type' option",
+ '--retype-policy',
)
self.assertIsNone(result)
diff --git a/openstackclient/tests/unit/volume/v2/test_volume_backup.py b/openstackclient/tests/unit/volume/v2/test_volume_backup.py
index 7d4fba9..e7bbb69 100644
--- a/openstackclient/tests/unit/volume/v2/test_volume_backup.py
+++ b/openstackclient/tests/unit/volume/v2/test_volume_backup.py
@@ -565,7 +565,9 @@ class TestBackupShow(volume_fakes.TestVolume):
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
- self.volume_sdk_client.find_backup.assert_called_with(self.backup.id)
+ self.volume_sdk_client.find_backup.assert_called_with(
+ self.backup.id, ignore_missing=False
+ )
self.assertEqual(self.columns, columns)
self.assertEqual(self.data, data)
diff --git a/openstackclient/tests/unit/volume/v3/test_volume.py b/openstackclient/tests/unit/volume/v3/test_volume.py
index 5fb35a0..3338ccf 100644
--- a/openstackclient/tests/unit/volume/v3/test_volume.py
+++ b/openstackclient/tests/unit/volume/v3/test_volume.py
@@ -37,6 +37,7 @@ class TestVolumeCreate(volume_fakes.TestVolume):
columns = (
'attachments',
'availability_zone',
+ 'backup_id',
'bootable',
'cluster_name',
'consistencygroup_id',
@@ -78,6 +79,7 @@ class TestVolumeCreate(volume_fakes.TestVolume):
self.datalist = (
self.volume.attachments,
self.volume.availability_zone,
+ self.volume.backup_id,
self.volume.is_bootable,
self.volume.cluster_name,
self.volume.consistency_group_id,
@@ -910,7 +912,7 @@ class TestVolumeDelete(volume_fakes.TestVolume):
arglist = [self.volumes[0].id]
verifylist = [
("force", False),
- ("purge", False),
+ ("cascade", False),
("volumes", [self.volumes[0].id]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -929,7 +931,7 @@ class TestVolumeDelete(volume_fakes.TestVolume):
arglist = [v.id for v in self.volumes]
verifylist = [
('force', False),
- ('purge', False),
+ ('cascade', False),
('volumes', arglist),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -956,7 +958,7 @@ class TestVolumeDelete(volume_fakes.TestVolume):
]
verifylist = [
('force', False),
- ('purge', False),
+ ('cascade', False),
('volumes', [self.volumes[0].id, 'unexist_volume']),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -987,7 +989,29 @@ class TestVolumeDelete(volume_fakes.TestVolume):
]
verifylist = [
('force', False),
- ('purge', True),
+ ('cascade', True),
+ ('volumes', [self.volumes[0].id]),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+ self.assertIsNone(result)
+
+ self.volume_sdk_client.find_volume.assert_called_once_with(
+ self.volumes[0].id, ignore_missing=False
+ )
+ self.volume_sdk_client.delete_volume.assert_called_once_with(
+ self.volumes[0].id, cascade=True, force=False
+ )
+
+ def test_volume_delete_with_cascade(self):
+ arglist = [
+ '--cascade',
+ self.volumes[0].id,
+ ]
+ verifylist = [
+ ('force', False),
+ ('cascade', True),
('volumes', [self.volumes[0].id]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -1009,7 +1033,7 @@ class TestVolumeDelete(volume_fakes.TestVolume):
]
verifylist = [
('force', True),
- ('purge', False),
+ ('cascade', False),
('volumes', [self.volumes[0].id]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -1029,7 +1053,7 @@ class TestVolumeDelete(volume_fakes.TestVolume):
verifylist = [
("remote", True),
("force", False),
- ("purge", False),
+ ("cascade", False),
("volumes", [self.volumes[0].id]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -1050,7 +1074,7 @@ class TestVolumeDelete(volume_fakes.TestVolume):
verifylist = [
('remote', True),
('force', False),
- ('purge', False),
+ ('cascade', False),
('volumes', arglist[1:]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -1075,7 +1099,6 @@ class TestVolumeDelete(volume_fakes.TestVolume):
verifylist = [
('remote', True),
('force', False),
- ('purge', True),
('volumes', [self.volumes[0].id]),
]
@@ -1084,7 +1107,7 @@ class TestVolumeDelete(volume_fakes.TestVolume):
exceptions.CommandError, self.cmd.take_action, parsed_args
)
self.assertIn(
- "The --force and --purge options are not supported with the "
+ "The --force and --cascade options are not supported with the "
"--remote parameter.",
str(exc),
)
@@ -1102,7 +1125,7 @@ class TestVolumeDelete(volume_fakes.TestVolume):
verifylist = [
('remote', True),
('force', True),
- ('purge', False),
+ ('cascade', False),
('volumes', [self.volumes[0].id]),
]
@@ -1111,7 +1134,7 @@ class TestVolumeDelete(volume_fakes.TestVolume):
exceptions.CommandError, self.cmd.take_action, parsed_args
)
self.assertIn(
- "The --force and --purge options are not supported with the "
+ "The --force and --cascade options are not supported with the "
"--remote parameter.",
str(exc),
)
@@ -1996,7 +2019,8 @@ class TestVolumeSet(volume_fakes.TestVolume):
result = self.cmd.take_action(parsed_args)
self.volumes_mock.retype.assert_not_called()
mock_warning.assert_called_with(
- "'--retype-policy' option will not work without '--type' option"
+ "'%s' option will not work without '--type' option",
+ '--retype-policy',
)
self.assertIsNone(result)
@@ -2011,6 +2035,7 @@ class TestVolumeShow(volume_fakes.TestVolume):
self.columns = (
'attachments',
'availability_zone',
+ 'backup_id',
'bootable',
'cluster_name',
'consistencygroup_id',
@@ -2045,6 +2070,7 @@ class TestVolumeShow(volume_fakes.TestVolume):
self.data = (
self.volume.attachments,
self.volume.availability_zone,
+ self.volume.backup_id,
self.volume.is_bootable,
self.volume.cluster_name,
self.volume.consistency_group_id,
diff --git a/openstackclient/tests/unit/volume/v3/test_volume_backup.py b/openstackclient/tests/unit/volume/v3/test_volume_backup.py
index 5be0985..86bde78 100644
--- a/openstackclient/tests/unit/volume/v3/test_volume_backup.py
+++ b/openstackclient/tests/unit/volume/v3/test_volume_backup.py
@@ -17,6 +17,7 @@ from openstack.block_storage.v3 import backup as _backup
from openstack.block_storage.v3 import snapshot as _snapshot
from openstack.block_storage.v3 import volume as _volume
from openstack import exceptions as sdk_exceptions
+from openstack.identity.v3 import project as _project
from openstack.test import fakes as sdk_fakes
from osc_lib import exceptions
@@ -381,6 +382,7 @@ class TestBackupList(volume_fakes.TestVolume):
("marker", None),
("limit", None),
('all_projects', False),
+ ("project", None),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -395,11 +397,14 @@ class TestBackupList(volume_fakes.TestVolume):
all_tenants=False,
marker=None,
limit=None,
+ project_id=None,
)
self.assertEqual(self.columns, columns)
self.assertCountEqual(self.data, list(data))
def test_backup_list_with_options(self):
+ project = sdk_fakes.generate_fake_resource(_project.Project)
+ self.identity_sdk_client.find_project.return_value = project
arglist = [
"--long",
"--name",
@@ -413,6 +418,8 @@ class TestBackupList(volume_fakes.TestVolume):
"--all-projects",
"--limit",
"3",
+ "--project",
+ project.id,
]
verifylist = [
("long", True),
@@ -422,6 +429,7 @@ class TestBackupList(volume_fakes.TestVolume):
("marker", self.backups[0].id),
('all_projects', True),
("limit", 3),
+ ("project", project.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -440,6 +448,7 @@ class TestBackupList(volume_fakes.TestVolume):
all_tenants=True,
marker=self.backups[0].id,
limit=3,
+ project_id=project.id,
)
self.assertEqual(self.columns_long, columns)
self.assertCountEqual(self.data_long, list(data))
diff --git a/openstackclient/volume/client.py b/openstackclient/volume/client.py
index d3a3406..dbef055 100644
--- a/openstackclient/volume/client.py
+++ b/openstackclient/volume/client.py
@@ -20,16 +20,14 @@ from osc_lib import utils
from openstackclient.i18n import _
-
LOG = logging.getLogger(__name__)
DEFAULT_API_VERSION = '3'
API_VERSION_OPTION = 'os_volume_api_version'
-API_NAME = "volume"
+API_NAME = 'volume'
API_VERSIONS = {
- "1": "cinderclient.v1.client.Client",
- "2": "cinderclient.v2.client.Client",
- "3": "cinderclient.v3.client.Client",
+ '2': 'cinderclient.v2.client.Client',
+ '3': 'cinderclient.v3.client.Client',
}
# Save the microversion if in use
@@ -45,11 +43,6 @@ def make_client(instance):
from cinderclient.v3 import volume_snapshots
from cinderclient.v3 import volumes
- # Check whether the available cinderclient supports v1 or v2
- try:
- from cinderclient.v1 import services # noqa
- except Exception:
- del API_VERSIONS['1']
try:
from cinderclient.v2 import services # noqa
except Exception:
@@ -127,21 +120,18 @@ def check_api_version(check_version):
global _volume_api_version
- # Copy some logic from novaclient 3.3.0 for basic version detection
- # NOTE(dtroyer): This is only enough to resume operations using API
- # version 3.0 or any valid version supplied by the user.
_volume_api_version = api_versions.get_api_version(check_version)
# Bypass X.latest format microversion
if not _volume_api_version.is_latest():
- if _volume_api_version > api_versions.APIVersion("3.0"):
+ if _volume_api_version > api_versions.APIVersion('3.0'):
if not _volume_api_version.matches(
api_versions.MIN_VERSION,
api_versions.MAX_VERSION,
):
- msg = _("versions supported by client: %(min)s - %(max)s") % {
- "min": api_versions.MIN_VERSION,
- "max": api_versions.MAX_VERSION,
+ msg = _('versions supported by client: %(min)s - %(max)s') % {
+ 'min': api_versions.MIN_VERSION,
+ 'max': api_versions.MAX_VERSION,
}
raise exceptions.CommandError(msg)
diff --git a/openstackclient/volume/v2/backup_record.py b/openstackclient/volume/v2/backup_record.py
index 98f7c71..93492f8 100644
--- a/openstackclient/volume/v2/backup_record.py
+++ b/openstackclient/volume/v2/backup_record.py
@@ -16,9 +16,9 @@
import logging
-from osc_lib.command import command
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/volume/v2/consistency_group.py b/openstackclient/volume/v2/consistency_group.py
index 347724f..31959c7 100644
--- a/openstackclient/volume/v2/consistency_group.py
+++ b/openstackclient/volume/v2/consistency_group.py
@@ -18,10 +18,10 @@ import argparse
import logging
from osc_lib.cli import format_columns
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
@@ -38,8 +38,8 @@ def _find_volumes(parsed_args_volumes, volume_client):
except Exception as e:
result += 1
LOG.error(
- _("Failed to find volume with name or ID '%(volume)s':%(e)s")
- % {'volume': volume, 'e': e}
+ _("Failed to find volume with name or ID '%(volume)s':%(e)s"),
+ {'volume': volume, 'e': e},
)
return result, uuid
@@ -73,8 +73,8 @@ class AddVolumeToConsistencyGroup(command.Command):
if result > 0:
total = len(parsed_args.volumes)
LOG.error(
- _("%(result)s of %(total)s volumes failed to add.")
- % {'result': result, 'total': total}
+ _("%(result)s of %(total)s volumes failed to add."),
+ {'result': result, 'total': total},
)
if add_uuid:
@@ -226,8 +226,8 @@ class DeleteConsistencyGroup(command.Command):
_(
"Failed to delete consistency group with "
"name or ID '%(consistency_group)s':%(e)s"
- )
- % {'consistency_group': i, 'e': e}
+ ),
+ {'consistency_group': i, 'e': e},
)
if result > 0:
@@ -317,8 +317,8 @@ class RemoveVolumeFromConsistencyGroup(command.Command):
if result > 0:
total = len(parsed_args.volumes)
LOG.error(
- _("%(result)s of %(total)s volumes failed to remove.")
- % {'result': result, 'total': total}
+ _("%(result)s of %(total)s volumes failed to remove."),
+ {'result': result, 'total': total},
)
if remove_uuid:
diff --git a/openstackclient/volume/v2/consistency_group_snapshot.py b/openstackclient/volume/v2/consistency_group_snapshot.py
index 3c582d6..4adf4a2 100644
--- a/openstackclient/volume/v2/consistency_group_snapshot.py
+++ b/openstackclient/volume/v2/consistency_group_snapshot.py
@@ -16,10 +16,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
@@ -101,8 +101,8 @@ class DeleteConsistencyGroupSnapshot(command.Command):
_(
"Failed to delete consistency group snapshot "
"with name or ID '%(snapshot)s': %(e)s"
- )
- % {'snapshot': snapshot, 'e': e}
+ ),
+ {'snapshot': snapshot, 'e': e},
)
if result > 0:
diff --git a/openstackclient/volume/v2/qos_specs.py b/openstackclient/volume/v2/qos_specs.py
index 72706a7..6dcc23f 100644
--- a/openstackclient/volume/v2/qos_specs.py
+++ b/openstackclient/volume/v2/qos_specs.py
@@ -19,10 +19,10 @@ import logging
from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
@@ -146,8 +146,8 @@ class DeleteQos(command.Command):
_(
"Failed to delete QoS specification with "
"name or ID '%(qos)s': %(e)s"
- )
- % {'qos': i, 'e': e}
+ ),
+ {'qos': i, 'e': e},
)
if result > 0:
diff --git a/openstackclient/volume/v2/service.py b/openstackclient/volume/v2/service.py
index 48cdba7..7777e7e 100644
--- a/openstackclient/volume/v2/service.py
+++ b/openstackclient/volume/v2/service.py
@@ -14,10 +14,10 @@
"""Service action implementations"""
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/volume/v2/volume.py b/openstackclient/volume/v2/volume.py
index fa76d77..ef4ff05 100644
--- a/openstackclient/volume/v2/volume.py
+++ b/openstackclient/volume/v2/volume.py
@@ -25,11 +25,11 @@ from openstack.block_storage.v2 import volume as _volume
from openstack import exceptions as sdk_exceptions
from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
from openstackclient.api import volume_v2
+from openstackclient import command
from openstackclient.common import pagination
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
@@ -61,7 +61,7 @@ class KeyValueHintAction(argparse.Action):
)
-class AttachmentsColumn(cliff_columns.FormattableColumn):
+class AttachmentsColumn(cliff_columns.FormattableColumn[list[ty.Any]]):
"""Formattable column for attachments column.
Unlike the parent FormattableColumn class, the initializer of the
@@ -390,12 +390,19 @@ class DeleteVolume(command.Command):
),
)
group.add_argument(
- "--purge",
+ "--cascade",
action="store_true",
help=_(
"Remove any snapshots along with volume(s) (defaults to False)"
),
)
+ group.add_argument(
+ # now called "cascade", accept old arg for compatibility
+ "--purge",
+ action="store_true",
+ help=argparse.SUPPRESS,
+ dest='cascade',
+ )
return parser
def take_action(self, parsed_args):
@@ -410,7 +417,7 @@ class DeleteVolume(command.Command):
volume_client.delete_volume(
volume_obj.id,
force=parsed_args.force,
- cascade=parsed_args.purge,
+ cascade=parsed_args.cascade,
)
except Exception as e:
result += 1
@@ -910,12 +917,12 @@ class SetVolume(command.Command):
elif policy:
# If the "--migration-policy" is specified without "--type"
LOG.warning(
- _("'%s' option will not work without '--type' option")
- % (
+ _("'%s' option will not work without '--type' option"),
+ (
'--migration-policy'
if parsed_args.migration_policy
else '--retype-policy'
- )
+ ),
)
kwargs = {}
diff --git a/openstackclient/volume/v2/volume_backend.py b/openstackclient/volume/v2/volume_backend.py
index 2fbbed6..e51e37b 100644
--- a/openstackclient/volume/v2/volume_backend.py
+++ b/openstackclient/volume/v2/volume_backend.py
@@ -15,9 +15,9 @@
"""Storage backend action implementations"""
from osc_lib.cli import format_columns
-from osc_lib.command import command
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/volume/v2/volume_backup.py b/openstackclient/volume/v2/volume_backup.py
index 55cde32..7f36652 100644
--- a/openstackclient/volume/v2/volume_backup.py
+++ b/openstackclient/volume/v2/volume_backup.py
@@ -18,17 +18,17 @@ import functools
import logging
from cliff import columns as cliff_columns
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.common import pagination
from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
-class VolumeIdColumn(cliff_columns.FormattableColumn):
+class VolumeIdColumn(cliff_columns.FormattableColumn[str]):
"""Formattable column for volume ID column.
Unlike the parent FormattableColumn class, the initializer of the
@@ -175,8 +175,8 @@ class DeleteVolumeBackup(command.Command):
_(
"Failed to delete backup with "
"name or ID '%(backup)s': %(e)s"
- )
- % {'backup': backup, 'e': e}
+ ),
+ {'backup': backup, 'e': e},
)
if result > 0:
@@ -453,7 +453,9 @@ class ShowVolumeBackup(command.ShowOne):
def take_action(self, parsed_args):
volume_client = self.app.client_manager.sdk_connection.volume
- backup = volume_client.find_backup(parsed_args.backup)
+ backup = volume_client.find_backup(
+ parsed_args.backup, ignore_missing=False
+ )
columns: tuple[str, ...] = (
"availability_zone",
"container",
diff --git a/openstackclient/volume/v2/volume_host.py b/openstackclient/volume/v2/volume_host.py
index 2b0df0a..44fd58a 100644
--- a/openstackclient/volume/v2/volume_host.py
+++ b/openstackclient/volume/v2/volume_host.py
@@ -14,8 +14,7 @@
"""Volume v2 host action implementations"""
-from osc_lib.command import command
-
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/volume/v2/volume_snapshot.py b/openstackclient/volume/v2/volume_snapshot.py
index fb77461..9533a1a 100644
--- a/openstackclient/volume/v2/volume_snapshot.py
+++ b/openstackclient/volume/v2/volume_snapshot.py
@@ -22,10 +22,10 @@ from cliff import columns as cliff_columns
from openstack.block_storage.v2 import snapshot as _snapshot
from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.common import pagination
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
@@ -34,7 +34,7 @@ from openstackclient.identity import common as identity_common
LOG = logging.getLogger(__name__)
-class VolumeIdColumn(cliff_columns.FormattableColumn):
+class VolumeIdColumn(cliff_columns.FormattableColumn[str]):
"""Formattable column for volume ID column.
Unlike the parent FormattableColumn class, the initializer of the
@@ -228,8 +228,8 @@ class DeleteVolumeSnapshot(command.Command):
_(
"Failed to delete snapshot with "
"name or ID '%(snapshot)s': %(e)s"
- )
- % {'snapshot': snapshot, 'e': e}
+ ),
+ {'snapshot': snapshot, 'e': e},
)
if result > 0:
diff --git a/openstackclient/volume/v2/volume_transfer_request.py b/openstackclient/volume/v2/volume_transfer_request.py
index 3bd91d0..2f1bee8 100644
--- a/openstackclient/volume/v2/volume_transfer_request.py
+++ b/openstackclient/volume/v2/volume_transfer_request.py
@@ -16,10 +16,10 @@
import logging
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
@@ -128,8 +128,8 @@ class DeleteTransferRequest(command.Command):
_(
"Failed to delete volume transfer request "
"with name or ID '%(transfer)s': %(e)s"
- )
- % {'transfer': t, 'e': e}
+ ),
+ {'transfer': t, 'e': e},
)
if result > 0:
diff --git a/openstackclient/volume/v2/volume_type.py b/openstackclient/volume/v2/volume_type.py
index 9e2ac20..9c80461 100644
--- a/openstackclient/volume/v2/volume_type.py
+++ b/openstackclient/volume/v2/volume_type.py
@@ -16,14 +16,15 @@
import functools
import logging
+import typing as ty
from cliff import columns as cliff_columns
from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
@@ -31,7 +32,7 @@ from openstackclient.identity import common as identity_common
LOG = logging.getLogger(__name__)
-class EncryptionInfoColumn(cliff_columns.FormattableColumn):
+class EncryptionInfoColumn(cliff_columns.FormattableColumn[ty.Any]):
"""Formattable column for encryption info column.
Unlike the parent FormattableColumn class, the initializer of the
@@ -171,7 +172,8 @@ class CreateVolumeType(command.ShowOne):
default=False,
help=_(
"Enabled replication for this volume type "
- "(this is an alias for '--property replication_enabled=<is> True') "
+ "(this is an alias for "
+ "'--property replication_enabled=<is> True') "
"(requires driver support)"
),
)
@@ -181,7 +183,8 @@ class CreateVolumeType(command.ShowOne):
dest='availability_zones',
help=_(
"Set an availability zone for this volume type "
- "(this is an alias for '--property RESKEY:availability_zones:<az>') "
+ "(this is an alias for "
+ "'--property RESKEY:availability_zones:<az>') "
"(repeat option to set multiple availability zones)"
),
)
@@ -274,7 +277,7 @@ class CreateVolumeType(command.ShowOne):
msg = _(
"Failed to add project %(project)s access to type: %(e)s"
)
- LOG.error(msg % {'project': parsed_args.project, 'e': e})
+ LOG.error(msg, {'project': parsed_args.project, 'e': e})
properties = {}
if parsed_args.properties:
@@ -355,8 +358,8 @@ class DeleteVolumeType(command.Command):
_(
"Failed to delete volume type with "
"name or ID '%(volume_type)s': %(e)s"
- )
- % {'volume_type': volume_type, 'e': e}
+ ),
+ {'volume_type': volume_type, 'e': e},
)
if result > 0:
@@ -463,7 +466,7 @@ class ListVolumeType(command.Lister):
_EncryptionInfoColumn = functools.partial(
EncryptionInfoColumn, encryption_data=encryption
)
- formatters['id'] = _EncryptionInfoColumn
+ formatters['id'] = _EncryptionInfoColumn # type: ignore
return (
column_headers,
@@ -534,7 +537,8 @@ class SetVolumeType(command.Command):
default=False,
help=_(
"Enabled replication for this volume type "
- "(this is an alias for '--property replication_enabled=<is> True') "
+ "(this is an alias for "
+ "'--property replication_enabled=<is> True') "
"(requires driver support)"
),
)
@@ -544,7 +548,8 @@ class SetVolumeType(command.Command):
dest='availability_zones',
help=_(
"Set an availability zone for this volume type "
- "(this is an alias for '--property RESKEY:availability_zones:<az>') "
+ "(this is an alias for "
+ "'--property RESKEY:availability_zones:<az>') "
"(repeat option to set multiple availability zones)"
),
)
@@ -758,7 +763,7 @@ class ShowVolumeType(command.ShowOne):
'Failed to get access project list for volume type '
'%(type)s: %(e)s'
)
- LOG.error(msg % {'type': volume_type.id, 'e': e})
+ LOG.error(msg, {'type': volume_type.id, 'e': e})
volume_type._info.update({'access_project_ids': access_project_ids})
if parsed_args.encryption_type:
# show encryption type information for this volume type
diff --git a/openstackclient/volume/v3/block_storage_cleanup.py b/openstackclient/volume/v3/block_storage_cleanup.py
index 361440c..5208504 100644
--- a/openstackclient/volume/v3/block_storage_cleanup.py
+++ b/openstackclient/volume/v3/block_storage_cleanup.py
@@ -11,9 +11,9 @@
# under the License.
from cinderclient import api_versions
-from osc_lib.command import command
from osc_lib import exceptions
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/volume/v3/block_storage_cluster.py b/openstackclient/volume/v3/block_storage_cluster.py
index 8cf01b2..d99ec52 100644
--- a/openstackclient/volume/v3/block_storage_cluster.py
+++ b/openstackclient/volume/v3/block_storage_cluster.py
@@ -11,10 +11,10 @@
# under the License.
from cinderclient import api_versions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/volume/v3/block_storage_log_level.py b/openstackclient/volume/v3/block_storage_log_level.py
index 1f8d5b3..2e2fdc5 100644
--- a/openstackclient/volume/v3/block_storage_log_level.py
+++ b/openstackclient/volume/v3/block_storage_log_level.py
@@ -15,9 +15,9 @@
"""Block Storage Service action implementations"""
from openstack import utils as sdk_utils
-from osc_lib.command import command
from osc_lib import exceptions
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/volume/v3/block_storage_manage.py b/openstackclient/volume/v3/block_storage_manage.py
index 17c699b..7875638 100644
--- a/openstackclient/volume/v3/block_storage_manage.py
+++ b/openstackclient/volume/v3/block_storage_manage.py
@@ -16,10 +16,10 @@
import argparse
from cinderclient import api_versions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/volume/v3/block_storage_resource_filter.py b/openstackclient/volume/v3/block_storage_resource_filter.py
index 494d9cb..fc56438 100644
--- a/openstackclient/volume/v3/block_storage_resource_filter.py
+++ b/openstackclient/volume/v3/block_storage_resource_filter.py
@@ -14,10 +14,10 @@
from openstack import utils as sdk_utils
from osc_lib.cli import format_columns
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/volume/v3/service.py b/openstackclient/volume/v3/service.py
index 0f14e47..eecd8e0 100644
--- a/openstackclient/volume/v3/service.py
+++ b/openstackclient/volume/v3/service.py
@@ -15,10 +15,10 @@
"""Service action implementations"""
from openstack import utils as sdk_utils
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
diff --git a/openstackclient/volume/v3/volume.py b/openstackclient/volume/v3/volume.py
index 54dd5c7..4284600 100644
--- a/openstackclient/volume/v3/volume.py
+++ b/openstackclient/volume/v3/volume.py
@@ -26,11 +26,11 @@ from openstack import exceptions as sdk_exceptions
from openstack import utils as sdk_utils
from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
from openstackclient.api import volume_v3
+from openstackclient import command
from openstackclient.common import pagination
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
@@ -62,7 +62,7 @@ class KeyValueHintAction(argparse.Action):
)
-class AttachmentsColumn(cliff_columns.FormattableColumn):
+class AttachmentsColumn(cliff_columns.FormattableColumn[list[ty.Any]]):
"""Formattable column for attachments column.
Unlike the parent FormattableColumn class, the initializer of the
@@ -515,12 +515,19 @@ class DeleteVolume(command.Command):
),
)
group.add_argument(
- "--purge",
+ "--cascade",
action="store_true",
help=_(
"Remove any snapshots along with volume(s) (defaults to False)"
),
)
+ group.add_argument(
+ # now called "cascade", accept old arg for compatibility
+ "--purge",
+ action="store_true",
+ help=argparse.SUPPRESS,
+ dest='cascade',
+ )
parser.add_argument(
'--remote',
action='store_true',
@@ -532,9 +539,9 @@ class DeleteVolume(command.Command):
volume_client = self.app.client_manager.sdk_connection.volume
result = 0
- if parsed_args.remote and (parsed_args.force or parsed_args.purge):
+ if parsed_args.remote and (parsed_args.force or parsed_args.cascade):
msg = _(
- "The --force and --purge options are not "
+ "The --force and --cascade options are not "
"supported with the --remote parameter."
)
raise exceptions.CommandError(msg)
@@ -550,7 +557,7 @@ class DeleteVolume(command.Command):
volume_client.delete_volume(
volume_obj.id,
force=parsed_args.force,
- cascade=parsed_args.purge,
+ cascade=parsed_args.cascade,
)
except Exception as e:
result += 1
@@ -1071,12 +1078,12 @@ class SetVolume(command.Command):
elif policy:
# If the "--migration-policy" is specified without "--type"
LOG.warning(
- _("'%s' option will not work without '--type' option")
- % (
+ _("'%s' option will not work without '--type' option"),
+ (
'--migration-policy'
if parsed_args.migration_policy
else '--retype-policy'
- )
+ ),
)
kwargs = {}
diff --git a/openstackclient/volume/v3/volume_attachment.py b/openstackclient/volume/v3/volume_attachment.py
index 5773a12..3201da3 100644
--- a/openstackclient/volume/v3/volume_attachment.py
+++ b/openstackclient/volume/v3/volume_attachment.py
@@ -11,13 +11,14 @@
# under the License.
import logging
+import typing as ty
from openstack import utils as sdk_utils
from osc_lib.cli import format_columns
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.common import envvars
from openstackclient.common import pagination
from openstackclient.i18n import _
@@ -56,12 +57,12 @@ def _format_attachment(attachment):
# VolumeAttachmentManager.create returns a dict while everything else
# returns a VolumeAttachment object
if isinstance(attachment, dict):
- data = []
+ data: tuple[ty.Any, ...] = ()
for column in columns:
if column == 'connection_info':
- data.append(format_columns.DictColumn(attachment[column]))
+ data += (format_columns.DictColumn(attachment[column]),)
continue
- data.append(attachment[column])
+ data += (attachment[column],)
else:
data = utils.get_item_properties(
attachment,
@@ -458,7 +459,7 @@ class ListVolumeAttachment(command.Lister):
}
# Update search option with `filters`
# if AppendFilters.filters:
- # search_opts.update(shell_utils.extract_filters(AppendFilters.filters))
+ # search_opts.update(shell_utils.extract_filters(AppendFilters.filters)) # noqa: E501
# TODO(stephenfin): Implement sorting
attachments = volume_client.attachments(
diff --git a/openstackclient/volume/v3/volume_backup.py b/openstackclient/volume/v3/volume_backup.py
index 7df46f8..2ab24f3 100644
--- a/openstackclient/volume/v3/volume_backup.py
+++ b/openstackclient/volume/v3/volume_backup.py
@@ -21,17 +21,17 @@ import logging
from cliff import columns as cliff_columns
from openstack import utils as sdk_utils
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.common import pagination
from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
-class VolumeIdColumn(cliff_columns.FormattableColumn):
+class VolumeIdColumn(cliff_columns.FormattableColumn[str]):
"""Formattable column for volume ID column.
Unlike the parent FormattableColumn class, the initializer of the
@@ -218,8 +218,8 @@ class DeleteVolumeBackup(command.Command):
_(
"Failed to delete backup with "
"name or ID '%(backup)s': %(e)s"
- )
- % {'backup': backup, 'e': e}
+ ),
+ {'backup': backup, 'e': e},
)
if result > 0:
@@ -237,6 +237,11 @@ class ListVolumeBackup(command.Lister):
def get_parser(self, prog_name):
parser = super().get_parser(prog_name)
parser.add_argument(
+ '--project',
+ metavar='<project>',
+ help=_('Filter results by project (name or ID) (admin only)'),
+ )
+ parser.add_argument(
"--long",
action="store_true",
default=False,
@@ -296,6 +301,7 @@ class ListVolumeBackup(command.Lister):
def take_action(self, parsed_args):
volume_client = self.app.client_manager.sdk_connection.volume
+ identity_client = self.app.client_manager.sdk_connection.identity
columns: tuple[str, ...] = (
'id',
@@ -332,6 +338,14 @@ class ListVolumeBackup(command.Lister):
VolumeIdColumn, volume_cache=volume_cache
)
+ all_tenants = parsed_args.all_projects
+ project_id = None
+ if parsed_args.project:
+ all_tenants = True
+ project_id = identity_client.find_project(
+ parsed_args.project, ignore_missing=False
+ ).id
+
filter_volume_id = None
if parsed_args.volume:
try:
@@ -360,9 +374,10 @@ class ListVolumeBackup(command.Lister):
name=parsed_args.name,
status=parsed_args.status,
volume_id=filter_volume_id,
- all_tenants=parsed_args.all_projects,
+ all_tenants=all_tenants,
marker=marker_backup_id,
limit=parsed_args.limit,
+ project_id=project_id,
)
return (
diff --git a/openstackclient/volume/v3/volume_group.py b/openstackclient/volume/v3/volume_group.py
index 8433e57..1810fee 100644
--- a/openstackclient/volume/v3/volume_group.py
+++ b/openstackclient/volume/v3/volume_group.py
@@ -13,10 +13,10 @@
import argparse
from cinderclient import api_versions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.common import envvars
from openstackclient.i18n import _
diff --git a/openstackclient/volume/v3/volume_group_snapshot.py b/openstackclient/volume/v3/volume_group_snapshot.py
index 5a760ac..530b7d5 100644
--- a/openstackclient/volume/v3/volume_group_snapshot.py
+++ b/openstackclient/volume/v3/volume_group_snapshot.py
@@ -13,10 +13,10 @@
import logging
from openstack import utils as sdk_utils
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.common import envvars
from openstackclient.i18n import _
diff --git a/openstackclient/volume/v3/volume_group_type.py b/openstackclient/volume/v3/volume_group_type.py
index f1ef617..bdedd25 100644
--- a/openstackclient/volume/v3/volume_group_type.py
+++ b/openstackclient/volume/v3/volume_group_type.py
@@ -15,10 +15,10 @@ import logging
from cinderclient import api_versions
from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
diff --git a/openstackclient/volume/v3/volume_message.py b/openstackclient/volume/v3/volume_message.py
index 0fc724a..b39c579 100644
--- a/openstackclient/volume/v3/volume_message.py
+++ b/openstackclient/volume/v3/volume_message.py
@@ -17,10 +17,10 @@
import logging as LOG
from cinderclient import api_versions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.common import pagination
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
diff --git a/openstackclient/volume/v3/volume_snapshot.py b/openstackclient/volume/v3/volume_snapshot.py
index 9cbc198..6eddb5a 100644
--- a/openstackclient/volume/v3/volume_snapshot.py
+++ b/openstackclient/volume/v3/volume_snapshot.py
@@ -22,10 +22,10 @@ from cliff import columns as cliff_columns
from openstack.block_storage.v3 import snapshot as _snapshot
from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.common import pagination
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
@@ -33,7 +33,7 @@ from openstackclient.identity import common as identity_common
LOG = logging.getLogger(__name__)
-class VolumeIdColumn(cliff_columns.FormattableColumn):
+class VolumeIdColumn(cliff_columns.FormattableColumn[str]):
"""Formattable column for volume ID column.
Unlike the parent FormattableColumn class, the initializer of the
@@ -246,8 +246,8 @@ class DeleteVolumeSnapshot(command.Command):
_(
"Failed to delete snapshot with "
"name or ID '%(snapshot)s': %(e)s"
- )
- % {'snapshot': snapshot, 'e': e}
+ ),
+ {'snapshot': snapshot, 'e': e},
)
if result > 0:
diff --git a/openstackclient/volume/v3/volume_transfer_request.py b/openstackclient/volume/v3/volume_transfer_request.py
index b7add12..42fd37c 100644
--- a/openstackclient/volume/v3/volume_transfer_request.py
+++ b/openstackclient/volume/v3/volume_transfer_request.py
@@ -17,10 +17,10 @@
import logging
from cinderclient import api_versions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
@@ -163,8 +163,8 @@ class DeleteTransferRequest(command.Command):
_(
"Failed to delete volume transfer request "
"with name or ID '%(transfer)s': %(e)s"
- )
- % {'transfer': t, 'e': e}
+ ),
+ {'transfer': t, 'e': e},
)
if result > 0:
diff --git a/openstackclient/volume/v3/volume_type.py b/openstackclient/volume/v3/volume_type.py
index b5b328c..ba69252 100644
--- a/openstackclient/volume/v3/volume_type.py
+++ b/openstackclient/volume/v3/volume_type.py
@@ -10,21 +10,21 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
-#
"""Volume v3 Type action implementations"""
import functools
import logging
+import typing as ty
from cinderclient import api_versions
from cliff import columns as cliff_columns
from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
-from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
+from openstackclient import command
from openstackclient.i18n import _
from openstackclient.identity import common as identity_common
@@ -32,7 +32,7 @@ from openstackclient.identity import common as identity_common
LOG = logging.getLogger(__name__)
-class EncryptionInfoColumn(cliff_columns.FormattableColumn):
+class EncryptionInfoColumn(cliff_columns.FormattableColumn[ty.Any]):
"""Formattable column for encryption info column.
Unlike the parent FormattableColumn class, the initializer of the
@@ -172,7 +172,8 @@ class CreateVolumeType(command.ShowOne):
default=False,
help=_(
"Enabled replication for this volume type "
- "(this is an alias for '--property replication_enabled=<is> True') "
+ "(this is an alias for "
+ "'--property replication_enabled=<is> True') "
"(requires driver support)"
),
)
@@ -182,7 +183,8 @@ class CreateVolumeType(command.ShowOne):
dest='availability_zones',
help=_(
"Set an availability zone for this volume type "
- "(this is an alias for '--property RESKEY:availability_zones:<az>') "
+ "(this is an alias for "
+ "'--property RESKEY:availability_zones:<az>') "
"(repeat option to set multiple availability zones)"
),
)
@@ -275,7 +277,7 @@ class CreateVolumeType(command.ShowOne):
msg = _(
"Failed to add project %(project)s access to type: %(e)s"
)
- LOG.error(msg % {'project': parsed_args.project, 'e': e})
+ LOG.error(msg, {'project': parsed_args.project, 'e': e})
properties = {}
if parsed_args.properties:
@@ -356,8 +358,8 @@ class DeleteVolumeType(command.Command):
_(
"Failed to delete volume type with "
"name or ID '%(volume_type)s': %(e)s"
- )
- % {'volume_type': volume_type, 'e': e}
+ ),
+ {'volume_type': volume_type, 'e': e},
)
if result > 0:
@@ -447,7 +449,8 @@ class ListVolumeType(command.Lister):
default=False,
help=_(
"List only volume types with replication enabled "
- "(this is an alias for '--property replication_enabled=<is> True') "
+ "(this is an alias for "
+ "'--property replication_enabled=<is> True') "
"(supported by --os-volume-api-version 3.52 or above)"
),
)
@@ -457,7 +460,8 @@ class ListVolumeType(command.Lister):
dest='availability_zones',
help=_(
"List only volume types with this availability configured "
- "(this is an alias for '--property RESKEY:availability_zones:<az>') "
+ "(this is an alias for "
+ "'--property RESKEY:availability_zones:<az>') "
"(repeat option to filter on multiple availability zones)"
),
)
@@ -545,7 +549,7 @@ class ListVolumeType(command.Lister):
_EncryptionInfoColumn = functools.partial(
EncryptionInfoColumn, encryption_data=encryption
)
- formatters['id'] = _EncryptionInfoColumn
+ formatters['id'] = _EncryptionInfoColumn # type: ignore
return (
column_headers,
@@ -616,7 +620,8 @@ class SetVolumeType(command.Command):
default=False,
help=_(
"Enabled replication for this volume type "
- "(this is an alias for '--property replication_enabled=<is> True') "
+ "(this is an alias for "
+ "'--property replication_enabled=<is> True') "
"(requires driver support)"
),
)
@@ -626,7 +631,8 @@ class SetVolumeType(command.Command):
dest='availability_zones',
help=_(
"Set an availability zone for this volume type "
- "(this is an alias for '--property RESKEY:availability_zones:<az>') "
+ "(this is an alias for "
+ "'--property RESKEY:availability_zones:<az>') "
"(repeat option to set multiple availability zones)"
),
)
@@ -840,7 +846,7 @@ class ShowVolumeType(command.ShowOne):
'Failed to get access project list for volume type '
'%(type)s: %(e)s'
)
- LOG.error(msg % {'type': volume_type.id, 'e': e})
+ LOG.error(msg, {'type': volume_type.id, 'e': e})
volume_type._info.update({'access_project_ids': access_project_ids})
if parsed_args.encryption_type:
# show encryption type information for this volume type
diff --git a/pyproject.toml b/pyproject.toml
index 74f93cc..b23877e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -540,6 +540,23 @@ subnet_pool_set = "openstackclient.network.v2.subnet_pool:SetSubnetPool"
subnet_pool_show = "openstackclient.network.v2.subnet_pool:ShowSubnetPool"
subnet_pool_unset = "openstackclient.network.v2.subnet_pool:UnsetSubnetPool"
+# Tap-as-a-Service
+tap_flow_create = "openstackclient.network.v2.taas.tap_flow:CreateTapFlow"
+tap_flow_delete = "openstackclient.network.v2.taas.tap_flow:DeleteTapFlow"
+tap_flow_list = "openstackclient.network.v2.taas.tap_flow:ListTapFlow"
+tap_flow_show = "openstackclient.network.v2.taas.tap_flow:ShowTapFlow"
+tap_flow_update = "openstackclient.network.v2.taas.tap_flow:UpdateTapFlow"
+tap_mirror_create = "openstackclient.network.v2.taas.tap_mirror:CreateTapMirror"
+tap_mirror_delete = "openstackclient.network.v2.taas.tap_mirror:DeleteTapMirror"
+tap_mirror_list = "openstackclient.network.v2.taas.tap_mirror:ListTapMirror"
+tap_mirror_show = "openstackclient.network.v2.taas.tap_mirror:ShowTapMirror"
+tap_mirror_update = "openstackclient.network.v2.taas.tap_mirror:UpdateTapMirror"
+tap_service_create = "openstackclient.network.v2.taas.tap_service:CreateTapService"
+tap_service_delete = "openstackclient.network.v2.taas.tap_service:DeleteTapService"
+tap_service_list = "openstackclient.network.v2.taas.tap_service:ListTapService"
+tap_service_show = "openstackclient.network.v2.taas.tap_service:ShowTapService"
+tap_service_update = "openstackclient.network.v2.taas.tap_service:UpdateTapService"
+
[project.entry-points."openstack.object_store.v1"]
object_store_account_set = "openstackclient.object.v1.account:SetAccount"
object_store_account_show = "openstackclient.object.v1.account:ShowAccount"
@@ -727,14 +744,7 @@ follow_imports = "normal"
incremental = true
check_untyped_defs = true
warn_unused_ignores = true
-# keep this in-sync with 'mypy.exclude' in '.pre-commit-config.yaml'
-exclude = '''
-(?x)(
- doc
- | examples
- | releasenotes
- )
-'''
+exclude = '(?x)(doc | examples | hacking | releasenotes)'
[[tool.mypy.overrides]]
module = ["openstackclient.tests.unit.*"]
@@ -748,7 +758,7 @@ quote-style = "preserve"
docstring-code-format = true
[tool.ruff.lint]
-select = ["E4", "E7", "E9", "F", "S", "U"]
+select = ["E4", "E5", "E7", "E9", "F", "G", "S", "UP"]
[tool.ruff.lint.per-file-ignores]
-"openstackclient/tests/*" = ["S"]
+"openstackclient/tests/*" = ["E501", "S"]
diff --git a/releasenotes/notes/add-volume-backup-project-filter-6c09b2c8aba83341.yaml b/releasenotes/notes/add-volume-backup-project-filter-6c09b2c8aba83341.yaml
new file mode 100644
index 0000000..06bc7a4
--- /dev/null
+++ b/releasenotes/notes/add-volume-backup-project-filter-6c09b2c8aba83341.yaml
@@ -0,0 +1,5 @@
+---
+features:
+ - |
+ Add ``--project`` option to ``volume backup list`` command,
+ to allow filtering for projects when listing volume backups.
diff --git a/releasenotes/notes/bug-2126565-a119ac242d9ac795.yaml b/releasenotes/notes/bug-2126565-a119ac242d9ac795.yaml
new file mode 100644
index 0000000..87fe689
--- /dev/null
+++ b/releasenotes/notes/bug-2126565-a119ac242d9ac795.yaml
@@ -0,0 +1,8 @@
+---
+fixes:
+ - |
+ Running ``openstack application credential show`` on
+ a non-existent application credential does not
+ raise an exception.
+
+ [Bug `2126565 <https://bugs.launchpad.net/python-openstackclient/+bug/2126565>`_]
diff --git a/releasenotes/notes/bug-2137636-fix-quota-usage-display-2d8f07dccc21f79c.yaml b/releasenotes/notes/bug-2137636-fix-quota-usage-display-2d8f07dccc21f79c.yaml
new file mode 100644
index 0000000..818e29a
--- /dev/null
+++ b/releasenotes/notes/bug-2137636-fix-quota-usage-display-2d8f07dccc21f79c.yaml
@@ -0,0 +1,5 @@
+---
+fixes:
+ - |
+ Fix ``openstack quota show --usage`` to correctly display resource usage
+ and reservation.
diff --git a/releasenotes/notes/bug-2138903-f75c7348f22db195.yaml b/releasenotes/notes/bug-2138903-f75c7348f22db195.yaml
new file mode 100644
index 0000000..2492421
--- /dev/null
+++ b/releasenotes/notes/bug-2138903-f75c7348f22db195.yaml
@@ -0,0 +1,5 @@
+---
+fixes:
+ - |
+ The ``--all-stores`` of the ``image import`` command is now correctly
+ treated as a boolean flag.
diff --git a/releasenotes/notes/fix-image-set-project-accept-owner-bug-2136795.yaml b/releasenotes/notes/fix-image-set-project-accept-owner-bug-2136795.yaml
new file mode 100644
index 0000000..4cd755b
--- /dev/null
+++ b/releasenotes/notes/fix-image-set-project-accept-owner-bug-2136795.yaml
@@ -0,0 +1,10 @@
+---
+fixes:
+ - |
+ Fix a bug where using ``openstack image set --project <project>
+ --accept <image>`` incorrectly changed the image owner to the specified
+ project instead of only updating the member status. The ``--project``
+ parameter when used with ``--accept``, ``--reject``, or ``--pending``
+ should only identify which member's status to update, not change the
+ image ownership.
+ [Bug `2136795 <https://bugs.launchpad.net/python-openstackclient/+bug/2136795>`_]
diff --git a/releasenotes/notes/fix-resize-server-args-required-2e9013bcbf207f6a.yaml b/releasenotes/notes/fix-resize-server-args-required-2e9013bcbf207f6a.yaml
new file mode 100644
index 0000000..e1faf7e
--- /dev/null
+++ b/releasenotes/notes/fix-resize-server-args-required-2e9013bcbf207f6a.yaml
@@ -0,0 +1,8 @@
+---
+fixes:
+ - |
+ The ``openstack server resize`` command now requires the ``--flavor``
+ option or one of the deprecated ``--confirm`` or ``--revert`` options
+ to be provided.
+ Previously, the command would silently exit successfully without
+ performing any action if no option was provided.
diff --git a/releasenotes/notes/keystone-create-user-no-password-619bcddcd046dda8.yaml b/releasenotes/notes/keystone-create-user-no-password-619bcddcd046dda8.yaml
new file mode 100644
index 0000000..7cd6acb
--- /dev/null
+++ b/releasenotes/notes/keystone-create-user-no-password-619bcddcd046dda8.yaml
@@ -0,0 +1,6 @@
+---
+fixes:
+ - |
+ [Bug `2136148 <https://bugs.launchpad.net/bugs/2136148>`_] Keystone allows
+ users to be created with no password but no value should be submitted for
+ the password instead of a ``null`` value.
diff --git a/releasenotes/notes/limits-project-domain-option-84bfbb0e30e21b73.yaml b/releasenotes/notes/limits-project-domain-option-84bfbb0e30e21b73.yaml
new file mode 100644
index 0000000..ab94680
--- /dev/null
+++ b/releasenotes/notes/limits-project-domain-option-84bfbb0e30e21b73.yaml
@@ -0,0 +1,5 @@
+---
+features:
+ - |
+ Add ``--project-domain`` option for the ``limit list`` and ``limit create``
+ commands.
diff --git a/releasenotes/notes/migrate-federation-protocol-to-sdk-43dc2b50fb277da6.yaml b/releasenotes/notes/migrate-federation-protocol-to-sdk-43dc2b50fb277da6.yaml
new file mode 100644
index 0000000..ea3808a
--- /dev/null
+++ b/releasenotes/notes/migrate-federation-protocol-to-sdk-43dc2b50fb277da6.yaml
@@ -0,0 +1,7 @@
+---
+features:
+ - |
+ Migrate ``federation protocol`` commands from keystoneclient to SDK.
+upgrade:
+ - |
+ Filtering in ``federation protocol`` commands is now case sensitive.
diff --git a/releasenotes/notes/migrate-limit-to-sdk-378037ec2b79e302.yaml b/releasenotes/notes/migrate-limit-to-sdk-378037ec2b79e302.yaml
new file mode 100644
index 0000000..d4a5732
--- /dev/null
+++ b/releasenotes/notes/migrate-limit-to-sdk-378037ec2b79e302.yaml
@@ -0,0 +1,9 @@
+---
+features:
+ - |
+ Migrate ``limit`` commands from keystoneclient to SDK.
+upgrade:
+ - |
+ Filtering in ``limit`` commands is now case sensitive.
+ - |
+ Specifying ``--region None`` is no longer supported for ``limit`` commands.
diff --git a/releasenotes/notes/migrate-project-to-sdk-9201efd2804371de.yaml b/releasenotes/notes/migrate-project-to-sdk-9201efd2804371de.yaml
new file mode 100644
index 0000000..90c6031
--- /dev/null
+++ b/releasenotes/notes/migrate-project-to-sdk-9201efd2804371de.yaml
@@ -0,0 +1,7 @@
+---
+features:
+ - |
+ Migrate ``project`` commands from keystoneclient to SDK.
+upgrade:
+ - |
+ Filtering in ``project`` commands is now case sensitive.
diff --git a/releasenotes/notes/migrate-registered-limit-to-sdk-36b6451e3a799a43.yaml b/releasenotes/notes/migrate-registered-limit-to-sdk-36b6451e3a799a43.yaml
new file mode 100644
index 0000000..77f404a
--- /dev/null
+++ b/releasenotes/notes/migrate-registered-limit-to-sdk-36b6451e3a799a43.yaml
@@ -0,0 +1,10 @@
+---
+features:
+ - |
+ Migrate ``registered limit`` commands from keystoneclient to SDK.
+upgrade:
+ - |
+ Filtering in ``registered limit`` commands is now case sensitive.
+ - |
+ Specifying ``--region None`` is no longer supported for ``registered limit``
+ commands.
diff --git a/releasenotes/notes/use-project-domain-for-parent-cb29ee3f5adeb647.yaml b/releasenotes/notes/use-project-domain-for-parent-cb29ee3f5adeb647.yaml
new file mode 100644
index 0000000..acbf2ba
--- /dev/null
+++ b/releasenotes/notes/use-project-domain-for-parent-cb29ee3f5adeb647.yaml
@@ -0,0 +1,5 @@
+---
+upgrade:
+ - |
+ When creating or listing projects, parent project will now be searched from
+ the same domain as the child project.
diff --git a/releasenotes/notes/volume-delete-cascade-384003efc8896096.yaml b/releasenotes/notes/volume-delete-cascade-384003efc8896096.yaml
new file mode 100644
index 0000000..679964f
--- /dev/null
+++ b/releasenotes/notes/volume-delete-cascade-384003efc8896096.yaml
@@ -0,0 +1,6 @@
+---
+upgrade:
+ - |
+ The ``--purge`` argument to the ``volume delete`` command has been renamed
+ to ``--cascade`` to better match the Cinder API and the meaning of what
+ this argument does. An alias is provided for backwards compatibility.
diff --git a/releasenotes/source/2024.1.rst b/releasenotes/source/2024.1.rst
index 4977a4f..6896656 100644
--- a/releasenotes/source/2024.1.rst
+++ b/releasenotes/source/2024.1.rst
@@ -3,4 +3,4 @@
===========================
.. release-notes::
- :branch: stable/2024.1
+ :branch: unmaintained/2024.1
diff --git a/releasenotes/source/2025.2.rst b/releasenotes/source/2025.2.rst
new file mode 100644
index 0000000..4dae18d
--- /dev/null
+++ b/releasenotes/source/2025.2.rst
@@ -0,0 +1,6 @@
+===========================
+2025.2 Series Release Notes
+===========================
+
+.. release-notes::
+ :branch: stable/2025.2
diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst
index a9c0579..2b28cfb 100644
--- a/releasenotes/source/index.rst
+++ b/releasenotes/source/index.rst
@@ -6,6 +6,7 @@ OpenStackClient Release Notes
:maxdepth: 1
unreleased
+ 2025.2
2025.1
2024.2
2024.1
diff --git a/requirements.txt b/requirements.txt
index 9a9c79a..fc31d78 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,7 +5,7 @@
pbr!=2.1.0,>=2.0.0 # Apache-2.0
cryptography>=2.7 # BSD/Apache-2.0
-cliff>=4.8.0 # Apache-2.0
+cliff>=4.13.0 # Apache-2.0
iso8601>=0.1.11 # MIT
openstacksdk>=4.6.0 # Apache-2.0
osc-lib>=2.3.0 # Apache-2.0
diff --git a/tox.ini b/tox.ini
index 7b3d951..6ce9e96 100644
--- a/tox.ini
+++ b/tox.ini
@@ -4,118 +4,128 @@ envlist = py3,pep8
[testenv]
description =
- Run unit tests.
+ Run unit tests.
usedevelop = true
setenv =
- OS_STDOUT_CAPTURE=1
- OS_STDERR_CAPTURE=1
- OS_TEST_TIMEOUT=60
+ OS_STDOUT_CAPTURE=1
+ OS_STDERR_CAPTURE=1
+ OS_TEST_TIMEOUT=60
deps =
- -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
- -r{toxinidir}/test-requirements.txt
- -r{toxinidir}/requirements.txt
+ -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
+ -r{toxinidir}/test-requirements.txt
+ -r{toxinidir}/requirements.txt
commands =
- stestr run {posargs}
+ stestr run {posargs}
[testenv:pep8]
description =
- Run style checks.
-skip_install = true
+ Run style checks.
deps =
- pre-commit
+ pre-commit
+ {[testenv:mypy]deps}
commands =
- pre-commit run --all-files --show-diff-on-failure
+ pre-commit run --all-files --show-diff-on-failure
+ {[testenv:mypy]commands}
-[testenv:bandit]
+[testenv:mypy]
description =
- Run bandit security checks.
-skip_install = true
+ Run type checks.
deps =
- pre-commit
+ {[testenv]deps}
+ mypy
+ types-requests
commands =
- pre-commit run --all-files --show-diff-on-failure bandit
+ mypy --cache-dir="{envdir}/mypy_cache" {posargs:openstackclient}
[testenv:unit-tips]
commands =
- python -m pip install -q -U -e {toxinidir}/../cliff#egg=cliff
- python -m pip install -q -U -e {toxinidir}/../keystoneauth#egg=keystoneauth
- python -m pip install -q -U -e {toxinidir}/../osc-lib#egg=osc_lib
- python -m pip install -q -U -e {toxinidir}/../openstacksdk#egg=openstacksdk
- python -m pip freeze
- stestr run {posargs}
+ python -m pip install -q -U -e {toxinidir}/../cliff#egg=cliff
+ python -m pip install -q -U -e {toxinidir}/../keystoneauth#egg=keystoneauth
+ python -m pip install -q -U -e {toxinidir}/../osc-lib#egg=osc_lib
+ python -m pip install -q -U -e {toxinidir}/../openstacksdk#egg=openstacksdk
+ python -m pip freeze
+ stestr run {posargs}
-[testenv:functional{,-tips,-py38,-py39,-py310,-py311,-py312}]
+[testenv:functional{,-tips,-py310,-py311,-py312,-py313,-py314}]
description =
- Run functional tests.
+ Run functional tests.
setenv =
- OS_TEST_PATH=./openstackclient/tests/functional
+ OS_TEST_PATH=./openstackclient/tests/functional
passenv =
- OS_*
+ OS_*
commands =
- tips: python -m pip install -q -U -e {toxinidir}/../cliff#egg=cliff
- tips: python -m pip install -q -U -e {toxinidir}/../keystoneauth#egg=keystoneauth1
- tips: python -m pip install -q -U -e {toxinidir}/../osc-lib#egg=osc_lib
- tips: python -m pip install -q -U -e {toxinidir}/../openstacksdk#egg=openstacksdk
- tips: python -m pip freeze
- {[testenv]commands}
+ tips: python -m pip install -q -U -e {toxinidir}/../cliff#egg=cliff
+ tips: python -m pip install -q -U -e {toxinidir}/../keystoneauth#egg=keystoneauth1
+ tips: python -m pip install -q -U -e {toxinidir}/../osc-lib#egg=osc_lib
+ tips: python -m pip install -q -U -e {toxinidir}/../openstacksdk#egg=openstacksdk
+ tips: python -m pip freeze
+ {[testenv]commands}
[testenv:venv]
description =
- Run specified command in a virtual environment with all dependencies installed.
+ Run specified command in a virtual environment with all dependencies installed.
deps =
- -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
- -r{toxinidir}/requirements.txt
- -r{toxinidir}/doc/requirements.txt
+ -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
+ -r{toxinidir}/requirements.txt
+ -r{toxinidir}/doc/requirements.txt
commands =
- {posargs}
+ {posargs}
[testenv:cover]
description =
- Run unit tests and generate coverage report.
+ Run unit tests and generate coverage report.
setenv =
- {[testenv]setenv}
- PYTHON=coverage run --source openstackclient --parallel-mode
+ {[testenv]setenv}
+ PYTHON=coverage run --source openstackclient --parallel-mode
commands =
- stestr run {posargs}
- coverage combine
- coverage html -d cover
- coverage xml -o cover/coverage.xml
+ stestr run {posargs}
+ coverage combine
+ coverage html -d cover
+ coverage xml -o cover/coverage.xml
[testenv:debug]
description =
- Run specified tests through oslo_debug_helper, which allows use of pdb.
+ Run specified tests through oslo_debug_helper, which allows use of pdb.
passenv =
- OS_*
+ OS_*
commands =
- oslo_debug_helper -t openstackclient/tests {posargs}
+ oslo_debug_helper -t openstackclient/tests {posargs}
[testenv:docs]
description =
- Build documentation in HTML format.
+ Build documentation in HTML format.
deps =
- -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
- -r{toxinidir}/doc/requirements.txt
+ -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
+ -r{toxinidir}/doc/requirements.txt
commands =
- sphinx-build -a -E -W -d doc/build/doctrees -b html doc/source doc/build/html
- sphinx-build -a -E -W -d doc/build/doctrees -b man doc/source doc/build/man
- # Validate redirects (must be done after the docs build
- whereto doc/build/html/.htaccess doc/test/redirect-tests.txt
+ sphinx-build -a -E -W -d doc/build/doctrees -b html doc/source doc/build/html
+ sphinx-build -a -E -W -d doc/build/doctrees -b man doc/source doc/build/man
+ # Validate redirects (must be done after the docs build
+ whereto doc/build/html/.htaccess doc/test/redirect-tests.txt
[testenv:releasenotes]
description =
- Build release note documentation in HTML format.
+ Build release note documentation in HTML format.
deps =
- -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
- -r{toxinidir}/doc/requirements.txt
+ -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
+ -r{toxinidir}/doc/requirements.txt
commands =
- sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html
+ sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html
[flake8]
show-source = true
exclude = .venv,.git,.tox,dist,doc,*lib/python*,*egg,build,tools,releasenotes
-# We only enable the hacking (H) checks
-select = H
+# We only enable the hacking (H) and openstackclient (O) checks
+select = H,O
# H301 Black will put commas after imports that can't fit on one line
ignore = H301
import-order-style = pep8
application_import_names = openstackclient
+
+[flake8:local-plugins]
+extension =
+ O400 = checks:assert_no_oslo
+ O401 = checks:assert_no_duplicated_setup
+ O402 = checks:assert_use_of_client_aliases
+ O403 = checks:assert_find_ignore_missing_kwargs
+paths = ./hacking