diff --git a/.gitreview b/.gitreview index 4eee726db..78b05ab9c 100644 --- a/.gitreview +++ b/.gitreview @@ -2,3 +2,4 @@ host=review.opendev.org port=29418 project=openstack/python-openstackclient.git +defaultbranch=stable/2023.1 diff --git a/.zuul.yaml b/.zuul.yaml index 2c66c74af..49659551a 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -1,42 +1,4 @@ --- -- job: - name: osc-tox-unit-tips - parent: openstack-tox - description: | - Run unit tests for OpenStackClient with master branch of important libs. - - Takes advantage of the base tox job's install-siblings feature. - required-projects: - - openstack/cliff - - openstack/keystoneauth - - openstack/openstacksdk - - openstack/osc-lib - - openstack/python-openstackclient - vars: - # Set work dir to openstackclient so that if it's triggered by one of the - # other repos the tests will run in the same place - zuul_work_dir: src/opendev.org/openstack/python-openstackclient - -- job: - name: osc-tox-py38-tips - parent: openstack-tox-py38 - description: | - Run unit tests for OpenStackClient with master branch of important libs. - - Takes advantage of the base tox job's install-siblings feature. - # The job only tests the latest and shouldn't be run on the stable branches - branches: ^(?!stable) - required-projects: - - openstack/cliff - - openstack/keystoneauth - - openstack/openstacksdk - - openstack/osc-lib - - openstack/python-openstackclient - vars: - # Set work dir to openstackclient so that if it's triggered by one of the - # other repos the tests will run in the same place - zuul_work_dir: src/opendev.org/openstack/python-openstackclient - - job: name: osc-functional-devstack parent: devstack-tox-functional @@ -99,26 +61,6 @@ tox_envlist: functional zuul_work_dir: src/opendev.org/openstack/python-openstackclient -- job: - name: osc-functional-devstack-tips - parent: osc-functional-devstack - description: | - Run functional tests for OpenStackClient with master branch of important libs. - - Takes advantage of the base tox job's install-siblings feature. - timeout: 7800 - required-projects: - - openstack/cliff - - openstack/keystoneauth - - openstack/openstacksdk - - openstack/osc-lib - - openstack/python-openstackclient - vars: - devstack_localrc: - LIBS_FROM_GIT: python-openstackclient,openstacksdk,osc-lib,cliff - tox_envlist: functional - tox_install_siblings: true - - secret: name: osc-dockerhub data: @@ -177,19 +119,9 @@ nodes: [] vars: *osc_image_vars -- project-template: - name: osc-tox-unit-tips - check: - jobs: - - osc-tox-py38-tips - gate: - jobs: - - osc-tox-py38-tips - - project: templates: - openstackclient-plugin-jobs - - osc-tox-unit-tips - openstack-cover-jobs - openstack-python3-jobs - publish-openstack-docs-pti @@ -199,10 +131,6 @@ jobs: - osc-build-image - osc-functional-devstack - - osc-functional-devstack-tips: - # The functional-tips job only tests the latest and shouldn't be run - # on the stable branches - branches: ^(?!stable) gate: jobs: - osc-upload-image diff --git a/openstackclient/identity/common.py b/openstackclient/identity/common.py index a75db4f8d..116d8ad8a 100644 --- a/openstackclient/identity/common.py +++ b/openstackclient/identity/common.py @@ -87,6 +87,18 @@ def get_resource(manager, name_type_or_id): raise exceptions.CommandError(msg % name_type_or_id) +def get_resource_by_id(manager, resource_id): + """Get resource by ID + + Raises CommandError if the resource is not found + """ + try: + return manager.get(resource_id) + except identity_exc.NotFound: + msg = _("Resource with id {} not found") + raise exceptions.CommandError(msg.format(resource_id)) + + def _get_token_resource(client, resource, parsed_name, parsed_domain=None): """Peek into the user's auth token to get resource IDs diff --git a/openstackclient/identity/v3/access_rule.py b/openstackclient/identity/v3/access_rule.py index ffda04f9e..e57e1b617 100644 --- a/openstackclient/identity/v3/access_rule.py +++ b/openstackclient/identity/v3/access_rule.py @@ -37,7 +37,7 @@ def get_parser(self, prog_name): 'access_rule', metavar='', nargs="+", - help=_('Access rule(s) to delete (name or ID)'), + help=_('Access rule ID(s) to delete'), ) return parser @@ -47,8 +47,9 @@ def take_action(self, parsed_args): errors = 0 for ac in parsed_args.access_rule: try: - access_rule = utils.find_resource( - identity_client.access_rules, ac) + access_rule = common.get_resource_by_id( + identity_client.access_rules, ac + ) identity_client.access_rules.delete(access_rule.id) except Exception as e: errors += 1 @@ -103,14 +104,15 @@ def get_parser(self, prog_name): parser.add_argument( 'access_rule', metavar='', - help=_('Access rule to display (name or ID)'), + help=_('Access rule ID to display'), ) return parser def take_action(self, parsed_args): identity_client = self.app.client_manager.identity - access_rule = utils.find_resource(identity_client.access_rules, - parsed_args.access_rule) + access_rule = common.get_resource_by_id( + identity_client.access_rules, parsed_args.access_rule + ) access_rule._info.pop('links', None) diff --git a/openstackclient/network/v2/network_service_provider.py b/openstackclient/network/v2/network_service_provider.py index 157948cc4..f743bfa6e 100644 --- a/openstackclient/network/v2/network_service_provider.py +++ b/openstackclient/network/v2/network_service_provider.py @@ -26,18 +26,24 @@ def take_action(self, parsed_args): client = self.app.client_manager.network columns = ( - 'service_type', - 'name', - 'is_default', + "service_type", + "name", + "is_default", ) column_headers = ( - 'Service Type', - 'Name', - 'Default', + "Service Type", + "Name", + "Default", ) data = client.service_providers() - return(column_headers, - (utils.get_item_properties( - s, columns, - ) for s in data)) + return ( + column_headers, + ( + utils.get_item_properties( + s, + columns, + ) + for s in data + ), + ) diff --git a/openstackclient/tests/unit/identity/v3/test_access_rule.py b/openstackclient/tests/unit/identity/v3/test_access_rule.py index 904fe323d..ed957a90c 100644 --- a/openstackclient/tests/unit/identity/v3/test_access_rule.py +++ b/openstackclient/tests/unit/identity/v3/test_access_rule.py @@ -14,10 +14,9 @@ # import copy -from unittest import mock +from keystoneclient import exceptions as identity_exc from osc_lib import exceptions -from osc_lib import utils from openstackclient.identity.v3 import access_rule from openstackclient.tests.unit import fakes @@ -69,10 +68,13 @@ def test_access_rule_delete(self): ) self.assertIsNone(result) - @mock.patch.object(utils, 'find_resource') - def test_delete_multi_access_rules_with_exception(self, find_mock): - find_mock.side_effect = [self.access_rules_mock.get.return_value, - exceptions.CommandError] + def test_delete_multi_access_rules_with_exception(self): + # mock returns for common.get_resource_by_id + mock_get = self.access_rules_mock.get + mock_get.side_effect = [ + mock_get.return_value, + identity_exc.NotFound, + ] arglist = [ identity_fakes.access_rule_id, 'nonexistent_access_rule', @@ -89,12 +91,10 @@ def test_delete_multi_access_rules_with_exception(self, find_mock): self.assertEqual('1 of 2 access rules failed to' ' delete.', str(e)) - find_mock.assert_any_call(self.access_rules_mock, - identity_fakes.access_rule_id) - find_mock.assert_any_call(self.access_rules_mock, - 'nonexistent_access_rule') + mock_get.assert_any_call(identity_fakes.access_rule_id) + mock_get.assert_any_call('nonexistent_access_rule') - self.assertEqual(2, find_mock.call_count) + self.assertEqual(2, mock_get.call_count) self.access_rules_mock.delete.assert_called_once_with( identity_fakes.access_rule_id) diff --git a/releasenotes/notes/fix-story-2010775-953dbdf03b2b6746.yaml b/releasenotes/notes/fix-story-2010775-953dbdf03b2b6746.yaml new file mode 100644 index 000000000..e4c98b744 --- /dev/null +++ b/releasenotes/notes/fix-story-2010775-953dbdf03b2b6746.yaml @@ -0,0 +1,8 @@ +--- +fixes: + - | + Fixed a bug in "access rule" subcommands where the client logic incorrectly + assumed that access rules have a "name" property which resulted in + unpredictable behaviors. e.g. "access rule delete {non-existent-id}" now + results in a not-found error instead of sometimes deleting an unrelated + rule. diff --git a/tox.ini b/tox.ini index 3de7dd380..03b3b6d16 100644 --- a/tox.ini +++ b/tox.ini @@ -15,7 +15,7 @@ setenv = OS_STDERR_CAPTURE=1 OS_TEST_TIMEOUT=60 deps = - -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} + -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/2023.1} -r{toxinidir}/test-requirements.txt -r{toxinidir}/requirements.txt commands = stestr run {posargs} @@ -98,7 +98,7 @@ commands = [testenv:venv] deps = - -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} + -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/2023.1} -r{toxinidir}/requirements.txt -r{toxinidir}/doc/requirements.txt commands = {posargs} @@ -121,7 +121,7 @@ commands = [testenv:docs] deps = - -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} + -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/2023.1} -r{toxinidir}/doc/requirements.txt commands = sphinx-build -a -E -W -d doc/build/doctrees -b html doc/source doc/build/html @@ -131,7 +131,7 @@ commands = [testenv:releasenotes] deps = - -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} + -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/2023.1} -r{toxinidir}/doc/requirements.txt commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html