Add --or-show option to user create

The --or-show option is added to create commands for the common case
of needing to ensure an object exists and getting its properties if
it does or creating a new one if it does not exist.

Note that if the object exists, any additional options that would
set values in a newly created object are ignored if the object
exists.

FakeResource needs the __name__ attribute to fall through utils.find_resource.

Prove the concept on v2 user create then propogate once we're happy with it...

Change-Id: I6268566514840c284e6a1d44b409a81d6699ef99
This commit is contained in:
Dean Troyer 2014-11-07 04:44:54 -06:00
parent 631ed3c802
commit 42d0b20ebc
3 changed files with 103 additions and 7 deletions

View File

@ -71,6 +71,11 @@ class CreateUser(show.ShowOne):
action='store_true',
help=_('Disable user'),
)
parser.add_argument(
'--or-show',
action='store_true',
help=_('Return existing user'),
)
return parser
def take_action(self, parsed_args):
@ -91,13 +96,24 @@ class CreateUser(show.ShowOne):
if parsed_args.password_prompt:
parsed_args.password = utils.get_password(self.app.stdin)
user = identity_client.users.create(
parsed_args.name,
parsed_args.password,
parsed_args.email,
tenant_id=project_id,
enabled=enabled,
)
try:
user = identity_client.users.create(
parsed_args.name,
parsed_args.password,
parsed_args.email,
tenant_id=project_id,
enabled=enabled,
)
except ksc_exc.Conflict as e:
if parsed_args.or_show:
user = utils.find_resource(
identity_client.users,
parsed_args.name,
)
self.log.info('Returning existing user %s', user.name)
else:
raise e
# NOTE(dtroyer): The users.create() method wants 'tenant_id' but
# the returned resource has 'tenantId'. Sigh.
# We're using project_id now inside OSC so there.

View File

@ -210,6 +210,7 @@ class FakeModule(object):
class FakeResource(object):
def __init__(self, manager, info, loaded=False):
self.__name__ = type(self).__name__
self.manager = manager
self._info = info
self._add_details(info)

View File

@ -16,6 +16,7 @@
import copy
import mock
from keystoneclient.openstack.common.apiclient import exceptions as ksc_exc
from openstackclient.identity.v2_0 import user
from openstackclient.tests import fakes
from openstackclient.tests.identity.v2_0 import fakes as identity_fakes
@ -342,6 +343,84 @@ class TestUserCreate(TestUser):
)
self.assertEqual(data, datalist)
def test_user_create_or_show_exists(self):
def _raise_conflict(*args, **kwargs):
raise ksc_exc.Conflict(None)
# need to make this throw an exception...
self.users_mock.create.side_effect = _raise_conflict
self.users_mock.get.return_value = fakes.FakeResource(
None,
copy.deepcopy(identity_fakes.USER),
loaded=True,
)
arglist = [
'--or-show',
identity_fakes.user_name,
]
verifylist = [
('name', identity_fakes.user_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)
# UserManager.create(name, password, email, tenant_id=, enabled=)
self.users_mock.get.assert_called_with(identity_fakes.user_name)
collist = ('email', 'enabled', 'id', 'name', 'project_id')
self.assertEqual(collist, columns)
datalist = (
identity_fakes.user_email,
True,
identity_fakes.user_id,
identity_fakes.user_name,
identity_fakes.project_id,
)
self.assertEqual(datalist, data)
def test_user_create_or_show_not_exists(self):
arglist = [
'--or-show',
identity_fakes.user_name,
]
verifylist = [
('name', identity_fakes.user_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 = {
'enabled': True,
'tenant_id': None,
}
# UserManager.create(name, password, email, tenant_id=, enabled=)
self.users_mock.create.assert_called_with(
identity_fakes.user_name,
None,
None,
**kwargs
)
collist = ('email', 'enabled', 'id', 'name', 'project_id')
self.assertEqual(collist, columns)
datalist = (
identity_fakes.user_email,
True,
identity_fakes.user_id,
identity_fakes.user_name,
identity_fakes.project_id,
)
self.assertEqual(datalist, data)
class TestUserDelete(TestUser):