diff --git a/openstackclient/identity/v2_0/project.py b/openstackclient/identity/v2_0/project.py index 7ead0890d..2d66b400d 100644 --- a/openstackclient/identity/v2_0/project.py +++ b/openstackclient/identity/v2_0/project.py @@ -63,6 +63,11 @@ class CreateProject(show.ShowOne): help=_('Property to add for this project ' '(repeat option to set multiple properties)'), ) + parser.add_argument( + '--or-show', + action='store_true', + help=_('Return existing project'), + ) return parser def take_action(self, parsed_args): @@ -76,12 +81,22 @@ class CreateProject(show.ShowOne): if parsed_args.property: kwargs = parsed_args.property.copy() - project = identity_client.tenants.create( - parsed_args.name, - description=parsed_args.description, - enabled=enabled, - **kwargs - ) + try: + project = identity_client.tenants.create( + parsed_args.name, + description=parsed_args.description, + enabled=enabled, + **kwargs + ) + except ksc_exc.Conflict as e: + if parsed_args.or_show: + project = utils.find_resource( + identity_client.tenants, + parsed_args.name, + ) + self.log.info('Returning existing project %s', project.name) + else: + raise e info = {} info.update(project._info) diff --git a/openstackclient/identity/v2_0/role.py b/openstackclient/identity/v2_0/role.py index 4c45004da..df69e857a 100644 --- a/openstackclient/identity/v2_0/role.py +++ b/openstackclient/identity/v2_0/role.py @@ -21,6 +21,7 @@ import six from cliff import command from cliff import lister from cliff import show +from keystoneclient.openstack.common.apiclient import exceptions as ksc_exc from openstackclient.common import exceptions from openstackclient.common import utils @@ -81,12 +82,27 @@ class CreateRole(show.ShowOne): 'role_name', metavar='', help=_('New role name')) + parser.add_argument( + '--or-show', + action='store_true', + help=_('Return existing role'), + ) return parser def take_action(self, parsed_args): self.log.debug('take_action(%s)', parsed_args) identity_client = self.app.client_manager.identity - role = identity_client.roles.create(parsed_args.role_name) + try: + role = identity_client.roles.create(parsed_args.role_name) + except ksc_exc.Conflict as e: + if parsed_args.or_show: + role = utils.find_resource( + identity_client.roles, + parsed_args.role_name, + ) + self.log.info('Returning existing role %s', role.name) + else: + raise e info = {} info.update(role._info) diff --git a/openstackclient/tests/identity/v2_0/test_project.py b/openstackclient/tests/identity/v2_0/test_project.py index d046cd479..833b5d84d 100644 --- a/openstackclient/tests/identity/v2_0/test_project.py +++ b/openstackclient/tests/identity/v2_0/test_project.py @@ -15,6 +15,8 @@ import copy +from keystoneclient.openstack.common.apiclient import exceptions as ksc_exc + from openstackclient.identity.v2_0 import project from openstackclient.tests import fakes from openstackclient.tests.identity.v2_0 import fakes as identity_fakes @@ -219,6 +221,89 @@ class TestProjectCreate(TestProject): ) self.assertEqual(data, datalist) + def test_project_create_or_show_exists(self): + def _raise_conflict(*args, **kwargs): + raise ksc_exc.Conflict(None) + + # need to make this throw an exception... + self.projects_mock.create.side_effect = _raise_conflict + + self.projects_mock.get.return_value = fakes.FakeResource( + None, + copy.deepcopy(identity_fakes.PROJECT), + loaded=True, + ) + + arglist = [ + '--or-show', + identity_fakes.project_name, + ] + verifylist = [ + ('name', identity_fakes.project_name), + ('or_show', True), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # DisplayCommandBase.take_action() returns two tuples + columns, data = self.cmd.take_action(parsed_args) + + # ProjectManager.create(name, description, enabled) + self.projects_mock.get.assert_called_with(identity_fakes.project_name) + + # Set expected values + kwargs = { + 'description': None, + 'enabled': True, + } + self.projects_mock.create.assert_called_with( + identity_fakes.project_name, + **kwargs + ) + + collist = ('description', 'enabled', 'id', 'name') + self.assertEqual(collist, columns) + datalist = ( + identity_fakes.project_description, + True, + identity_fakes.project_id, + identity_fakes.project_name, + ) + self.assertEqual(datalist, data) + + def test_project_create_or_show_not_exists(self): + arglist = [ + '--or-show', + identity_fakes.project_name, + ] + verifylist = [ + ('name', identity_fakes.project_name), + ('or_show', True), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # DisplayCommandBase.take_action() returns two tuples + columns, data = self.cmd.take_action(parsed_args) + + # Set expected values + kwargs = { + 'description': None, + 'enabled': True, + } + self.projects_mock.create.assert_called_with( + identity_fakes.project_name, + **kwargs + ) + + collist = ('description', 'enabled', 'id', 'name') + self.assertEqual(collist, columns) + datalist = ( + identity_fakes.project_description, + True, + identity_fakes.project_id, + identity_fakes.project_name, + ) + self.assertEqual(datalist, data) + class TestProjectDelete(TestProject): diff --git a/openstackclient/tests/identity/v2_0/test_role.py b/openstackclient/tests/identity/v2_0/test_role.py index d515bd7cd..67467747f 100644 --- a/openstackclient/tests/identity/v2_0/test_role.py +++ b/openstackclient/tests/identity/v2_0/test_role.py @@ -16,6 +16,8 @@ import copy import mock +from keystoneclient.openstack.common.apiclient import exceptions as ksc_exc + from openstackclient.common import exceptions from openstackclient.identity.v2_0 import role from openstackclient.tests import fakes @@ -142,6 +144,75 @@ class TestRoleCreate(TestRole): ) self.assertEqual(data, datalist) + def test_role_create_or_show_exists(self): + def _raise_conflict(*args, **kwargs): + raise ksc_exc.Conflict(None) + + # need to make this throw an exception... + self.roles_mock.create.side_effect = _raise_conflict + + self.roles_mock.get.return_value = fakes.FakeResource( + None, + copy.deepcopy(identity_fakes.ROLE), + loaded=True, + ) + + arglist = [ + '--or-show', + identity_fakes.role_name, + ] + verifylist = [ + ('role_name', identity_fakes.role_name), + ('or_show', True), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # DisplayCommandBase.take_action() returns two tuples + columns, data = self.cmd.take_action(parsed_args) + + # RoleManager.get(name, description, enabled) + self.roles_mock.get.assert_called_with(identity_fakes.role_name) + + # RoleManager.create(name) + self.roles_mock.create.assert_called_with( + identity_fakes.role_name, + ) + + collist = ('id', 'name') + self.assertEqual(collist, columns) + datalist = ( + identity_fakes.role_id, + identity_fakes.role_name, + ) + self.assertEqual(datalist, data) + + def test_role_create_or_show_not_exists(self): + arglist = [ + '--or-show', + identity_fakes.role_name, + ] + verifylist = [ + ('role_name', identity_fakes.role_name), + ('or_show', True), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # DisplayCommandBase.take_action() returns two tuples + columns, data = self.cmd.take_action(parsed_args) + + # RoleManager.create(name) + self.roles_mock.create.assert_called_with( + identity_fakes.role_name, + ) + + collist = ('id', 'name') + self.assertEqual(collist, columns) + datalist = ( + identity_fakes.role_id, + identity_fakes.role_name, + ) + self.assertEqual(datalist, data) + class TestRoleDelete(TestRole):