Merge "identity: Migrate 'application credential' commands to SDK"
This commit is contained in:
commit
7de15cee16
@ -18,6 +18,7 @@
|
|||||||
import datetime
|
import datetime
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
import uuid
|
||||||
|
|
||||||
from osc_lib.command import command
|
from osc_lib.command import command
|
||||||
from osc_lib import exceptions
|
from osc_lib import exceptions
|
||||||
@ -30,6 +31,30 @@ from openstackclient.identity import common
|
|||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO(stephenfin): Move this to osc_lib since it's useful elsewhere
|
||||||
|
def is_uuid_like(value) -> bool:
|
||||||
|
"""Returns validation of a value as a UUID.
|
||||||
|
|
||||||
|
:param val: Value to verify
|
||||||
|
:type val: string
|
||||||
|
:returns: bool
|
||||||
|
|
||||||
|
.. versionchanged:: 1.1.1
|
||||||
|
Support non-lowercase UUIDs.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
formatted_value = (
|
||||||
|
value.replace('urn:', '')
|
||||||
|
.replace('uuid:', '')
|
||||||
|
.strip('{}')
|
||||||
|
.replace('-', '')
|
||||||
|
.lower()
|
||||||
|
)
|
||||||
|
return str(uuid.UUID(value)).replace('-', '') == formatted_value
|
||||||
|
except (TypeError, ValueError, AttributeError):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class CreateApplicationCredential(command.ShowOne):
|
class CreateApplicationCredential(command.ShowOne):
|
||||||
_description = _("Create new application credential")
|
_description = _("Create new application credential")
|
||||||
|
|
||||||
@ -105,19 +130,16 @@ class CreateApplicationCredential(command.ShowOne):
|
|||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
identity_client = self.app.client_manager.identity
|
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)
|
||||||
|
|
||||||
role_ids = []
|
role_ids = []
|
||||||
for role in parsed_args.role:
|
for role in parsed_args.role:
|
||||||
# A user can only create an application credential for themself,
|
if is_uuid_like(role):
|
||||||
# not for another user even as an admin, and only on the project to
|
role_ids.append({'id': role})
|
||||||
# which they are currently scoped with a subset of the role
|
else:
|
||||||
# assignments they have on that project. Don't bother trying to
|
role_ids.append({'name': role})
|
||||||
# look up roles via keystone, just introspect the token.
|
|
||||||
role_id = common._get_token_resource(
|
|
||||||
identity_client, "roles", role
|
|
||||||
)
|
|
||||||
role_ids.append(role_id)
|
|
||||||
|
|
||||||
expires_at = None
|
expires_at = None
|
||||||
if parsed_args.expiration:
|
if parsed_args.expiration:
|
||||||
@ -144,10 +166,10 @@ class CreateApplicationCredential(command.ShowOne):
|
|||||||
)
|
)
|
||||||
raise exceptions.CommandError(msg)
|
raise exceptions.CommandError(msg)
|
||||||
else:
|
else:
|
||||||
access_rules = None
|
access_rules = []
|
||||||
|
|
||||||
app_cred_manager = identity_client.application_credentials
|
application_credential = identity_client.create_application_credential(
|
||||||
application_credential = app_cred_manager.create(
|
user_id,
|
||||||
parsed_args.name,
|
parsed_args.name,
|
||||||
roles=role_ids,
|
roles=role_ids,
|
||||||
expires_at=expires_at,
|
expires_at=expires_at,
|
||||||
@ -157,14 +179,32 @@ class CreateApplicationCredential(command.ShowOne):
|
|||||||
access_rules=access_rules,
|
access_rules=access_rules,
|
||||||
)
|
)
|
||||||
|
|
||||||
application_credential._info.pop('links', None)
|
|
||||||
|
|
||||||
# Format roles into something sensible
|
# Format roles into something sensible
|
||||||
roles = application_credential._info.pop('roles')
|
if application_credential['roles']:
|
||||||
msg = ' '.join(r['name'] for r in roles)
|
roles = application_credential['roles']
|
||||||
application_credential._info['roles'] = msg
|
msg = ' '.join(r['name'] for r in roles)
|
||||||
|
application_credential['roles'] = msg
|
||||||
|
|
||||||
return zip(*sorted(application_credential._info.items()))
|
columns = (
|
||||||
|
'ID',
|
||||||
|
'Name',
|
||||||
|
'Description',
|
||||||
|
'Project ID',
|
||||||
|
'Roles',
|
||||||
|
'Unrestricted',
|
||||||
|
'Access Rules',
|
||||||
|
'Expires At',
|
||||||
|
'Secret',
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
columns,
|
||||||
|
(
|
||||||
|
utils.get_dict_properties(
|
||||||
|
application_credential,
|
||||||
|
columns,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class DeleteApplicationCredential(command.Command):
|
class DeleteApplicationCredential(command.Command):
|
||||||
@ -181,15 +221,19 @@ class DeleteApplicationCredential(command.Command):
|
|||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
identity_client = self.app.client_manager.identity
|
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)
|
||||||
|
|
||||||
errors = 0
|
errors = 0
|
||||||
for ac in parsed_args.application_credential:
|
for ac in parsed_args.application_credential:
|
||||||
try:
|
try:
|
||||||
app_cred = utils.find_resource(
|
app_cred = identity_client.find_application_credential(
|
||||||
identity_client.application_credentials, ac
|
user_id, ac
|
||||||
|
)
|
||||||
|
identity_client.delete_application_credential(
|
||||||
|
user_id, app_cred.id
|
||||||
)
|
)
|
||||||
identity_client.application_credentials.delete(app_cred.id)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
errors += 1
|
errors += 1
|
||||||
LOG.error(
|
LOG.error(
|
||||||
@ -223,16 +267,36 @@ class ListApplicationCredential(command.Lister):
|
|||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
identity_client = self.app.client_manager.identity
|
identity_client = self.app.client_manager.sdk_connection.identity
|
||||||
if parsed_args.user:
|
if parsed_args.user:
|
||||||
user_id = common.find_user(
|
user_id = common.find_user(
|
||||||
identity_client, parsed_args.user, parsed_args.user_domain
|
identity_client, parsed_args.user, parsed_args.user_domain
|
||||||
).id
|
).id
|
||||||
else:
|
else:
|
||||||
user_id = None
|
conn = self.app.client_manager.sdk_connection
|
||||||
|
user_id = conn.config.get_auth().get_user_id(conn.identity)
|
||||||
|
|
||||||
columns = ('ID', 'Name', 'Project ID', 'Description', 'Expires At')
|
data = identity_client.application_credentials(user=user_id)
|
||||||
data = identity_client.application_credentials.list(user=user_id)
|
|
||||||
|
data_formatted = []
|
||||||
|
for ac in data:
|
||||||
|
# Format roles into something sensible
|
||||||
|
roles = ac['roles']
|
||||||
|
msg = ' '.join(r['name'] for r in roles)
|
||||||
|
ac['roles'] = msg
|
||||||
|
|
||||||
|
data_formatted.append(ac)
|
||||||
|
|
||||||
|
columns = (
|
||||||
|
'ID',
|
||||||
|
'Name',
|
||||||
|
'Description',
|
||||||
|
'Project ID',
|
||||||
|
'Roles',
|
||||||
|
'Unrestricted',
|
||||||
|
'Access Rules',
|
||||||
|
'Expires At',
|
||||||
|
)
|
||||||
return (
|
return (
|
||||||
columns,
|
columns,
|
||||||
(
|
(
|
||||||
@ -241,7 +305,7 @@ class ListApplicationCredential(command.Lister):
|
|||||||
columns,
|
columns,
|
||||||
formatters={},
|
formatters={},
|
||||||
)
|
)
|
||||||
for s in data
|
for s in data_formatted
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -259,17 +323,35 @@ class ShowApplicationCredential(command.ShowOne):
|
|||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
identity_client = self.app.client_manager.identity
|
identity_client = self.app.client_manager.sdk_connection.identity
|
||||||
app_cred = utils.find_resource(
|
conn = self.app.client_manager.sdk_connection
|
||||||
identity_client.application_credentials,
|
user_id = conn.config.get_auth().get_user_id(conn.identity)
|
||||||
parsed_args.application_credential,
|
|
||||||
|
app_cred = identity_client.find_application_credential(
|
||||||
|
user_id, parsed_args.application_credential
|
||||||
)
|
)
|
||||||
|
|
||||||
app_cred._info.pop('links', None)
|
|
||||||
|
|
||||||
# Format roles into something sensible
|
# Format roles into something sensible
|
||||||
roles = app_cred._info.pop('roles')
|
roles = app_cred['roles']
|
||||||
msg = ' '.join(r['name'] for r in roles)
|
msg = ' '.join(r['name'] for r in roles)
|
||||||
app_cred._info['roles'] = msg
|
app_cred['roles'] = msg
|
||||||
|
|
||||||
return zip(*sorted(app_cred._info.items()))
|
columns = (
|
||||||
|
'ID',
|
||||||
|
'Name',
|
||||||
|
'Description',
|
||||||
|
'Project ID',
|
||||||
|
'Roles',
|
||||||
|
'Unrestricted',
|
||||||
|
'Access Rules',
|
||||||
|
'Expires At',
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
columns,
|
||||||
|
(
|
||||||
|
utils.get_dict_properties(
|
||||||
|
app_cred,
|
||||||
|
columns,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
@ -21,13 +21,13 @@ from openstackclient.tests.functional.identity.v3 import common
|
|||||||
|
|
||||||
class ApplicationCredentialTests(common.IdentityTests):
|
class ApplicationCredentialTests(common.IdentityTests):
|
||||||
APPLICATION_CREDENTIAL_FIELDS = [
|
APPLICATION_CREDENTIAL_FIELDS = [
|
||||||
'id',
|
'ID',
|
||||||
'name',
|
'Name',
|
||||||
'project_id',
|
'Project ID',
|
||||||
'description',
|
'Description',
|
||||||
'roles',
|
'Roles',
|
||||||
'expires_at',
|
'Expires At',
|
||||||
'unrestricted',
|
'Unrestricted',
|
||||||
]
|
]
|
||||||
APPLICATION_CREDENTIAL_LIST_HEADERS = [
|
APPLICATION_CREDENTIAL_LIST_HEADERS = [
|
||||||
'ID',
|
'ID',
|
||||||
|
@ -13,37 +13,58 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
import copy
|
import datetime
|
||||||
import json
|
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
from unittest.mock import call
|
||||||
|
|
||||||
from osc_lib import exceptions
|
from osc_lib import exceptions
|
||||||
from osc_lib import utils
|
|
||||||
|
|
||||||
|
from openstack import exceptions as sdk_exceptions
|
||||||
|
from openstack.identity.v3 import (
|
||||||
|
application_credential as _application_credential,
|
||||||
|
)
|
||||||
|
from openstack.identity.v3 import role as _role
|
||||||
|
from openstack.test import fakes as sdk_fakes
|
||||||
from openstackclient.identity.v3 import application_credential
|
from openstackclient.identity.v3 import application_credential
|
||||||
from openstackclient.tests.unit import fakes
|
|
||||||
from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes
|
from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes
|
||||||
|
|
||||||
|
|
||||||
class TestApplicationCredential(identity_fakes.TestIdentityv3):
|
class TestApplicationCredentialCreate(identity_fakes.TestIdentityv3):
|
||||||
|
columns = (
|
||||||
|
'ID',
|
||||||
|
'Name',
|
||||||
|
'Description',
|
||||||
|
'Project ID',
|
||||||
|
'Roles',
|
||||||
|
'Unrestricted',
|
||||||
|
'Access Rules',
|
||||||
|
'Expires At',
|
||||||
|
'Secret',
|
||||||
|
)
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
|
|
||||||
identity_manager = self.identity_client
|
self.roles = sdk_fakes.generate_fake_resource(_role.Role)
|
||||||
self.app_creds_mock = identity_manager.application_credentials
|
self.application_credential = sdk_fakes.generate_fake_resource(
|
||||||
self.app_creds_mock.reset_mock()
|
resource_type=_application_credential.ApplicationCredential,
|
||||||
self.roles_mock = identity_manager.roles
|
roles=[],
|
||||||
self.roles_mock.reset_mock()
|
)
|
||||||
|
|
||||||
|
self.datalist = (
|
||||||
|
self.application_credential.id,
|
||||||
|
self.application_credential.name,
|
||||||
|
self.application_credential.description,
|
||||||
|
self.application_credential.project_id,
|
||||||
|
self.application_credential.roles,
|
||||||
|
self.application_credential.unrestricted,
|
||||||
|
self.application_credential.access_rules,
|
||||||
|
self.application_credential.expires_at,
|
||||||
|
self.application_credential.secret,
|
||||||
|
)
|
||||||
|
|
||||||
class TestApplicationCredentialCreate(TestApplicationCredential):
|
self.identity_sdk_client.create_application_credential.return_value = (
|
||||||
def setUp(self):
|
self.application_credential
|
||||||
super().setUp()
|
|
||||||
|
|
||||||
self.roles_mock.get.return_value = fakes.FakeResource(
|
|
||||||
None,
|
|
||||||
copy.deepcopy(identity_fakes.ROLE),
|
|
||||||
loaded=True,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Get the command object to test
|
# Get the command object to test
|
||||||
@ -52,17 +73,14 @@ class TestApplicationCredentialCreate(TestApplicationCredential):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_application_credential_create_basic(self):
|
def test_application_credential_create_basic(self):
|
||||||
self.app_creds_mock.create.return_value = fakes.FakeResource(
|
name = self.application_credential.name
|
||||||
None,
|
|
||||||
copy.deepcopy(identity_fakes.APP_CRED_BASIC),
|
|
||||||
loaded=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
name = identity_fakes.app_cred_name
|
|
||||||
arglist = [name]
|
arglist = [name]
|
||||||
verifylist = [('name', identity_fakes.app_cred_name)]
|
verifylist = [('name', self.application_credential.name)]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
conn = self.app.client_manager.sdk_connection
|
||||||
|
user_id = conn.config.get_auth().get_user_id(conn.identity)
|
||||||
|
|
||||||
# In base command class ShowOne in cliff, abstract method take_action()
|
# 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
|
# returns a two-part tuple with a tuple of column names and a tuple of
|
||||||
# data to be shown.
|
# data to be shown.
|
||||||
@ -70,68 +88,45 @@ class TestApplicationCredentialCreate(TestApplicationCredential):
|
|||||||
|
|
||||||
# Set expected values
|
# Set expected values
|
||||||
kwargs = {
|
kwargs = {
|
||||||
'secret': None,
|
|
||||||
'roles': [],
|
'roles': [],
|
||||||
'expires_at': None,
|
'expires_at': None,
|
||||||
'description': None,
|
'description': None,
|
||||||
|
'secret': None,
|
||||||
'unrestricted': False,
|
'unrestricted': False,
|
||||||
'access_rules': None,
|
'access_rules': [],
|
||||||
}
|
}
|
||||||
self.app_creds_mock.create.assert_called_with(name, **kwargs)
|
self.identity_sdk_client.create_application_credential.assert_called_with(
|
||||||
|
user_id, name, **kwargs
|
||||||
|
)
|
||||||
|
|
||||||
collist = (
|
self.assertEqual(self.columns, columns)
|
||||||
'access_rules',
|
self.assertEqual(self.datalist, data)
|
||||||
'description',
|
|
||||||
'expires_at',
|
|
||||||
'id',
|
|
||||||
'name',
|
|
||||||
'project_id',
|
|
||||||
'roles',
|
|
||||||
'secret',
|
|
||||||
'unrestricted',
|
|
||||||
)
|
|
||||||
self.assertEqual(collist, columns)
|
|
||||||
datalist = (
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
identity_fakes.app_cred_id,
|
|
||||||
identity_fakes.app_cred_name,
|
|
||||||
identity_fakes.project_id,
|
|
||||||
identity_fakes.role_name,
|
|
||||||
identity_fakes.app_cred_secret,
|
|
||||||
False,
|
|
||||||
)
|
|
||||||
self.assertEqual(datalist, data)
|
|
||||||
|
|
||||||
def test_application_credential_create_with_options(self):
|
def test_application_credential_create_with_options(self):
|
||||||
name = identity_fakes.app_cred_name
|
name = self.application_credential.name
|
||||||
self.app_creds_mock.create.return_value = fakes.FakeResource(
|
|
||||||
None,
|
|
||||||
copy.deepcopy(identity_fakes.APP_CRED_OPTIONS),
|
|
||||||
loaded=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
arglist = [
|
arglist = [
|
||||||
name,
|
name,
|
||||||
'--secret',
|
'--secret',
|
||||||
'moresecuresecret',
|
'moresecuresecret',
|
||||||
'--role',
|
'--role',
|
||||||
identity_fakes.role_id,
|
self.roles.id,
|
||||||
'--expiration',
|
'--expiration',
|
||||||
identity_fakes.app_cred_expires_str,
|
'2024-01-01T00:00:00',
|
||||||
'--description',
|
'--description',
|
||||||
'credential for testing',
|
'credential for testing',
|
||||||
]
|
]
|
||||||
verifylist = [
|
verifylist = [
|
||||||
('name', identity_fakes.app_cred_name),
|
('name', self.application_credential.name),
|
||||||
('secret', 'moresecuresecret'),
|
('secret', 'moresecuresecret'),
|
||||||
('role', [identity_fakes.role_id]),
|
('role', [self.roles.id]),
|
||||||
('expiration', identity_fakes.app_cred_expires_str),
|
('expiration', '2024-01-01T00:00:00'),
|
||||||
('description', 'credential for testing'),
|
('description', 'credential for testing'),
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
conn = self.app.client_manager.sdk_connection
|
||||||
|
user_id = conn.config.get_auth().get_user_id(conn.identity)
|
||||||
|
|
||||||
# In base command class ShowOne in cliff, abstract method take_action()
|
# 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
|
# returns a two-part tuple with a tuple of column names and a tuple of
|
||||||
# data to be shown.
|
# data to be shown.
|
||||||
@ -139,172 +134,119 @@ class TestApplicationCredentialCreate(TestApplicationCredential):
|
|||||||
|
|
||||||
# Set expected values
|
# Set expected values
|
||||||
kwargs = {
|
kwargs = {
|
||||||
'secret': 'moresecuresecret',
|
'roles': [{'id': self.roles.id}],
|
||||||
'roles': [identity_fakes.role_id],
|
'expires_at': datetime.datetime(2024, 1, 1, 0, 0),
|
||||||
'expires_at': identity_fakes.app_cred_expires,
|
|
||||||
'description': 'credential for testing',
|
'description': 'credential for testing',
|
||||||
|
'secret': 'moresecuresecret',
|
||||||
'unrestricted': False,
|
'unrestricted': False,
|
||||||
'access_rules': None,
|
'access_rules': [],
|
||||||
}
|
}
|
||||||
self.app_creds_mock.create.assert_called_with(name, **kwargs)
|
self.identity_sdk_client.create_application_credential.assert_called_with(
|
||||||
|
user_id, name, **kwargs
|
||||||
|
)
|
||||||
|
|
||||||
collist = (
|
self.assertEqual(self.columns, columns)
|
||||||
'access_rules',
|
self.assertEqual(self.datalist, data)
|
||||||
'description',
|
|
||||||
'expires_at',
|
|
||||||
'id',
|
|
||||||
'name',
|
|
||||||
'project_id',
|
|
||||||
'roles',
|
|
||||||
'secret',
|
|
||||||
'unrestricted',
|
|
||||||
)
|
|
||||||
self.assertEqual(collist, columns)
|
|
||||||
datalist = (
|
|
||||||
None,
|
|
||||||
identity_fakes.app_cred_description,
|
|
||||||
identity_fakes.app_cred_expires_str,
|
|
||||||
identity_fakes.app_cred_id,
|
|
||||||
identity_fakes.app_cred_name,
|
|
||||||
identity_fakes.project_id,
|
|
||||||
identity_fakes.role_name,
|
|
||||||
identity_fakes.app_cred_secret,
|
|
||||||
False,
|
|
||||||
)
|
|
||||||
self.assertEqual(datalist, data)
|
|
||||||
|
|
||||||
def test_application_credential_create_with_access_rules_string(self):
|
def test_application_credential_create_with_access_rules_string(self):
|
||||||
name = identity_fakes.app_cred_name
|
name = self.application_credential.name
|
||||||
self.app_creds_mock.create.return_value = fakes.FakeResource(
|
|
||||||
None,
|
|
||||||
copy.deepcopy(identity_fakes.APP_CRED_ACCESS_RULES),
|
|
||||||
loaded=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
arglist = [
|
arglist = [
|
||||||
name,
|
name,
|
||||||
'--access-rules',
|
'--access-rules',
|
||||||
identity_fakes.app_cred_access_rules,
|
'[{"path": "/v2.1/servers", "method": "GET", "service": "compute"}]',
|
||||||
]
|
]
|
||||||
verifylist = [
|
verifylist = [
|
||||||
('name', identity_fakes.app_cred_name),
|
('name', self.application_credential.name),
|
||||||
('access_rules', identity_fakes.app_cred_access_rules),
|
(
|
||||||
|
'access_rules',
|
||||||
|
'[{"path": "/v2.1/servers", "method": "GET", "service": "compute"}]',
|
||||||
|
),
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
conn = self.app.client_manager.sdk_connection
|
||||||
|
user_id = conn.config.get_auth().get_user_id(conn.identity)
|
||||||
|
|
||||||
columns, data = self.cmd.take_action(parsed_args)
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
# Set expected values
|
# Set expected values
|
||||||
kwargs = {
|
kwargs = {
|
||||||
'secret': None,
|
|
||||||
'roles': [],
|
'roles': [],
|
||||||
'expires_at': None,
|
'expires_at': None,
|
||||||
'description': None,
|
'description': None,
|
||||||
|
'secret': None,
|
||||||
'unrestricted': False,
|
'unrestricted': False,
|
||||||
'access_rules': json.loads(identity_fakes.app_cred_access_rules),
|
'access_rules': [
|
||||||
|
{
|
||||||
|
"path": "/v2.1/servers",
|
||||||
|
"method": "GET",
|
||||||
|
"service": "compute",
|
||||||
|
}
|
||||||
|
],
|
||||||
}
|
}
|
||||||
self.app_creds_mock.create.assert_called_with(name, **kwargs)
|
self.identity_sdk_client.create_application_credential.assert_called_with(
|
||||||
|
user_id, name, **kwargs
|
||||||
|
)
|
||||||
|
|
||||||
collist = (
|
self.assertEqual(self.columns, columns)
|
||||||
'access_rules',
|
self.assertEqual(self.datalist, data)
|
||||||
'description',
|
|
||||||
'expires_at',
|
|
||||||
'id',
|
|
||||||
'name',
|
|
||||||
'project_id',
|
|
||||||
'roles',
|
|
||||||
'secret',
|
|
||||||
'unrestricted',
|
|
||||||
)
|
|
||||||
self.assertEqual(collist, columns)
|
|
||||||
datalist = (
|
|
||||||
identity_fakes.app_cred_access_rules,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
identity_fakes.app_cred_id,
|
|
||||||
identity_fakes.app_cred_name,
|
|
||||||
identity_fakes.project_id,
|
|
||||||
identity_fakes.role_name,
|
|
||||||
identity_fakes.app_cred_secret,
|
|
||||||
False,
|
|
||||||
)
|
|
||||||
self.assertEqual(datalist, data)
|
|
||||||
|
|
||||||
@mock.patch('openstackclient.identity.v3.application_credential.json.load')
|
@mock.patch('openstackclient.identity.v3.application_credential.json.load')
|
||||||
@mock.patch('openstackclient.identity.v3.application_credential.open')
|
@mock.patch('openstackclient.identity.v3.application_credential.open')
|
||||||
def test_application_credential_create_with_access_rules_file(
|
def test_application_credential_create_with_access_rules_file(
|
||||||
self, _, mock_json_load
|
self, _, mock_json_load
|
||||||
):
|
):
|
||||||
mock_json_load.return_value = identity_fakes.app_cred_access_rules
|
mock_json_load.return_value = '/tmp/access_rules.json'
|
||||||
|
name = self.application_credential.name
|
||||||
name = identity_fakes.app_cred_name
|
|
||||||
self.app_creds_mock.create.return_value = fakes.FakeResource(
|
|
||||||
None,
|
|
||||||
copy.deepcopy(identity_fakes.APP_CRED_ACCESS_RULES),
|
|
||||||
loaded=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
arglist = [
|
arglist = [
|
||||||
name,
|
name,
|
||||||
'--access-rules',
|
'--access-rules',
|
||||||
identity_fakes.app_cred_access_rules_path,
|
'/tmp/access_rules.json',
|
||||||
]
|
]
|
||||||
verifylist = [
|
verifylist = [
|
||||||
('name', identity_fakes.app_cred_name),
|
('name', self.application_credential.name),
|
||||||
('access_rules', identity_fakes.app_cred_access_rules_path),
|
('access_rules', '/tmp/access_rules.json'),
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
conn = self.app.client_manager.sdk_connection
|
||||||
|
user_id = conn.config.get_auth().get_user_id(conn.identity)
|
||||||
|
|
||||||
columns, data = self.cmd.take_action(parsed_args)
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
# Set expected values
|
# Set expected values
|
||||||
kwargs = {
|
kwargs = {
|
||||||
'secret': None,
|
|
||||||
'roles': [],
|
'roles': [],
|
||||||
'expires_at': None,
|
'expires_at': None,
|
||||||
'description': None,
|
'description': None,
|
||||||
|
'secret': None,
|
||||||
'unrestricted': False,
|
'unrestricted': False,
|
||||||
'access_rules': identity_fakes.app_cred_access_rules,
|
'access_rules': '/tmp/access_rules.json',
|
||||||
}
|
}
|
||||||
self.app_creds_mock.create.assert_called_with(name, **kwargs)
|
self.identity_sdk_client.create_application_credential.assert_called_with(
|
||||||
|
user_id, name, **kwargs
|
||||||
collist = (
|
|
||||||
'access_rules',
|
|
||||||
'description',
|
|
||||||
'expires_at',
|
|
||||||
'id',
|
|
||||||
'name',
|
|
||||||
'project_id',
|
|
||||||
'roles',
|
|
||||||
'secret',
|
|
||||||
'unrestricted',
|
|
||||||
)
|
)
|
||||||
self.assertEqual(collist, columns)
|
|
||||||
datalist = (
|
self.assertEqual(self.columns, columns)
|
||||||
identity_fakes.app_cred_access_rules,
|
self.assertEqual(self.datalist, data)
|
||||||
None,
|
|
||||||
None,
|
|
||||||
identity_fakes.app_cred_id,
|
|
||||||
identity_fakes.app_cred_name,
|
|
||||||
identity_fakes.project_id,
|
|
||||||
identity_fakes.role_name,
|
|
||||||
identity_fakes.app_cred_secret,
|
|
||||||
False,
|
|
||||||
)
|
|
||||||
self.assertEqual(datalist, data)
|
|
||||||
|
|
||||||
|
|
||||||
class TestApplicationCredentialDelete(TestApplicationCredential):
|
class TestApplicationCredentialDelete(identity_fakes.TestIdentityv3):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
|
|
||||||
# This is the return value for utils.find_resource()
|
self.application_credential = sdk_fakes.generate_fake_resource(
|
||||||
self.app_creds_mock.get.return_value = fakes.FakeResource(
|
resource_type=_application_credential.ApplicationCredential,
|
||||||
None,
|
roles=[],
|
||||||
copy.deepcopy(identity_fakes.APP_CRED_BASIC),
|
)
|
||||||
loaded=True,
|
self.identity_sdk_client.find_application_credential.return_value = (
|
||||||
|
self.application_credential
|
||||||
|
)
|
||||||
|
self.identity_sdk_client.delete_application_credential.return_value = (
|
||||||
|
None
|
||||||
)
|
)
|
||||||
self.app_creds_mock.delete.return_value = None
|
|
||||||
|
|
||||||
# Get the command object to test
|
# Get the command object to test
|
||||||
self.cmd = application_credential.DeleteApplicationCredential(
|
self.cmd = application_credential.DeleteApplicationCredential(
|
||||||
@ -313,26 +255,31 @@ class TestApplicationCredentialDelete(TestApplicationCredential):
|
|||||||
|
|
||||||
def test_application_credential_delete(self):
|
def test_application_credential_delete(self):
|
||||||
arglist = [
|
arglist = [
|
||||||
identity_fakes.app_cred_id,
|
self.application_credential.id,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('application_credential', [self.application_credential.id])
|
||||||
]
|
]
|
||||||
verifylist = [('application_credential', [identity_fakes.app_cred_id])]
|
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
conn = self.app.client_manager.sdk_connection
|
||||||
|
user_id = conn.config.get_auth().get_user_id(conn.identity)
|
||||||
|
|
||||||
result = self.cmd.take_action(parsed_args)
|
result = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
self.app_creds_mock.delete.assert_called_with(
|
self.identity_sdk_client.delete_application_credential.assert_called_with(
|
||||||
identity_fakes.app_cred_id,
|
user_id,
|
||||||
|
self.application_credential.id,
|
||||||
)
|
)
|
||||||
self.assertIsNone(result)
|
self.assertIsNone(result)
|
||||||
|
|
||||||
@mock.patch.object(utils, 'find_resource')
|
def test_delete_multi_app_creds_with_exception(self):
|
||||||
def test_delete_multi_app_creds_with_exception(self, find_mock):
|
self.identity_sdk_client.find_application_credential.side_effect = [
|
||||||
find_mock.side_effect = [
|
self.application_credential,
|
||||||
self.app_creds_mock.get.return_value,
|
sdk_exceptions.NotFoundException,
|
||||||
exceptions.CommandError,
|
|
||||||
]
|
]
|
||||||
arglist = [
|
arglist = [
|
||||||
identity_fakes.app_cred_id,
|
self.application_credential.id,
|
||||||
'nonexistent_app_cred',
|
'nonexistent_app_cred',
|
||||||
]
|
]
|
||||||
verifylist = [
|
verifylist = [
|
||||||
@ -340,6 +287,9 @@ class TestApplicationCredentialDelete(TestApplicationCredential):
|
|||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
conn = self.app.client_manager.sdk_connection
|
||||||
|
user_id = conn.config.get_auth().get_user_id(conn.identity)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.cmd.take_action(parsed_args)
|
self.cmd.take_action(parsed_args)
|
||||||
self.fail('CommandError should be raised.')
|
self.fail('CommandError should be raised.')
|
||||||
@ -348,27 +298,32 @@ class TestApplicationCredentialDelete(TestApplicationCredential):
|
|||||||
'1 of 2 application credentials failed to' ' delete.', str(e)
|
'1 of 2 application credentials failed to' ' delete.', str(e)
|
||||||
)
|
)
|
||||||
|
|
||||||
find_mock.assert_any_call(
|
calls = []
|
||||||
self.app_creds_mock, identity_fakes.app_cred_id
|
for a in arglist:
|
||||||
)
|
calls.append(call(user_id, a))
|
||||||
find_mock.assert_any_call(self.app_creds_mock, 'nonexistent_app_cred')
|
|
||||||
|
|
||||||
self.assertEqual(2, find_mock.call_count)
|
self.identity_sdk_client.find_application_credential.assert_has_calls(
|
||||||
self.app_creds_mock.delete.assert_called_once_with(
|
calls
|
||||||
identity_fakes.app_cred_id
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
2, self.identity_sdk_client.find_application_credential.call_count
|
||||||
|
)
|
||||||
|
self.identity_sdk_client.delete_application_credential.assert_called_once_with(
|
||||||
|
user_id, self.application_credential.id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestApplicationCredentialList(TestApplicationCredential):
|
class TestApplicationCredentialList(identity_fakes.TestIdentityv3):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
|
|
||||||
self.app_creds_mock.list.return_value = [
|
self.application_credential = sdk_fakes.generate_fake_resource(
|
||||||
fakes.FakeResource(
|
resource_type=_application_credential.ApplicationCredential,
|
||||||
None,
|
roles=[],
|
||||||
copy.deepcopy(identity_fakes.APP_CRED_BASIC),
|
)
|
||||||
loaded=True,
|
self.identity_sdk_client.application_credentials.return_value = [
|
||||||
),
|
self.application_credential
|
||||||
]
|
]
|
||||||
|
|
||||||
# Get the command object to test
|
# Get the command object to test
|
||||||
@ -381,35 +336,54 @@ class TestApplicationCredentialList(TestApplicationCredential):
|
|||||||
verifylist = []
|
verifylist = []
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
conn = self.app.client_manager.sdk_connection
|
||||||
|
user_id = conn.config.get_auth().get_user_id(conn.identity)
|
||||||
|
|
||||||
# In base command class Lister in cliff, abstract method take_action()
|
# In base command class Lister in cliff, abstract method take_action()
|
||||||
# returns a tuple containing the column names and an iterable
|
# returns a tuple containing the column names and an iterable
|
||||||
# containing the data to be listed.
|
# containing the data to be listed.
|
||||||
columns, data = self.cmd.take_action(parsed_args)
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
self.app_creds_mock.list.assert_called_with(user=None)
|
self.identity_sdk_client.application_credentials.assert_called_with(
|
||||||
|
user=user_id
|
||||||
|
)
|
||||||
|
|
||||||
collist = ('ID', 'Name', 'Project ID', 'Description', 'Expires At')
|
collist = (
|
||||||
|
'ID',
|
||||||
|
'Name',
|
||||||
|
'Description',
|
||||||
|
'Project ID',
|
||||||
|
'Roles',
|
||||||
|
'Unrestricted',
|
||||||
|
'Access Rules',
|
||||||
|
'Expires At',
|
||||||
|
)
|
||||||
self.assertEqual(collist, columns)
|
self.assertEqual(collist, columns)
|
||||||
datalist = (
|
datalist = (
|
||||||
(
|
(
|
||||||
identity_fakes.app_cred_id,
|
self.application_credential.id,
|
||||||
identity_fakes.app_cred_name,
|
self.application_credential.name,
|
||||||
identity_fakes.project_id,
|
self.application_credential.description,
|
||||||
None,
|
self.application_credential.project_id,
|
||||||
None,
|
self.application_credential.roles,
|
||||||
|
self.application_credential.unrestricted,
|
||||||
|
self.application_credential.access_rules,
|
||||||
|
self.application_credential.expires_at,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
self.assertEqual(datalist, tuple(data))
|
self.assertEqual(datalist, tuple(data))
|
||||||
|
|
||||||
|
|
||||||
class TestApplicationCredentialShow(TestApplicationCredential):
|
class TestApplicationCredentialShow(identity_fakes.TestIdentityv3):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
|
|
||||||
self.app_creds_mock.get.return_value = fakes.FakeResource(
|
self.application_credential = sdk_fakes.generate_fake_resource(
|
||||||
None,
|
resource_type=_application_credential.ApplicationCredential,
|
||||||
copy.deepcopy(identity_fakes.APP_CRED_BASIC),
|
roles=[],
|
||||||
loaded=True,
|
)
|
||||||
|
self.identity_sdk_client.find_application_credential.return_value = (
|
||||||
|
self.application_credential
|
||||||
)
|
)
|
||||||
|
|
||||||
# Get the command object to test
|
# Get the command object to test
|
||||||
@ -419,41 +393,44 @@ class TestApplicationCredentialShow(TestApplicationCredential):
|
|||||||
|
|
||||||
def test_application_credential_show(self):
|
def test_application_credential_show(self):
|
||||||
arglist = [
|
arglist = [
|
||||||
identity_fakes.app_cred_id,
|
self.application_credential.id,
|
||||||
]
|
]
|
||||||
verifylist = [
|
verifylist = [
|
||||||
('application_credential', identity_fakes.app_cred_id),
|
('application_credential', self.application_credential.id),
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
conn = self.app.client_manager.sdk_connection
|
||||||
|
user_id = conn.config.get_auth().get_user_id(conn.identity)
|
||||||
|
|
||||||
# In base command class ShowOne in cliff, abstract method take_action()
|
# 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
|
# returns a two-part tuple with a tuple of column names and a tuple of
|
||||||
# data to be shown.
|
# data to be shown.
|
||||||
columns, data = self.cmd.take_action(parsed_args)
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
self.app_creds_mock.get.assert_called_with(identity_fakes.app_cred_id)
|
self.identity_sdk_client.find_application_credential.assert_called_with(
|
||||||
|
user_id, self.application_credential.id
|
||||||
|
)
|
||||||
|
|
||||||
collist = (
|
collist = (
|
||||||
'access_rules',
|
'ID',
|
||||||
'description',
|
'Name',
|
||||||
'expires_at',
|
'Description',
|
||||||
'id',
|
'Project ID',
|
||||||
'name',
|
'Roles',
|
||||||
'project_id',
|
'Unrestricted',
|
||||||
'roles',
|
'Access Rules',
|
||||||
'secret',
|
'Expires At',
|
||||||
'unrestricted',
|
|
||||||
)
|
)
|
||||||
self.assertEqual(collist, columns)
|
self.assertEqual(collist, columns)
|
||||||
datalist = (
|
datalist = (
|
||||||
None,
|
self.application_credential.id,
|
||||||
None,
|
self.application_credential.name,
|
||||||
None,
|
self.application_credential.description,
|
||||||
identity_fakes.app_cred_id,
|
self.application_credential.project_id,
|
||||||
identity_fakes.app_cred_name,
|
self.application_credential.roles,
|
||||||
identity_fakes.project_id,
|
self.application_credential.unrestricted,
|
||||||
identity_fakes.role_name,
|
self.application_credential.access_rules,
|
||||||
identity_fakes.app_cred_secret,
|
self.application_credential.expires_at,
|
||||||
False,
|
|
||||||
)
|
)
|
||||||
self.assertEqual(datalist, data)
|
self.assertEqual(datalist, data)
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
The following commands have been migrated to SDK:
|
||||||
|
|
||||||
|
- ``application credential create``
|
||||||
|
- ``application credential delete``
|
||||||
|
- ``application credential list``
|
||||||
|
- ``application credential show``
|
Loading…
x
Reference in New Issue
Block a user